Merge "Add Low Power Standby support to NetworkPolicyManagerService"

This commit is contained in:
Robert Horvath
2022-04-11 08:48:34 +00:00
committed by Gerrit Code Review
4 changed files with 317 additions and 48 deletions

View File

@@ -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.
@@ -246,6 +249,20 @@ public class NetworkPolicyManager {
* @hide
*/
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.

View File

@@ -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);
}

View File

@@ -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) {

View File

@@ -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;
@@ -1876,56 +1881,100 @@ public class NetworkPolicyManagerServiceTest {
assertFalse(mService.isUidNetworkingBlocked(UID_E, false));
}
@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));
final Map<Pair<Integer, Integer>, Integer> effectiveBlockedReasons = new HashMap<>();
effectiveBlockedReasons.put(Pair.create(BLOCKED_REASON_NONE, ALLOWED_REASON_NONE),
BLOCKED_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(
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(BLOCKED_METERED_REASON_DATA_SAVER,
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));
ALLOWED_METERED_REASON_SYSTEM), BLOCKED_REASON_APP_STANDBY);
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,
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)