Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a96eeac8 authored by Patrick Rohr's avatar Patrick Rohr Committed by Gerrit Code Review
Browse files

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
parents 1ab1849a 8591180d
Loading
Loading
Loading
Loading
+76 −33
Original line number Diff line number Diff line
@@ -149,6 +149,7 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.IConnectivityManager;
@@ -609,6 +610,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
    @GuardedBy("mUidRulesFirstLock")
    private final SparseBooleanArray mInternetPermissionMap = new SparseBooleanArray();

    private RestrictedModeObserver mRestrictedModeObserver;

    // TODO: keep allowlist of system-critical services that should never have
    // rules enforced, such as system, phone, and radio UIDs.

@@ -622,6 +625,34 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
        int COUNT = IS_UID_NETWORKING_BLOCKED + 1;
    }

    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()",
            "isUidNetworkingBlocked()",
@@ -797,9 +828,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
                    mRestrictPower = mPowerManagerInternal.getLowPowerState(
                            ServiceType.NETWORK_FIREWALL).batterySaverEnabled;

                    mRestrictedNetworkingMode = Settings.Global.getInt(
                            mContext.getContentResolver(),
                            Settings.Global.RESTRICTED_NETWORKING_MODE, 0) != 0;
                    mRestrictedModeObserver = new RestrictedModeObserver(mContext,
                            enabled -> {
                                synchronized (mUidRulesFirstLock) {
                                    mRestrictedNetworkingMode = enabled;
                                    updateRestrictedModeAllowlistUL();
                                }
                            });
                    mRestrictedNetworkingMode = mRestrictedModeObserver.isRestrictedModeEnabled();

                    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
     * 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 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.
        if (isRestrictedByAdmin) {
            newRule = RULE_REJECT_METERED;
            newUidRules |= RULE_REJECT_METERED;
        } else if (isForeground) {
            if (isDenied || (mRestrictBackground && !isAllowed)) {
                newRule = RULE_TEMPORARY_ALLOW_METERED;
                newUidRules |= RULE_TEMPORARY_ALLOW_METERED;
            } else if (isAllowed) {
                newRule = RULE_ALLOW_METERED;
                newUidRules |= RULE_ALLOW_METERED;
            }
        } else {
            if (isDenied) {
                newRule = RULE_REJECT_METERED;
                newUidRules |= RULE_REJECT_METERED;
            } else if (mRestrictBackground && isAllowed) {
                newRule = RULE_ALLOW_METERED;
                newUidRules |= RULE_ALLOW_METERED;
            }
        }
        final int newUidRules = newRule | (oldUidRules & MASK_ALL_NETWORKS);

        if (LOGV) {
            Log.v(TAG, "updateRuleForRestrictBackgroundUL(" + uid + ")"
@@ -4482,8 +4525,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
                    + ", isDenied=" + isDenied
                    + ", isAllowed=" + isAllowed
                    + ", isRestrictedByAdmin=" + isRestrictedByAdmin
                    + ", oldRule=" + uidRulesToString(oldRule)
                    + ", newRule=" + uidRulesToString(newRule)
                    + ", oldRule=" + uidRulesToString(oldUidRules & MASK_METERED_NETWORKS)
                    + ", newRule=" + uidRulesToString(newUidRules & MASK_METERED_NETWORKS)
                    + ", newUidRules=" + uidRulesToString(newUidRules)
                    + ", oldUidRules=" + uidRulesToString(oldUidRules));
        }
@@ -4495,8 +4538,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
        }

        // Second step: apply bw changes based on change of state.
        if (newRule != oldRule) {
            if (hasRule(newRule, RULE_TEMPORARY_ALLOW_METERED)) {
        if (newUidRules != oldUidRules) {
            if (hasRule(newUidRules, RULE_TEMPORARY_ALLOW_METERED)) {
                // Temporarily allow foreground app, removing from denylist if necessary
                // (since bw_penalty_box prevails over bw_happy_box).

@@ -4507,7 +4550,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
                if (isDenied) {
                    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.

                // 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) {
                    setMeteredNetworkDenylist(uid, true);
                }
            } else if (hasRule(newRule, RULE_REJECT_METERED)
                    || hasRule(oldRule, RULE_REJECT_METERED)) {
            } else if (hasRule(newUidRules, RULE_REJECT_METERED)
                    || hasRule(oldUidRules, RULE_REJECT_METERED)) {
                // Flip state because app was explicitly added or removed to denylist.
                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
                    // 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.
                    setMeteredNetworkAllowlist(uid, isAllowed);
                }
            } else if (hasRule(newRule, RULE_ALLOW_METERED)
                    || hasRule(oldRule, RULE_ALLOW_METERED)) {
            } else if (hasRule(newUidRules, RULE_ALLOW_METERED)
                    || hasRule(oldUidRules, RULE_ALLOW_METERED)) {
                // Flip state because app was explicitly added or removed to allowlist.
                setMeteredNetworkAllowlist(uid, isAllowed);
            } else {
@@ -4617,8 +4660,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
        final boolean isForeground = isUidForegroundOnRestrictPowerUL(uid);

        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.

@@ -4626,14 +4670,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
        // by considering the foreground and non-foreground states.
        if (isForeground) {
            if (restrictMode) {
                newRule = RULE_ALLOW_ALL;
                newUidRules |= RULE_ALLOW_ALL;
            }
        } 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) {
            Log.v(TAG, "updateRulesForPowerRestrictionsUL(" + uid + ")"
                    + ", isIdle: " + isUidIdle
@@ -4641,17 +4683,18 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
                    + ", mDeviceIdleMode: " + mDeviceIdleMode
                    + ", isForeground=" + isForeground
                    + ", isWhitelisted=" + isWhitelisted
                    + ", oldRule=" + uidRulesToString(oldRule)
                    + ", newRule=" + uidRulesToString(newRule)
                    + ", oldRule=" + uidRulesToString(oldUidRules & MASK_ALL_NETWORKS)
                    + ", newRule=" + uidRulesToString(newUidRules & MASK_ALL_NETWORKS)
                    + ", newUidRules=" + uidRulesToString(newUidRules)
                    + ", oldUidRules=" + uidRulesToString(oldUidRules));
        }

        // Second step: notify listeners if state changed.
        if (newRule != oldRule) {
            if (newRule == RULE_NONE || hasRule(newRule, RULE_ALLOW_ALL)) {
        if (newUidRules != oldUidRules) {
            if ((newUidRules & MASK_ALL_NETWORKS) == RULE_NONE || hasRule(newUidRules,
                    RULE_ALLOW_ALL)) {
                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);
            } else {
                // All scenarios should have been covered above
+9 −0
Original line number Diff line number Diff line
@@ -119,6 +119,8 @@ class NetworkPolicyManagerShellCommand extends ShellCommand {
        switch(type) {
            case "restrict-background":
                return getRestrictBackground();
            case "restricted-mode":
                return getRestrictedModeState();
        }
        pw.println("Error: unknown get type '" + type + "'");
        return -1;
@@ -255,6 +257,13 @@ class NetworkPolicyManagerShellCommand extends ShellCommand {
        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 {
        final PrintWriter pw = getOutPrintWriter();
        pw.print("Restrict background status: ");