Merge changes from topic "restricted-mode-cts"

* changes:
  Prevent clearing Restricted Mode uid state when other rules change
  Add shell command to query Restricted Mode state
  Add Restricted Mode settings observer to NetworkPolicyManagerService
This commit is contained in:
Patrick Rohr
2021-01-12 17:41:19 +00:00
committed by Gerrit Code Review
2 changed files with 85 additions and 33 deletions

View File

@@ -149,6 +149,7 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo; import android.content.pm.UserInfo;
import android.content.res.Resources; import android.content.res.Resources;
import android.database.ContentObserver;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback; import android.net.ConnectivityManager.NetworkCallback;
import android.net.IConnectivityManager; import android.net.IConnectivityManager;
@@ -609,6 +610,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
@GuardedBy("mUidRulesFirstLock") @GuardedBy("mUidRulesFirstLock")
private final SparseBooleanArray mInternetPermissionMap = new SparseBooleanArray(); private final SparseBooleanArray mInternetPermissionMap = new SparseBooleanArray();
private RestrictedModeObserver mRestrictedModeObserver;
// TODO: keep allowlist of system-critical services that should never have // TODO: keep allowlist of system-critical services that should never have
// rules enforced, such as system, phone, and radio UIDs. // rules enforced, such as system, phone, and radio UIDs.
@@ -622,7 +625,35 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
int COUNT = IS_UID_NETWORKING_BLOCKED + 1; int COUNT = IS_UID_NETWORKING_BLOCKED + 1;
} }
public final StatLogger mStatLogger = new StatLogger(new String[] { private static class RestrictedModeObserver extends ContentObserver {
private final Context mContext;
private final RestrictedModeListener mListener;
RestrictedModeObserver(Context ctx, RestrictedModeListener listener) {
super(null);
mContext = ctx;
mListener = listener;
mContext.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.RESTRICTED_NETWORKING_MODE), false,
this);
}
public boolean isRestrictedModeEnabled() {
return Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.RESTRICTED_NETWORKING_MODE, 0) != 0;
}
@Override
public void onChange(boolean selfChange) {
mListener.onChange(isRestrictedModeEnabled());
}
public interface RestrictedModeListener {
void onChange(boolean enabled);
}
}
public final StatLogger mStatLogger = new StatLogger(new String[]{
"updateNetworkEnabledNL()", "updateNetworkEnabledNL()",
"isUidNetworkingBlocked()", "isUidNetworkingBlocked()",
}); });
@@ -797,9 +828,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mRestrictPower = mPowerManagerInternal.getLowPowerState( mRestrictPower = mPowerManagerInternal.getLowPowerState(
ServiceType.NETWORK_FIREWALL).batterySaverEnabled; ServiceType.NETWORK_FIREWALL).batterySaverEnabled;
mRestrictedNetworkingMode = Settings.Global.getInt( mRestrictedModeObserver = new RestrictedModeObserver(mContext,
mContext.getContentResolver(), enabled -> {
Settings.Global.RESTRICTED_NETWORKING_MODE, 0) != 0; synchronized (mUidRulesFirstLock) {
mRestrictedNetworkingMode = enabled;
updateRestrictedModeAllowlistUL();
}
});
mRestrictedNetworkingMode = mRestrictedModeObserver.isRestrictedModeEnabled();
mSystemReady = true; mSystemReady = true;
@@ -3828,6 +3864,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
} }
} }
@VisibleForTesting
boolean isRestrictedModeEnabled() {
synchronized (mUidRulesFirstLock) {
return mRestrictedNetworkingMode;
}
}
/** /**
* updates restricted mode state / access for all apps * updates restricted mode state / access for all apps
* Called on initialization and when restricted mode is enabled / disabled. * Called on initialization and when restricted mode is enabled / disabled.
@@ -4455,26 +4498,26 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final boolean isDenied = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0; final boolean isDenied = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
final boolean isAllowed = (uidPolicy & POLICY_ALLOW_METERED_BACKGROUND) != 0; final boolean isAllowed = (uidPolicy & POLICY_ALLOW_METERED_BACKGROUND) != 0;
final int oldRule = oldUidRules & MASK_METERED_NETWORKS;
int newRule = RULE_NONE; // copy oldUidRules and clear out METERED_NETWORKS rules.
int newUidRules = oldUidRules & (~MASK_METERED_NETWORKS);
// First step: define the new rule based on user restrictions and foreground state. // First step: define the new rule based on user restrictions and foreground state.
if (isRestrictedByAdmin) { if (isRestrictedByAdmin) {
newRule = RULE_REJECT_METERED; newUidRules |= RULE_REJECT_METERED;
} else if (isForeground) { } else if (isForeground) {
if (isDenied || (mRestrictBackground && !isAllowed)) { if (isDenied || (mRestrictBackground && !isAllowed)) {
newRule = RULE_TEMPORARY_ALLOW_METERED; newUidRules |= RULE_TEMPORARY_ALLOW_METERED;
} else if (isAllowed) { } else if (isAllowed) {
newRule = RULE_ALLOW_METERED; newUidRules |= RULE_ALLOW_METERED;
} }
} else { } else {
if (isDenied) { if (isDenied) {
newRule = RULE_REJECT_METERED; newUidRules |= RULE_REJECT_METERED;
} else if (mRestrictBackground && isAllowed) { } else if (mRestrictBackground && isAllowed) {
newRule = RULE_ALLOW_METERED; newUidRules |= RULE_ALLOW_METERED;
} }
} }
final int newUidRules = newRule | (oldUidRules & MASK_ALL_NETWORKS);
if (LOGV) { if (LOGV) {
Log.v(TAG, "updateRuleForRestrictBackgroundUL(" + uid + ")" Log.v(TAG, "updateRuleForRestrictBackgroundUL(" + uid + ")"
@@ -4482,8 +4525,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
+ ", isDenied=" + isDenied + ", isDenied=" + isDenied
+ ", isAllowed=" + isAllowed + ", isAllowed=" + isAllowed
+ ", isRestrictedByAdmin=" + isRestrictedByAdmin + ", isRestrictedByAdmin=" + isRestrictedByAdmin
+ ", oldRule=" + uidRulesToString(oldRule) + ", oldRule=" + uidRulesToString(oldUidRules & MASK_METERED_NETWORKS)
+ ", newRule=" + uidRulesToString(newRule) + ", newRule=" + uidRulesToString(newUidRules & MASK_METERED_NETWORKS)
+ ", newUidRules=" + uidRulesToString(newUidRules) + ", newUidRules=" + uidRulesToString(newUidRules)
+ ", oldUidRules=" + uidRulesToString(oldUidRules)); + ", oldUidRules=" + uidRulesToString(oldUidRules));
} }
@@ -4495,8 +4538,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
} }
// Second step: apply bw changes based on change of state. // Second step: apply bw changes based on change of state.
if (newRule != oldRule) { if (newUidRules != oldUidRules) {
if (hasRule(newRule, RULE_TEMPORARY_ALLOW_METERED)) { if (hasRule(newUidRules, RULE_TEMPORARY_ALLOW_METERED)) {
// Temporarily allow foreground app, removing from denylist if necessary // Temporarily allow foreground app, removing from denylist if necessary
// (since bw_penalty_box prevails over bw_happy_box). // (since bw_penalty_box prevails over bw_happy_box).
@@ -4507,7 +4550,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (isDenied) { if (isDenied) {
setMeteredNetworkDenylist(uid, false); setMeteredNetworkDenylist(uid, false);
} }
} else if (hasRule(oldRule, RULE_TEMPORARY_ALLOW_METERED)) { } else if (hasRule(oldUidRules, RULE_TEMPORARY_ALLOW_METERED)) {
// Remove temporary exemption from app that is not on foreground anymore. // Remove temporary exemption from app that is not on foreground anymore.
// TODO: if statements below are used to avoid unnecessary calls to netd / iptables, // TODO: if statements below are used to avoid unnecessary calls to netd / iptables,
@@ -4520,18 +4563,18 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (isDenied || isRestrictedByAdmin) { if (isDenied || isRestrictedByAdmin) {
setMeteredNetworkDenylist(uid, true); setMeteredNetworkDenylist(uid, true);
} }
} else if (hasRule(newRule, RULE_REJECT_METERED) } else if (hasRule(newUidRules, RULE_REJECT_METERED)
|| hasRule(oldRule, RULE_REJECT_METERED)) { || hasRule(oldUidRules, RULE_REJECT_METERED)) {
// Flip state because app was explicitly added or removed to denylist. // Flip state because app was explicitly added or removed to denylist.
setMeteredNetworkDenylist(uid, (isDenied || isRestrictedByAdmin)); setMeteredNetworkDenylist(uid, (isDenied || isRestrictedByAdmin));
if (hasRule(oldRule, RULE_REJECT_METERED) && isAllowed) { if (hasRule(oldUidRules, RULE_REJECT_METERED) && isAllowed) {
// Since denial prevails over allowance, we need to handle the special case // Since denial prevails over allowance, we need to handle the special case
// where app is allowed and denied at the same time (although such // where app is allowed and denied at the same time (although such
// scenario should be blocked by the UI), then it is removed from the denylist. // scenario should be blocked by the UI), then it is removed from the denylist.
setMeteredNetworkAllowlist(uid, isAllowed); setMeteredNetworkAllowlist(uid, isAllowed);
} }
} else if (hasRule(newRule, RULE_ALLOW_METERED) } else if (hasRule(newUidRules, RULE_ALLOW_METERED)
|| hasRule(oldRule, RULE_ALLOW_METERED)) { || hasRule(oldUidRules, RULE_ALLOW_METERED)) {
// Flip state because app was explicitly added or removed to allowlist. // Flip state because app was explicitly added or removed to allowlist.
setMeteredNetworkAllowlist(uid, isAllowed); setMeteredNetworkAllowlist(uid, isAllowed);
} else { } else {
@@ -4617,8 +4660,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final boolean isForeground = isUidForegroundOnRestrictPowerUL(uid); final boolean isForeground = isUidForegroundOnRestrictPowerUL(uid);
final boolean isWhitelisted = isWhitelistedFromPowerSaveUL(uid, mDeviceIdleMode); final boolean isWhitelisted = isWhitelistedFromPowerSaveUL(uid, mDeviceIdleMode);
final int oldRule = oldUidRules & MASK_ALL_NETWORKS;
int newRule = RULE_NONE; // Copy existing uid rules and clear ALL_NETWORK rules.
int newUidRules = oldUidRules & (~MASK_ALL_NETWORKS);
// First step: define the new rule based on user restrictions and foreground state. // First step: define the new rule based on user restrictions and foreground state.
@@ -4626,14 +4670,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// by considering the foreground and non-foreground states. // by considering the foreground and non-foreground states.
if (isForeground) { if (isForeground) {
if (restrictMode) { if (restrictMode) {
newRule = RULE_ALLOW_ALL; newUidRules |= RULE_ALLOW_ALL;
} }
} else if (restrictMode) { } else if (restrictMode) {
newRule = isWhitelisted ? RULE_ALLOW_ALL : RULE_REJECT_ALL; newUidRules |= isWhitelisted ? RULE_ALLOW_ALL : RULE_REJECT_ALL;
} }
final int newUidRules = (oldUidRules & MASK_METERED_NETWORKS) | newRule;
if (LOGV) { if (LOGV) {
Log.v(TAG, "updateRulesForPowerRestrictionsUL(" + uid + ")" Log.v(TAG, "updateRulesForPowerRestrictionsUL(" + uid + ")"
+ ", isIdle: " + isUidIdle + ", isIdle: " + isUidIdle
@@ -4641,17 +4683,18 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
+ ", mDeviceIdleMode: " + mDeviceIdleMode + ", mDeviceIdleMode: " + mDeviceIdleMode
+ ", isForeground=" + isForeground + ", isForeground=" + isForeground
+ ", isWhitelisted=" + isWhitelisted + ", isWhitelisted=" + isWhitelisted
+ ", oldRule=" + uidRulesToString(oldRule) + ", oldRule=" + uidRulesToString(oldUidRules & MASK_ALL_NETWORKS)
+ ", newRule=" + uidRulesToString(newRule) + ", newRule=" + uidRulesToString(newUidRules & MASK_ALL_NETWORKS)
+ ", newUidRules=" + uidRulesToString(newUidRules) + ", newUidRules=" + uidRulesToString(newUidRules)
+ ", oldUidRules=" + uidRulesToString(oldUidRules)); + ", oldUidRules=" + uidRulesToString(oldUidRules));
} }
// Second step: notify listeners if state changed. // Second step: notify listeners if state changed.
if (newRule != oldRule) { if (newUidRules != oldUidRules) {
if (newRule == RULE_NONE || hasRule(newRule, RULE_ALLOW_ALL)) { if ((newUidRules & MASK_ALL_NETWORKS) == RULE_NONE || hasRule(newUidRules,
RULE_ALLOW_ALL)) {
if (LOGV) Log.v(TAG, "Allowing non-metered access for UID " + uid); if (LOGV) Log.v(TAG, "Allowing non-metered access for UID " + uid);
} else if (hasRule(newRule, RULE_REJECT_ALL)) { } else if (hasRule(newUidRules, RULE_REJECT_ALL)) {
if (LOGV) Log.v(TAG, "Rejecting non-metered access for UID " + uid); if (LOGV) Log.v(TAG, "Rejecting non-metered access for UID " + uid);
} else { } else {
// All scenarios should have been covered above // All scenarios should have been covered above

View File

@@ -119,6 +119,8 @@ class NetworkPolicyManagerShellCommand extends ShellCommand {
switch(type) { switch(type) {
case "restrict-background": case "restrict-background":
return getRestrictBackground(); return getRestrictBackground();
case "restricted-mode":
return getRestrictedModeState();
} }
pw.println("Error: unknown get type '" + type + "'"); pw.println("Error: unknown get type '" + type + "'");
return -1; return -1;
@@ -255,6 +257,13 @@ class NetworkPolicyManagerShellCommand extends ShellCommand {
return listUidList("App Idle whitelisted UIDs", uids); return listUidList("App Idle whitelisted UIDs", uids);
} }
private int getRestrictedModeState() {
final PrintWriter pw = getOutPrintWriter();
pw.print("Restricted mode status: ");
pw.println(mInterface.isRestrictedModeEnabled() ? "enabled" : "disabled");
return 0;
}
private int getRestrictBackground() throws RemoteException { private int getRestrictBackground() throws RemoteException {
final PrintWriter pw = getOutPrintWriter(); final PrintWriter pw = getOutPrintWriter();
pw.print("Restrict background status: "); pw.print("Restrict background status: ");