|
|
@ -729,14 +729,14 @@ public class Helper {
|
|
|
|
boolean metered = prefs.getBoolean("metered", true);
|
|
|
|
boolean metered = prefs.getBoolean("metered", true);
|
|
|
|
|
|
|
|
|
|
|
|
NetworkState state = new NetworkState();
|
|
|
|
NetworkState state = new NetworkState();
|
|
|
|
Boolean isMetered = isMetered(context, false);
|
|
|
|
Boolean isMetered = isMetered(context);
|
|
|
|
state.connected = (isMetered != null);
|
|
|
|
state.connected = (isMetered != null);
|
|
|
|
state.unmetered = (isMetered != null && !isMetered);
|
|
|
|
state.unmetered = (isMetered != null && !isMetered);
|
|
|
|
state.suitable = (isMetered != null && (metered || !isMetered));
|
|
|
|
state.suitable = (isMetered != null && (metered || !isMetered));
|
|
|
|
return state;
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static Boolean isMetered(Context context, boolean log) {
|
|
|
|
private static Boolean isMetered(Context context) {
|
|
|
|
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
|
|
|
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
|
|
|
|
|
|
|
|
|
|
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
|
|
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
|
|
@ -748,45 +748,38 @@ public class Helper {
|
|
|
|
|
|
|
|
|
|
|
|
Network active = cm.getActiveNetwork();
|
|
|
|
Network active = cm.getActiveNetwork();
|
|
|
|
if (active == null) {
|
|
|
|
if (active == null) {
|
|
|
|
if (log)
|
|
|
|
Log.i("isMetered: no active network");
|
|
|
|
EntityLog.log(context, "isMetered: no active network");
|
|
|
|
|
|
|
|
return null;
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NetworkCapabilities caps = cm.getNetworkCapabilities(active);
|
|
|
|
NetworkCapabilities caps = cm.getNetworkCapabilities(active);
|
|
|
|
if (caps == null) {
|
|
|
|
if (caps == null) {
|
|
|
|
if (log)
|
|
|
|
Log.i("isMetered: active no caps");
|
|
|
|
EntityLog.log(context, "isMetered: active no caps");
|
|
|
|
|
|
|
|
return null; // network unknown
|
|
|
|
return null; // network unknown
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (log)
|
|
|
|
Log.i("isMetered: active caps=" + caps);
|
|
|
|
EntityLog.log(context, "isMetered: active caps=" + caps);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) &&
|
|
|
|
if (caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) &&
|
|
|
|
!caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
|
|
|
|
!caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
|
|
|
|
if (log)
|
|
|
|
Log.i("isMetered: no internet");
|
|
|
|
EntityLog.log(context, "isMetered: no internet");
|
|
|
|
|
|
|
|
return null;
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)) {
|
|
|
|
if (!caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)) {
|
|
|
|
if (log)
|
|
|
|
Log.i("isMetered: active restricted");
|
|
|
|
EntityLog.log(context, "isMetered: active restricted");
|
|
|
|
|
|
|
|
return null;
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P &&
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P &&
|
|
|
|
!caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOREGROUND)) {
|
|
|
|
!caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOREGROUND)) {
|
|
|
|
if (log)
|
|
|
|
Log.i("isMetered: active background");
|
|
|
|
EntityLog.log(context, "isMetered: active background");
|
|
|
|
|
|
|
|
return null;
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)) {
|
|
|
|
if (caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)) {
|
|
|
|
boolean unmetered = caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
|
|
|
|
boolean unmetered = caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
|
|
|
|
if (log)
|
|
|
|
Log.i("isMetered: active not VPN unmetered=" + unmetered);
|
|
|
|
EntityLog.log(context, "isMetered: active not VPN unmetered=" + unmetered);
|
|
|
|
|
|
|
|
return !unmetered;
|
|
|
|
return !unmetered;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -798,54 +791,46 @@ public class Helper {
|
|
|
|
for (Network network : networks) {
|
|
|
|
for (Network network : networks) {
|
|
|
|
caps = cm.getNetworkCapabilities(network);
|
|
|
|
caps = cm.getNetworkCapabilities(network);
|
|
|
|
if (caps == null) {
|
|
|
|
if (caps == null) {
|
|
|
|
if (log)
|
|
|
|
Log.i("isMetered: no underlying caps");
|
|
|
|
EntityLog.log(context, "isMetered: no underlying caps");
|
|
|
|
|
|
|
|
continue; // network unknown
|
|
|
|
continue; // network unknown
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (log)
|
|
|
|
Log.i("isMetered: underlying caps=" + caps);
|
|
|
|
Log.i("isMetered: underlying caps=" + caps);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
|
|
|
|
if (!caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
|
|
|
|
if (log)
|
|
|
|
Log.i("isMetered: underlying no internet");
|
|
|
|
EntityLog.log(context, "isMetered: underlying no internet");
|
|
|
|
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)) {
|
|
|
|
if (!caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)) {
|
|
|
|
if (log)
|
|
|
|
Log.i("isMetered: underlying restricted");
|
|
|
|
EntityLog.log(context, "isMetered: underlying restricted");
|
|
|
|
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P &&
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P &&
|
|
|
|
!caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOREGROUND)) {
|
|
|
|
!caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOREGROUND)) {
|
|
|
|
if (log)
|
|
|
|
Log.i("isMetered: underlying background");
|
|
|
|
EntityLog.log(context, "isMetered: underlying background");
|
|
|
|
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)) {
|
|
|
|
if (caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)) {
|
|
|
|
underlying = true;
|
|
|
|
underlying = true;
|
|
|
|
if (log)
|
|
|
|
Log.i("isMetered: underlying is connected");
|
|
|
|
Log.i("isMetered: underlying is connected");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)) {
|
|
|
|
if (caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)) {
|
|
|
|
if (log)
|
|
|
|
Log.i("isMetered: underlying is unmetered");
|
|
|
|
EntityLog.log(context, "isMetered: underlying is unmetered");
|
|
|
|
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!underlying) {
|
|
|
|
if (!underlying) {
|
|
|
|
EntityLog.log(context, "isMetered: no underlying network");
|
|
|
|
Log.i("isMetered: no underlying network");
|
|
|
|
return null;
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (log)
|
|
|
|
|
|
|
|
EntityLog.log(context, "isMetered: underlying assume metered");
|
|
|
|
|
|
|
|
// Assume metered
|
|
|
|
// Assume metered
|
|
|
|
|
|
|
|
Log.i("isMetered: underlying assume metered");
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|