Created new public API so applications can customize its metered network
usage while running in background.
The new API is 'int getRestrictBackgroundStatus()' and returns the
following values:
- RESTRICT_BACKGROUND_STATUS_DISABLED: no restrictions
- RESTRICT_BACKGROUND_STATUS_WHITELISTED: restriction but app is
whitelisted
- RESTRICT_BACKGROUND_STATUS_ENABLED: full restriction
The proper way to interprete these values for using metered networks
while running on background is:
- When disabled, there is no restriction and the application could use the
metered networks freely.
- When whitelisted, the application can use the metered network, but should try
to minimize the usage.
- When enabled, the application should not try to use metered networks at
all, since the usage will be denied.
BUG: 26451391
Change-Id: If07d42bb88e4c02802df0234861f38aef2cfead7
diff --git a/api/current.txt b/api/current.txt
index e50eba1..99195ba 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -22760,6 +22760,7 @@
method public android.net.NetworkInfo getNetworkInfo(android.net.Network);
method public deprecated int getNetworkPreference();
method public static deprecated android.net.Network getProcessDefaultNetwork();
+ method public int getRestrictBackgroundStatus();
method public boolean isActiveNetworkMetered();
method public boolean isDefaultNetworkActive();
method public static deprecated boolean isNetworkTypeValid(int);
@@ -22794,6 +22795,9 @@
field public static final java.lang.String EXTRA_NO_CONNECTIVITY = "noConnectivity";
field public static final java.lang.String EXTRA_OTHER_NETWORK_INFO = "otherNetwork";
field public static final java.lang.String EXTRA_REASON = "reason";
+ field public static final int RESTRICT_BACKGROUND_STATUS_DISABLED = 1; // 0x1
+ field public static final int RESTRICT_BACKGROUND_STATUS_ENABLED = 3; // 0x3
+ field public static final int RESTRICT_BACKGROUND_STATUS_WHITELISTED = 2; // 0x2
field public static final int TYPE_BLUETOOTH = 7; // 0x7
field public static final int TYPE_DUMMY = 8; // 0x8
field public static final int TYPE_ETHERNET = 9; // 0x9
@@ -22820,6 +22824,9 @@
method public abstract void onNetworkActive();
}
+ public static abstract class ConnectivityManager.RestrictBackgroundStatus implements java.lang.annotation.Annotation {
+ }
+
public class Credentials {
ctor public Credentials(int, int, int);
method public int getGid();
diff --git a/api/system-current.txt b/api/system-current.txt
index 2d358bf..abdf680 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -24348,6 +24348,7 @@
method public android.net.NetworkInfo getNetworkInfo(android.net.Network);
method public deprecated int getNetworkPreference();
method public static deprecated android.net.Network getProcessDefaultNetwork();
+ method public int getRestrictBackgroundStatus();
method public boolean isActiveNetworkMetered();
method public boolean isDefaultNetworkActive();
method public static deprecated boolean isNetworkTypeValid(int);
@@ -24382,6 +24383,9 @@
field public static final java.lang.String EXTRA_NO_CONNECTIVITY = "noConnectivity";
field public static final java.lang.String EXTRA_OTHER_NETWORK_INFO = "otherNetwork";
field public static final java.lang.String EXTRA_REASON = "reason";
+ field public static final int RESTRICT_BACKGROUND_STATUS_DISABLED = 1; // 0x1
+ field public static final int RESTRICT_BACKGROUND_STATUS_ENABLED = 3; // 0x3
+ field public static final int RESTRICT_BACKGROUND_STATUS_WHITELISTED = 2; // 0x2
field public static final int TYPE_BLUETOOTH = 7; // 0x7
field public static final int TYPE_DUMMY = 8; // 0x8
field public static final int TYPE_ETHERNET = 9; // 0x9
@@ -24408,6 +24412,9 @@
method public abstract void onNetworkActive();
}
+ public static abstract class ConnectivityManager.RestrictBackgroundStatus implements java.lang.annotation.Annotation {
+ }
+
public class Credentials {
ctor public Credentials(int, int, int);
method public int getGid();
diff --git a/api/test-current.txt b/api/test-current.txt
index bcdf5c1..7c96799 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -22768,6 +22768,7 @@
method public android.net.NetworkInfo getNetworkInfo(android.net.Network);
method public deprecated int getNetworkPreference();
method public static deprecated android.net.Network getProcessDefaultNetwork();
+ method public int getRestrictBackgroundStatus();
method public boolean isActiveNetworkMetered();
method public boolean isDefaultNetworkActive();
method public static deprecated boolean isNetworkTypeValid(int);
@@ -22802,6 +22803,9 @@
field public static final java.lang.String EXTRA_NO_CONNECTIVITY = "noConnectivity";
field public static final java.lang.String EXTRA_OTHER_NETWORK_INFO = "otherNetwork";
field public static final java.lang.String EXTRA_REASON = "reason";
+ field public static final int RESTRICT_BACKGROUND_STATUS_DISABLED = 1; // 0x1
+ field public static final int RESTRICT_BACKGROUND_STATUS_ENABLED = 3; // 0x3
+ field public static final int RESTRICT_BACKGROUND_STATUS_WHITELISTED = 2; // 0x2
field public static final int TYPE_BLUETOOTH = 7; // 0x7
field public static final int TYPE_DUMMY = 8; // 0x8
field public static final int TYPE_ETHERNET = 9; // 0x9
@@ -22828,6 +22832,9 @@
method public abstract void onNetworkActive();
}
+ public static abstract class ConnectivityManager.RestrictBackgroundStatus implements java.lang.annotation.Annotation {
+ }
+
public class Credentials {
ctor public Credentials(int, int, int);
method public int getGid();
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index c4f0847..5584cde 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -16,7 +16,7 @@
package android.net;
import static com.android.internal.util.Preconditions.checkNotNull;
-
+import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
@@ -49,6 +49,8 @@
import libcore.net.event.NetworkEventDispatcher;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicInteger;
@@ -512,6 +514,7 @@
private final Context mContext;
private INetworkManagementService mNMService;
+ private INetworkPolicyManager mNPManager;
/**
* Tests if a given integer represents a valid network type.
@@ -3025,4 +3028,58 @@
return NetworkUtils.bindProcessToNetworkForHostResolution(
network == null ? NETID_UNSET : network.netId);
}
+
+ /**
+ * Device is not restricting metered network activity while application is running on
+ * background.
+ */
+ public static final int RESTRICT_BACKGROUND_STATUS_DISABLED = 1;
+
+ /**
+ * Device is restricting metered network activity while application is running on background,
+ * but application is allowed to bypass it.
+ * <p>
+ * In this state, application should take action to mitigate metered network access.
+ * For example, a music streaming application should switch to a low-bandwidth bitrate.
+ */
+ public static final int RESTRICT_BACKGROUND_STATUS_WHITELISTED = 2;
+
+ /**
+ * Device is restricting metered network activity while application is running on background.
+ * In this state, application should not try to use the network while running on background,
+ * because it would be denied.
+ */
+ public static final int RESTRICT_BACKGROUND_STATUS_ENABLED = 3;
+
+ @IntDef(flag = false, value = {
+ RESTRICT_BACKGROUND_STATUS_DISABLED,
+ RESTRICT_BACKGROUND_STATUS_WHITELISTED,
+ RESTRICT_BACKGROUND_STATUS_ENABLED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface RestrictBackgroundStatus {
+ }
+
+ private INetworkPolicyManager getNetworkPolicyManager() {
+ synchronized (this) {
+ if (mNPManager != null) {
+ return mNPManager;
+ }
+ mNPManager = INetworkPolicyManager.Stub.asInterface(ServiceManager
+ .getService(Context.NETWORK_POLICY_SERVICE));
+ return mNPManager;
+ }
+ }
+
+ /**
+ * Determines if the calling application is subject to metered network restrictions while
+ * running on background.
+ */
+ public @RestrictBackgroundStatus int getRestrictBackgroundStatus() {
+ try {
+ return getNetworkPolicyManager().getRestrictBackgroundByCaller();
+ } catch (RemoteException e) {
+ return RESTRICT_BACKGROUND_STATUS_DISABLED;
+ }
+ }
}
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 06aa616..a57fac3 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -56,6 +56,12 @@
void addRestrictBackgroundWhitelistedUid(int uid);
void removeRestrictBackgroundWhitelistedUid(int uid);
int[] getRestrictBackgroundWhitelistedUids();
+ /** Gets the restrict background status based on the caller's UID:
+ 1 - disabled
+ 2 - whitelisted
+ 3 - enabled
+ */
+ int getRestrictBackgroundByCaller();
void setDeviceIdleMode(boolean enabled);
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 38ebc80..2658489 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -31,6 +31,9 @@
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_WIMAX;
+import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED;
+import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
+import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED;
import static android.net.ConnectivityManager.isNetworkTypeMobile;
import static android.net.NetworkPolicy.CYCLE_NONE;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
@@ -1873,6 +1876,20 @@
}
@Override
+ public int getRestrictBackgroundByCaller() {
+ mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
+ final int uid = Binder.getCallingUid();
+ synchronized (mRulesLock) {
+ if (!mRestrictBackground) {
+ return RESTRICT_BACKGROUND_STATUS_DISABLED;
+ }
+ return mRestrictBackgroundWhitelistUids.get(uid)
+ ? RESTRICT_BACKGROUND_STATUS_WHITELISTED
+ : RESTRICT_BACKGROUND_STATUS_ENABLED;
+ }
+ }
+
+ @Override
public boolean getRestrictBackground() {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);