diff --git a/api/current.txt b/api/current.txt index e764994a3f256..e0b92f4039b5f 100644 --- a/api/current.txt +++ b/api/current.txt @@ -22761,6 +22761,7 @@ package android.net { 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); @@ -22795,6 +22796,9 @@ package android.net { 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 @@ -22821,6 +22825,9 @@ package android.net { 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 4bd5db571ca90..6b84f5672608d 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -24349,6 +24349,7 @@ package android.net { 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); @@ -24383,6 +24384,9 @@ package android.net { 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 @@ -24409,6 +24413,9 @@ package android.net { 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 d446c4b257cae..f0038758ae708 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -22769,6 +22769,7 @@ package android.net { 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); @@ -22803,6 +22804,9 @@ package android.net { 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 @@ -22829,6 +22833,9 @@ package android.net { 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 c4f0847e694bc..5584cde2aa6c4 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 com.android.internal.util.Protocol; 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 @@ public class ConnectivityManager { private final Context mContext; private INetworkManagementService mNMService; + private INetworkPolicyManager mNPManager; /** * Tests if a given integer represents a valid network type. @@ -3025,4 +3028,58 @@ public class ConnectivityManager { 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. + *
+ * 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 06aa616b93172..a57fac3afe6cd 100644 --- a/core/java/android/net/INetworkPolicyManager.aidl +++ b/core/java/android/net/INetworkPolicyManager.aidl @@ -56,6 +56,12 @@ interface INetworkPolicyManager { 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 38ebc8003bc71..26584896460ec 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.content.Intent.EXTRA_UID; 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; @@ -1872,6 +1875,20 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + @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);