summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/net/NetworkPolicyManager.java25
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java6
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java203
-rw-r--r--services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java137
4 files changed, 320 insertions, 51 deletions
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 43ae4fc0a41b..2c2a703b16e2 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -176,6 +176,9 @@ public class NetworkPolicyManager {
public static final int FOREGROUND_THRESHOLD_STATE =
ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+ /** @hide */
+ public static final int TOP_THRESHOLD_STATE = ActivityManager.PROCESS_STATE_BOUND_TOP;
+
/**
* {@link Intent} extra that indicates which {@link NetworkTemplate} rule it
* applies to.
@@ -247,6 +250,20 @@ public class NetworkPolicyManager {
*/
public static final int ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS = 1 << 4;
/**
+ * Flag to indicate that app is exempt from certain network restrictions because of it being
+ * in the bound top or top procstate.
+ *
+ * @hide
+ */
+ public static final int ALLOWED_REASON_TOP = 1 << 5;
+ /**
+ * Flag to indicate that app is exempt from low power standby restrictions because of it being
+ * allowlisted.
+ *
+ * @hide
+ */
+ public static final int ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST = 1 << 6;
+ /**
* Flag to indicate that app is exempt from certain metered network restrictions because user
* explicitly exempted it.
*
@@ -770,6 +787,14 @@ public class NetworkPolicyManager {
|| (capability & ActivityManager.PROCESS_CAPABILITY_NETWORK) != 0;
}
+ /** @hide */
+ public static boolean isProcStateAllowedWhileInLowPowerStandby(@Nullable UidState uidState) {
+ if (uidState == null) {
+ return false;
+ }
+ return uidState.procState <= TOP_THRESHOLD_STATE;
+ }
+
/**
* Returns true if {@param procState} is considered foreground and as such will be allowed
* to access network when the device is in data saver mode. Otherwise, false.
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
index 8ef42ff97aad..3cb587812c2a 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
@@ -91,4 +91,10 @@ public abstract class NetworkPolicyManagerInternal {
*/
public abstract void setMeteredRestrictedPackagesAsync(
Set<String> packageNames, int userId);
+
+ /** Informs that Low Power Standby has become active */
+ public abstract void setLowPowerStandbyActive(boolean active);
+
+ /** Informs that the Low Power Standby allowlist has changed */
+ public abstract void setLowPowerStandbyAllowlist(int[] uids);
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 67b44696d326..ea851ba9669f 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -46,17 +46,19 @@ import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_USER_RESTRI
import static android.net.ConnectivityManager.BLOCKED_REASON_APP_STANDBY;
import static android.net.ConnectivityManager.BLOCKED_REASON_BATTERY_SAVER;
import static android.net.ConnectivityManager.BLOCKED_REASON_DOZE;
+import static android.net.ConnectivityManager.BLOCKED_REASON_LOW_POWER_STANDBY;
import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
import static android.net.ConnectivityManager.BLOCKED_REASON_RESTRICTED_MODE;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY;
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.TYPE_MOBILE;
-import static android.net.INetd.FIREWALL_CHAIN_DOZABLE;
-import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE;
-import static android.net.INetd.FIREWALL_CHAIN_RESTRICTED;
-import static android.net.INetd.FIREWALL_CHAIN_STANDBY;
import static android.net.INetd.FIREWALL_RULE_ALLOW;
import static android.net.INetd.FIREWALL_RULE_DENY;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
@@ -69,11 +71,13 @@ import static android.net.NetworkPolicyManager.ALLOWED_METERED_REASON_MASK;
import static android.net.NetworkPolicyManager.ALLOWED_METERED_REASON_SYSTEM;
import static android.net.NetworkPolicyManager.ALLOWED_METERED_REASON_USER_EXEMPTED;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_FOREGROUND;
+import static android.net.NetworkPolicyManager.ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_NONE;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_POWER_SAVE_ALLOWLIST;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_POWER_SAVE_EXCEPT_IDLE_ALLOWLIST;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_SYSTEM;
+import static android.net.NetworkPolicyManager.ALLOWED_REASON_TOP;
import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
import static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND;
@@ -87,6 +91,7 @@ import static android.net.NetworkPolicyManager.RULE_REJECT_RESTRICTED_MODE;
import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED;
import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_UNMETERED;
import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode;
+import static android.net.NetworkPolicyManager.isProcStateAllowedWhileInLowPowerStandby;
import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground;
import static android.net.NetworkPolicyManager.resolveNetworkId;
import static android.net.NetworkPolicyManager.uidPoliciesToString;
@@ -477,6 +482,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
volatile boolean mRestrictBackgroundChangedInBsm;
@GuardedBy("mUidRulesFirstLock")
volatile boolean mRestrictedNetworkingMode;
+ @GuardedBy("mUidRulesFirstLock")
+ volatile boolean mLowPowerStandbyActive;
private final boolean mSuppressDefaultPolicy;
@@ -516,6 +523,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
@GuardedBy("mUidRulesFirstLock")
final SparseIntArray mUidFirewallRestrictedModeRules = new SparseIntArray();
+ @GuardedBy("mUidRulesFirstLock")
+ final SparseIntArray mUidFirewallLowPowerStandbyModeRules = new SparseIntArray();
/** Set of states for the child firewall chains. True if the chain is active. */
@GuardedBy("mUidRulesFirstLock")
@@ -544,6 +553,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
@GuardedBy("mUidRulesFirstLock")
private final SparseBooleanArray mPowerSaveTempWhitelistAppIds = new SparseBooleanArray();
+ @GuardedBy("mUidRulesFirstLock")
+ private final SparseBooleanArray mLowPowerStandbyAllowlistUids = new SparseBooleanArray();
+
/**
* UIDs that have been allowlisted temporarily to be able to have network access despite being
* idle. Other power saving restrictions still apply.
@@ -3785,6 +3797,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
fout.print("Restrict power: "); fout.println(mRestrictPower);
fout.print("Device idle: "); fout.println(mDeviceIdleMode);
fout.print("Restricted networking mode: "); fout.println(mRestrictedNetworkingMode);
+ fout.print("Low Power Standby mode: "); fout.println(mLowPowerStandbyActive);
synchronized (mMeteredIfacesLock) {
fout.print("Metered ifaces: ");
fout.println(mMeteredIfaces);
@@ -3920,6 +3933,18 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
fout.decreaseIndent();
}
+ size = mLowPowerStandbyAllowlistUids.size();
+ if (size > 0) {
+ fout.println("Low Power Standby allowlist uids:");
+ fout.increaseIndent();
+ for (int i = 0; i < size; i++) {
+ fout.print("UID=");
+ fout.print(mLowPowerStandbyAllowlistUids.keyAt(i));
+ fout.println();
+ }
+ fout.decreaseIndent();
+ }
+
final SparseBooleanArray knownUids = new SparseBooleanArray();
collectKeys(mUidState, knownUids);
collectKeys(mUidBlockedState, knownUids);
@@ -4001,6 +4026,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
return isProcStateAllowedWhileIdleOrPowerSaveMode(uidState);
}
+ @GuardedBy("mUidRulesFirstLock")
+ private boolean isUidTop(int uid) {
+ final UidState uidState = mUidState.get(uid);
+ return isProcStateAllowedWhileInLowPowerStandby(uidState);
+ }
+
/**
* Process state of UID changed; if needed, will trigger
* {@link #updateRulesForDataUsageRestrictionsUL(int)} and
@@ -4017,8 +4048,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// state changed, push updated rules
mUidState.put(uid, newUidState);
updateRestrictBackgroundRulesOnUidStatusChangedUL(uid, oldUidState, newUidState);
- if (isProcStateAllowedWhileIdleOrPowerSaveMode(oldUidState)
- != isProcStateAllowedWhileIdleOrPowerSaveMode(newUidState)) {
+ boolean allowedWhileIdleOrPowerSaveModeChanged =
+ isProcStateAllowedWhileIdleOrPowerSaveMode(oldUidState)
+ != isProcStateAllowedWhileIdleOrPowerSaveMode(newUidState);
+ if (allowedWhileIdleOrPowerSaveModeChanged) {
updateRuleForAppIdleUL(uid);
if (mDeviceIdleMode) {
updateRuleForDeviceIdleUL(uid);
@@ -4028,6 +4061,17 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
updateRulesForPowerRestrictionsUL(uid);
}
+ if (mLowPowerStandbyActive) {
+ boolean allowedInLpsChanged =
+ isProcStateAllowedWhileInLowPowerStandby(oldUidState)
+ != isProcStateAllowedWhileInLowPowerStandby(newUidState);
+ if (allowedInLpsChanged) {
+ if (!allowedWhileIdleOrPowerSaveModeChanged) {
+ updateRulesForPowerRestrictionsUL(uid);
+ }
+ updateRuleForLowPowerStandbyUL(uid);
+ }
+ }
return true;
}
} finally {
@@ -4051,6 +4095,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
updateRuleForRestrictPowerUL(uid);
}
updateRulesForPowerRestrictionsUL(uid);
+ if (mLowPowerStandbyActive) {
+ updateRuleForLowPowerStandbyUL(uid);
+ }
return true;
}
}
@@ -4254,6 +4301,50 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
+ @GuardedBy("mUidRulesFirstLock")
+ void updateRulesForLowPowerStandbyUL() {
+ Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForLowPowerStandbyUL");
+ try {
+ if (mLowPowerStandbyActive) {
+ mUidFirewallLowPowerStandbyModeRules.clear();
+ for (int i = mUidState.size() - 1; i >= 0; i--) {
+ final int uid = mUidState.keyAt(i);
+ UidBlockedState uidBlockedState = mUidBlockedState.get(uid);
+ if (hasInternetPermissionUL(uid) && uidBlockedState != null
+ && (uidBlockedState.effectiveBlockedReasons
+ & BLOCKED_REASON_LOW_POWER_STANDBY) == 0) {
+ mUidFirewallLowPowerStandbyModeRules.put(mUidBlockedState.keyAt(i),
+ FIREWALL_RULE_ALLOW);
+ }
+ }
+ setUidFirewallRulesUL(FIREWALL_CHAIN_LOW_POWER_STANDBY,
+ mUidFirewallLowPowerStandbyModeRules, CHAIN_TOGGLE_ENABLE);
+ } else {
+ setUidFirewallRulesUL(FIREWALL_CHAIN_LOW_POWER_STANDBY, null, CHAIN_TOGGLE_DISABLE);
+ }
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
+ }
+ }
+
+ @GuardedBy("mUidRulesFirstLock")
+ void updateRuleForLowPowerStandbyUL(int uid) {
+ if (!hasInternetPermissionUL(uid)) {
+ return;
+ }
+
+ final UidBlockedState uidBlockedState = mUidBlockedState.get(uid);
+ if (mUidState.contains(uid) && uidBlockedState != null
+ && (uidBlockedState.effectiveBlockedReasons & BLOCKED_REASON_LOW_POWER_STANDBY)
+ == 0) {
+ mUidFirewallLowPowerStandbyModeRules.put(uid, FIREWALL_RULE_ALLOW);
+ setUidFirewallRuleUL(FIREWALL_CHAIN_LOW_POWER_STANDBY, uid, FIREWALL_RULE_ALLOW);
+ } else {
+ mUidFirewallLowPowerStandbyModeRules.delete(uid);
+ setUidFirewallRuleUL(FIREWALL_CHAIN_LOW_POWER_STANDBY, uid, FIREWALL_RULE_DEFAULT);
+ }
+ }
+
/**
* Returns whether a uid is allowlisted from power saving restrictions (eg: Battery Saver, Doze
* mode, and app idle).
@@ -4283,6 +4374,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
return mPowerSaveWhitelistExceptIdleAppIds.get(appId);
}
+ /**
+ * Returns whether a uid is allowlisted from low power standby restrictions.
+ */
+ @GuardedBy("mUidRulesFirstLock")
+ private boolean isAllowlistedFromLowPowerStandbyUL(int uid) {
+ return mLowPowerStandbyAllowlistUids.get(uid);
+ }
+
// NOTE: since both fw_dozable and fw_powersave uses the same map
// (mPowerSaveTempWhitelistAppIds) for allowlisting, we can reuse their logic in this method.
@GuardedBy("mUidRulesFirstLock")
@@ -4620,6 +4719,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mPowerSaveTempWhitelistAppIds.delete(uid);
mAppIdleTempWhitelistAppIds.delete(uid);
mUidFirewallRestrictedModeRules.delete(uid);
+ mUidFirewallLowPowerStandbyModeRules.delete(uid);
synchronized (mUidStateCallbackInfos) {
mUidStateCallbackInfos.remove(uid);
}
@@ -4845,6 +4945,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
final boolean isForeground = isUidForegroundOnRestrictPowerUL(uid);
+ final boolean isTop = isUidTop(uid);
final boolean isWhitelisted = isWhitelistedFromPowerSaveUL(uid, mDeviceIdleMode);
@@ -4858,17 +4959,21 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
int newAllowedReasons = ALLOWED_REASON_NONE;
newBlockedReasons |= (mRestrictPower ? BLOCKED_REASON_BATTERY_SAVER : 0);
newBlockedReasons |= (mDeviceIdleMode ? BLOCKED_REASON_DOZE : 0);
+ newBlockedReasons |= (mLowPowerStandbyActive ? BLOCKED_REASON_LOW_POWER_STANDBY : 0);
newBlockedReasons |= (isUidIdle ? BLOCKED_REASON_APP_STANDBY : 0);
newBlockedReasons |= (uidBlockedState.blockedReasons & BLOCKED_REASON_RESTRICTED_MODE);
newAllowedReasons |= (isSystem(uid) ? ALLOWED_REASON_SYSTEM : 0);
newAllowedReasons |= (isForeground ? ALLOWED_REASON_FOREGROUND : 0);
+ newAllowedReasons |= (isTop ? ALLOWED_REASON_TOP : 0);
newAllowedReasons |= (isWhitelistedFromPowerSaveUL(uid, true)
? ALLOWED_REASON_POWER_SAVE_ALLOWLIST : 0);
newAllowedReasons |= (isWhitelistedFromPowerSaveExceptIdleUL(uid)
? ALLOWED_REASON_POWER_SAVE_EXCEPT_IDLE_ALLOWLIST : 0);
newAllowedReasons |= (uidBlockedState.allowedReasons
& ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS);
+ newAllowedReasons |= (isAllowlistedFromLowPowerStandbyUL(uid))
+ ? ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST : 0;
uidBlockedState.blockedReasons = (uidBlockedState.blockedReasons
& BLOCKED_METERED_REASON_MASK) | newBlockedReasons;
@@ -4890,6 +4995,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
+ ", mRestrictPower: " + mRestrictPower
+ ", mDeviceIdleMode: " + mDeviceIdleMode
+ ", isForeground=" + isForeground
+ + ", isTop=" + isTop
+ ", isWhitelisted=" + isWhitelisted
+ ", oldUidBlockedState=" + previousUidBlockedState.toString()
+ ", newUidBlockedState=" + uidBlockedState.toString());
@@ -5421,6 +5527,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mUidFirewallPowerSaveRules.put(uid, rule);
} else if (chain == FIREWALL_CHAIN_RESTRICTED) {
mUidFirewallRestrictedModeRules.put(uid, rule);
+ } else if (chain == FIREWALL_CHAIN_LOW_POWER_STANDBY) {
+ mUidFirewallLowPowerStandbyModeRules.put(uid, rule);
}
try {
@@ -5468,6 +5576,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
.setFirewallUidRule(FIREWALL_CHAIN_POWERSAVE, uid, FIREWALL_RULE_DEFAULT);
mNetworkManager
.setFirewallUidRule(FIREWALL_CHAIN_RESTRICTED, uid, FIREWALL_RULE_DEFAULT);
+ mNetworkManager
+ .setFirewallUidRule(FIREWALL_CHAIN_LOW_POWER_STANDBY, uid,
+ FIREWALL_RULE_DEFAULT);
mNetworkManager.setUidOnMeteredNetworkAllowlist(uid, false);
mNetworkManager.setUidOnMeteredNetworkDenylist(uid, false);
} catch (IllegalStateException e) {
@@ -5747,6 +5858,67 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mHandler.obtainMessage(MSG_METERED_RESTRICTED_PACKAGES_CHANGED,
userId, 0, packageNames).sendToTarget();
}
+
+ @Override
+ public void setLowPowerStandbyActive(boolean active) {
+ Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "setLowPowerStandbyActive");
+ try {
+ synchronized (mUidRulesFirstLock) {
+ if (mLowPowerStandbyActive == active) {
+ return;
+ }
+ mLowPowerStandbyActive = active;
+ synchronized (mNetworkPoliciesSecondLock) {
+ if (!mSystemReady) return;
+ }
+
+ forEachUid("updateRulesForRestrictPower",
+ uid -> updateRulesForPowerRestrictionsUL(uid));
+ updateRulesForLowPowerStandbyUL();
+ }
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
+ }
+ }
+
+ @Override
+ public void setLowPowerStandbyAllowlist(int[] uids) {
+ synchronized (mUidRulesFirstLock) {
+ final SparseBooleanArray changedUids = new SparseBooleanArray();
+ for (int i = 0; i < mLowPowerStandbyAllowlistUids.size(); i++) {
+ final int oldUid = mLowPowerStandbyAllowlistUids.keyAt(i);
+ if (!ArrayUtils.contains(uids, oldUid)) {
+ changedUids.put(oldUid, true);
+ }
+ }
+
+ for (int i = 0; i < changedUids.size(); i++) {
+ final int deletedUid = changedUids.keyAt(i);
+ mLowPowerStandbyAllowlistUids.delete(deletedUid);
+ }
+
+ for (int newUid : uids) {
+ if (mLowPowerStandbyAllowlistUids.indexOfKey(newUid) < 0) {
+ changedUids.append(newUid, true);
+ mLowPowerStandbyAllowlistUids.append(newUid, true);
+ }
+ }
+
+ if (!mLowPowerStandbyActive) {
+ return;
+ }
+
+ synchronized (mNetworkPoliciesSecondLock) {
+ if (!mSystemReady) return;
+ }
+
+ for (int i = 0; i < changedUids.size(); i++) {
+ final int changedUid = changedUids.keyAt(i);
+ updateRulesForPowerRestrictionsUL(changedUid);
+ updateRuleForLowPowerStandbyUL(changedUid);
+ }
+ }
+ }
}
private void setMeteredRestrictedPackagesInternal(Set<String> packageNames, int userId) {
@@ -5904,6 +6076,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
effectiveBlockedReasons &= ~BLOCKED_METERED_REASON_DATA_SAVER;
effectiveBlockedReasons &= ~BLOCKED_METERED_REASON_USER_RESTRICTED;
}
+ if ((allowedReasons & ALLOWED_REASON_TOP) != 0) {
+ effectiveBlockedReasons &= ~BLOCKED_REASON_LOW_POWER_STANDBY;
+ }
if ((allowedReasons & ALLOWED_REASON_POWER_SAVE_ALLOWLIST) != 0) {
effectiveBlockedReasons &= ~BLOCKED_REASON_BATTERY_SAVER;
effectiveBlockedReasons &= ~BLOCKED_REASON_DOZE;
@@ -5919,6 +6094,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if ((allowedReasons & ALLOWED_METERED_REASON_USER_EXEMPTED) != 0) {
effectiveBlockedReasons &= ~BLOCKED_METERED_REASON_DATA_SAVER;
}
+ if ((allowedReasons & ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST) != 0) {
+ effectiveBlockedReasons &= ~BLOCKED_REASON_LOW_POWER_STANDBY;
+ }
+
return effectiveBlockedReasons;
}
@@ -5943,6 +6122,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
BLOCKED_REASON_DOZE,
BLOCKED_REASON_APP_STANDBY,
BLOCKED_REASON_RESTRICTED_MODE,
+ BLOCKED_REASON_LOW_POWER_STANDBY,
BLOCKED_METERED_REASON_DATA_SAVER,
BLOCKED_METERED_REASON_USER_RESTRICTED,
BLOCKED_METERED_REASON_ADMIN_DISABLED,
@@ -5951,9 +6131,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private static final int[] ALLOWED_REASONS = {
ALLOWED_REASON_SYSTEM,
ALLOWED_REASON_FOREGROUND,
+ ALLOWED_REASON_TOP,
ALLOWED_REASON_POWER_SAVE_ALLOWLIST,
ALLOWED_REASON_POWER_SAVE_EXCEPT_IDLE_ALLOWLIST,
ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS,
+ ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST,
ALLOWED_METERED_REASON_USER_EXEMPTED,
ALLOWED_METERED_REASON_SYSTEM,
ALLOWED_METERED_REASON_FOREGROUND,
@@ -5971,6 +6153,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
return "APP_STANDBY";
case BLOCKED_REASON_RESTRICTED_MODE:
return "RESTRICTED_MODE";
+ case BLOCKED_REASON_LOW_POWER_STANDBY:
+ return "LOW_POWER_STANDBY";
case BLOCKED_METERED_REASON_DATA_SAVER:
return "DATA_SAVER";
case BLOCKED_METERED_REASON_USER_RESTRICTED:
@@ -5991,12 +6175,16 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
return "SYSTEM";
case ALLOWED_REASON_FOREGROUND:
return "FOREGROUND";
+ case ALLOWED_REASON_TOP:
+ return "TOP";
case ALLOWED_REASON_POWER_SAVE_ALLOWLIST:
return "POWER_SAVE_ALLOWLIST";
case ALLOWED_REASON_POWER_SAVE_EXCEPT_IDLE_ALLOWLIST:
return "POWER_SAVE_EXCEPT_IDLE_ALLOWLIST";
case ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS:
return "RESTRICTED_MODE_PERMISSIONS";
+ case ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST:
+ return "LOW_POWER_STANDBY_ALLOWLIST";
case ALLOWED_METERED_REASON_USER_EXEMPTED:
return "METERED_USER_EXEMPTED";
case ALLOWED_METERED_REASON_SYSTEM:
@@ -6063,7 +6251,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
int powerBlockedReasons = BLOCKED_REASON_APP_STANDBY
| BLOCKED_REASON_DOZE
- | BLOCKED_REASON_BATTERY_SAVER;
+ | BLOCKED_REASON_BATTERY_SAVER
+ | BLOCKED_REASON_LOW_POWER_STANDBY;
if ((effectiveBlockedReasons & powerBlockedReasons) != 0) {
uidRule |= RULE_REJECT_ALL;
} else if ((blockedReasons & powerBlockedReasons) != 0) {
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index f865a50978b5..af8ac6f412f5 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -23,11 +23,13 @@ import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_USER_RESTRI
import static android.net.ConnectivityManager.BLOCKED_REASON_APP_STANDBY;
import static android.net.ConnectivityManager.BLOCKED_REASON_BATTERY_SAVER;
import static android.net.ConnectivityManager.BLOCKED_REASON_DOZE;
+import static android.net.ConnectivityManager.BLOCKED_REASON_LOW_POWER_STANDBY;
import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_WIFI;
-import static android.net.INetd.FIREWALL_CHAIN_RESTRICTED;
import static android.net.INetd.FIREWALL_RULE_ALLOW;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
@@ -38,8 +40,10 @@ import static android.net.NetworkPolicy.WARNING_DISABLED;
import static android.net.NetworkPolicyManager.ALLOWED_METERED_REASON_FOREGROUND;
import static android.net.NetworkPolicyManager.ALLOWED_METERED_REASON_SYSTEM;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_FOREGROUND;
+import static android.net.NetworkPolicyManager.ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_NONE;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_SYSTEM;
+import static android.net.NetworkPolicyManager.ALLOWED_REASON_TOP;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
import static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.POLICY_NONE;
@@ -200,6 +204,7 @@ import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
@@ -1877,55 +1882,99 @@ public class NetworkPolicyManagerServiceTest {
}
@Test
+ public void testLowPowerStandbyAllowlist() throws Exception {
+ callOnUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_TOP, 0);
+ callOnUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
+ callOnUidStateChanged(UID_C, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
+ expectHasInternetPermission(UID_A, true);
+ expectHasInternetPermission(UID_B, true);
+ expectHasInternetPermission(UID_C, true);
+
+ final NetworkPolicyManagerInternal internal = LocalServices
+ .getService(NetworkPolicyManagerInternal.class);
+
+ Map<Integer, Integer> firewallUidRules = new ArrayMap<>();
+ doAnswer(arg -> {
+ int[] uids = arg.getArgument(1);
+ int[] rules = arg.getArgument(2);
+ assertTrue(uids.length == rules.length);
+
+ for (int i = 0; i < uids.length; ++i) {
+ firewallUidRules.put(uids[i], rules[i]);
+ }
+ return null;
+ }).when(mNetworkManager).setFirewallUidRules(eq(FIREWALL_CHAIN_LOW_POWER_STANDBY),
+ any(int[].class), any(int[].class));
+
+ internal.setLowPowerStandbyAllowlist(new int[] { UID_B });
+ internal.setLowPowerStandbyActive(true);
+ assertEquals(FIREWALL_RULE_ALLOW, firewallUidRules.get(UID_A).intValue());
+ assertEquals(FIREWALL_RULE_ALLOW, firewallUidRules.get(UID_B).intValue());
+ assertFalse(mService.isUidNetworkingBlocked(UID_A, false));
+ assertFalse(mService.isUidNetworkingBlocked(UID_B, false));
+ assertTrue(mService.isUidNetworkingBlocked(UID_C, false));
+
+ internal.setLowPowerStandbyActive(false);
+ assertFalse(mService.isUidNetworkingBlocked(UID_A, false));
+ assertFalse(mService.isUidNetworkingBlocked(UID_B, false));
+ assertFalse(mService.isUidNetworkingBlocked(UID_C, false));
+ }
+
+ @Test
public void testUpdateEffectiveBlockedReasons() {
- final SparseArray<Pair<Integer, Integer>> effectiveBlockedReasons = new SparseArray<>();
- effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
- Pair.create(BLOCKED_REASON_NONE, ALLOWED_REASON_NONE));
-
- effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
- Pair.create(BLOCKED_REASON_BATTERY_SAVER, ALLOWED_REASON_SYSTEM));
- effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
- Pair.create(BLOCKED_REASON_BATTERY_SAVER | BLOCKED_REASON_DOZE,
- ALLOWED_REASON_SYSTEM));
- effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
- Pair.create(BLOCKED_METERED_REASON_DATA_SAVER,
- ALLOWED_METERED_REASON_SYSTEM));
- effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
- Pair.create(BLOCKED_METERED_REASON_DATA_SAVER
- | BLOCKED_METERED_REASON_USER_RESTRICTED,
- ALLOWED_METERED_REASON_SYSTEM));
-
- effectiveBlockedReasons.put(BLOCKED_METERED_REASON_DATA_SAVER,
+ final Map<Pair<Integer, Integer>, Integer> effectiveBlockedReasons = new HashMap<>();
+ effectiveBlockedReasons.put(Pair.create(BLOCKED_REASON_NONE, ALLOWED_REASON_NONE),
+ BLOCKED_REASON_NONE);
+
+ effectiveBlockedReasons.put(
+ Pair.create(BLOCKED_REASON_BATTERY_SAVER, ALLOWED_REASON_SYSTEM),
+ BLOCKED_REASON_NONE);
+ effectiveBlockedReasons.put(Pair.create(BLOCKED_REASON_BATTERY_SAVER | BLOCKED_REASON_DOZE,
+ ALLOWED_REASON_SYSTEM), BLOCKED_REASON_NONE);
+ effectiveBlockedReasons.put(
+ Pair.create(BLOCKED_METERED_REASON_DATA_SAVER, ALLOWED_METERED_REASON_SYSTEM),
+ BLOCKED_REASON_NONE);
+ effectiveBlockedReasons.put(Pair.create(BLOCKED_METERED_REASON_DATA_SAVER
+ | BLOCKED_METERED_REASON_USER_RESTRICTED,
+ ALLOWED_METERED_REASON_SYSTEM), BLOCKED_REASON_NONE);
+
+ effectiveBlockedReasons.put(
Pair.create(BLOCKED_REASON_BATTERY_SAVER | BLOCKED_METERED_REASON_DATA_SAVER,
- ALLOWED_REASON_SYSTEM));
- effectiveBlockedReasons.put(BLOCKED_REASON_APP_STANDBY,
+ ALLOWED_REASON_SYSTEM), BLOCKED_METERED_REASON_DATA_SAVER);
+ effectiveBlockedReasons.put(
Pair.create(BLOCKED_REASON_APP_STANDBY | BLOCKED_METERED_REASON_USER_RESTRICTED,
- ALLOWED_METERED_REASON_SYSTEM));
-
- effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
- Pair.create(BLOCKED_REASON_BATTERY_SAVER, ALLOWED_REASON_FOREGROUND));
- effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
- Pair.create(BLOCKED_REASON_BATTERY_SAVER | BLOCKED_REASON_DOZE,
- ALLOWED_REASON_FOREGROUND));
- effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
- Pair.create(BLOCKED_METERED_REASON_DATA_SAVER, ALLOWED_METERED_REASON_FOREGROUND));
- effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
- Pair.create(BLOCKED_METERED_REASON_DATA_SAVER
- | BLOCKED_METERED_REASON_USER_RESTRICTED,
- ALLOWED_METERED_REASON_FOREGROUND));
- effectiveBlockedReasons.put(BLOCKED_METERED_REASON_DATA_SAVER,
+ ALLOWED_METERED_REASON_SYSTEM), BLOCKED_REASON_APP_STANDBY);
+
+ effectiveBlockedReasons.put(
+ Pair.create(BLOCKED_REASON_BATTERY_SAVER, ALLOWED_REASON_FOREGROUND),
+ BLOCKED_REASON_NONE);
+ effectiveBlockedReasons.put(Pair.create(BLOCKED_REASON_BATTERY_SAVER | BLOCKED_REASON_DOZE,
+ ALLOWED_REASON_FOREGROUND), BLOCKED_REASON_NONE);
+ effectiveBlockedReasons.put(
+ Pair.create(BLOCKED_METERED_REASON_DATA_SAVER, ALLOWED_METERED_REASON_FOREGROUND),
+ BLOCKED_REASON_NONE);
+ effectiveBlockedReasons.put(Pair.create(BLOCKED_METERED_REASON_DATA_SAVER
+ | BLOCKED_METERED_REASON_USER_RESTRICTED,
+ ALLOWED_METERED_REASON_FOREGROUND), BLOCKED_REASON_NONE);
+ effectiveBlockedReasons.put(
Pair.create(BLOCKED_REASON_BATTERY_SAVER | BLOCKED_METERED_REASON_DATA_SAVER,
- ALLOWED_REASON_FOREGROUND));
- effectiveBlockedReasons.put(BLOCKED_REASON_BATTERY_SAVER,
- Pair.create(BLOCKED_REASON_BATTERY_SAVER
- | BLOCKED_METERED_REASON_USER_RESTRICTED,
- ALLOWED_METERED_REASON_FOREGROUND));
+ ALLOWED_REASON_FOREGROUND), BLOCKED_METERED_REASON_DATA_SAVER);
+ effectiveBlockedReasons.put(Pair.create(BLOCKED_REASON_BATTERY_SAVER
+ | BLOCKED_METERED_REASON_USER_RESTRICTED,
+ ALLOWED_METERED_REASON_FOREGROUND), BLOCKED_REASON_BATTERY_SAVER);
+
+ effectiveBlockedReasons.put(Pair.create(BLOCKED_REASON_LOW_POWER_STANDBY,
+ ALLOWED_REASON_FOREGROUND), BLOCKED_REASON_LOW_POWER_STANDBY);
+ effectiveBlockedReasons.put(Pair.create(BLOCKED_REASON_LOW_POWER_STANDBY,
+ ALLOWED_REASON_TOP), BLOCKED_REASON_NONE);
+ effectiveBlockedReasons.put(Pair.create(BLOCKED_REASON_LOW_POWER_STANDBY,
+ ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST), BLOCKED_REASON_NONE);
// TODO: test more combinations of blocked reasons.
- for (int i = 0; i < effectiveBlockedReasons.size(); ++i) {
- final int expectedEffectiveBlockedReasons = effectiveBlockedReasons.keyAt(i);
- final int blockedReasons = effectiveBlockedReasons.valueAt(i).first;
- final int allowedReasons = effectiveBlockedReasons.valueAt(i).second;
+ for (Map.Entry<Pair<Integer, Integer>, Integer> test : effectiveBlockedReasons.entrySet()) {
+ final int expectedEffectiveBlockedReasons = test.getValue();
+ final int blockedReasons = test.getKey().first;
+ final int allowedReasons = test.getKey().second;
final String errorMsg = "Expected="
+ blockedReasonsToString(expectedEffectiveBlockedReasons)
+ "; blockedReasons=" + blockedReasonsToString(blockedReasons)