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

Commit 46b451fa authored by Felipe Leme's avatar Felipe Leme
Browse files

Refactored whitelist restrict background uids.

On Android N, the list of UIDs whitelisted was kept in a separate array
and XML tag, while in reality it should be a new UID
policy (POLICY_ALLOW_METERED_BACKGROUND).

This change refactors NetworkPolicyManagerService to use the new UID
policy, although without removing any of its existing methods (but
marking them as deprecated).

Test: m -j32 FrameworksServicesTests && adb install -r -g ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk && adb shell am instrument -e class "com.android.server.NetworkPolicyManagerServiceTest" -w "com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner"

Test: cts-tradefed run commandAndExit cts --skip-device-info --skip-system-status-check com.android.compatibility.common.tradefed.targetprep.NetworkConnectivityChecker --skip-preconditions -m CtsHostsideNetworkTests --abi armeabi-v7a -t com.android.cts.net.HostsideRestrictBackgroundNetworkTests

BUG: 28791717

Change-Id: I39869efda554ca0b736dd2380e439474f91dfbe6
parent 8546a444
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -41,11 +41,13 @@ import java.util.TimeZone;
 */
public class NetworkPolicyManager {

    /* POLICY_* are masks and can be ORed */
    /* POLICY_* are masks and can be ORed, although currently they are not.*/
    /** No specific network policy, use system default. */
    public static final int POLICY_NONE = 0x0;
    /** Reject network usage on metered networks when application in background. */
    public static final int POLICY_REJECT_METERED_BACKGROUND = 0x1;
    /** Allow metered network use in the background even when in data usage save mode. */
    public static final int POLICY_ALLOW_METERED_BACKGROUND = 0x4;

    /*
     * Rules defining whether an uid has access to a network given its type (metered / non-metered).
+3 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ package android.net;

import static android.net.NetworkPolicyManager.MASK_ALL_NETWORKS;
import static android.net.NetworkPolicyManager.MASK_METERED_NETWORKS;
import static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
@@ -78,6 +79,8 @@ public class NetworkPolicyManagerTest {
        uidPoliciesToStringTest(POLICY_NONE, "0 (NONE)");
        uidPoliciesToStringTest(POLICY_REJECT_METERED_BACKGROUND,
                "1 (REJECT_METERED_BACKGROUND)");
        uidPoliciesToStringTest(POLICY_ALLOW_METERED_BACKGROUND,
                "4 (ALLOW_BACKGROUND_BATTERY_SAVE)");
    }

    private void uidPoliciesToStringTest(int policyRules, String... expectedOptions) {
+77 −52
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY;
import static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
@@ -356,12 +357,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
    @GuardedBy("mUidRulesFirstLock")
    private final SparseBooleanArray mPowerSaveTempWhitelistAppIds = new SparseBooleanArray();

    /**
     * UIDs that have been white-listed to avoid restricted background.
     */
    @GuardedBy("mUidRulesFirstLock")
    private final SparseBooleanArray mRestrictBackgroundWhitelistUids = new SparseBooleanArray();

    /**
     * UIDs that have been initially white-listed by system to avoid restricted background.
     */
@@ -486,7 +481,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
     * Whitelists pre-defined apps for restrict background, but only if the user didn't already
     * revoke the whitelist.
     *
     * @return whether any uid has been added to {@link #mRestrictBackgroundWhitelistUids}.
     * @return whether any uid has been whitelisted.
     */
    boolean addDefaultRestrictBackgroundWhitelistUidsUL() {
        final List<UserInfo> users = mUserManager.getUsers();
@@ -531,7 +526,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
            if (!mRestrictBackgroundWhitelistRevokedUids.get(uid)) {
                Slog.i(TAG, "adding default package " + pkg + " (uid " + uid + " for user "
                        + userId + ") to restrict background whitelist");
                mRestrictBackgroundWhitelistUids.append(uid, true);
                setUidPolicyUncheckedUL(uid, POLICY_ALLOW_METERED_BACKGROUND, false);
                changed = true;
            }
        }
@@ -1460,6 +1455,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
            final XmlPullParser in = Xml.newPullParser();
            in.setInput(fis, StandardCharsets.UTF_8.name());

             // Must save the <restrict-background> tags and convert them to <uid-policy> later,
             // to skip UIDs that were explicitly blacklisted.
            final SparseBooleanArray whitelistedRestrictBackground = new SparseBooleanArray();

            int type;
            int version = VERSION_INIT;
            boolean insideWhitelist = false;
@@ -1568,7 +1567,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
                        insideWhitelist = true;
                    } else if (TAG_RESTRICT_BACKGROUND.equals(tag) && insideWhitelist) {
                        final int uid = readIntAttribute(in, ATTR_UID);
                        mRestrictBackgroundWhitelistUids.put(uid, true);
                        whitelistedRestrictBackground.append(uid, true);
                    } else if (TAG_REVOKED_RESTRICT_BACKGROUND.equals(tag) && insideWhitelist) {
                        final int uid = readIntAttribute(in, ATTR_UID);
                        mRestrictBackgroundWhitelistRevokedUids.put(uid, true);
@@ -1581,6 +1580,25 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
                }
            }

            final int size = whitelistedRestrictBackground.size();
            for (int i = 0; i < size; i++) {
                final int uid = whitelistedRestrictBackground.keyAt(i);
                final int policy = mUidPolicy.get(uid, POLICY_NONE);
                if ((policy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
                    Slog.w(TAG, "ignoring restrict-background-whitelist for " + uid
                            + " because its policy is " + uidPoliciesToString(policy));
                    continue;
                }
                if (UserHandle.isApp(uid)) {
                    final int newPolicy = policy | POLICY_ALLOW_METERED_BACKGROUND;
                    if (LOGV)
                        Log.v(TAG, "new policy for " + uid + ": " + uidPoliciesToString(newPolicy));
                    setUidPolicyUncheckedUL(uid, newPolicy, false);
                } else {
                    Slog.w(TAG, "unable to update policy on UID " + uid);
                }
            }

        } catch (FileNotFoundException e) {
            // missing policy is okay, probably first boot
            upgradeLegacyBackgroundDataUL();
@@ -1670,17 +1688,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
            // write all whitelists
            out.startTag(null, TAG_WHITELIST);

            // restrict background whitelist
            int size = mRestrictBackgroundWhitelistUids.size();
            for (int i = 0; i < size; i++) {
                final int uid = mRestrictBackgroundWhitelistUids.keyAt(i);
                out.startTag(null, TAG_RESTRICT_BACKGROUND);
                writeIntAttribute(out, ATTR_UID, uid);
                out.endTag(null, TAG_RESTRICT_BACKGROUND);
            }

            // revoked restrict background whitelist
            size = mRestrictBackgroundWhitelistRevokedUids.size();
            int size = mRestrictBackgroundWhitelistRevokedUids.size();
            for (int i = 0; i < size; i++) {
                final int uid = mRestrictBackgroundWhitelistRevokedUids.keyAt(i);
                out.startTag(null, TAG_REVOKED_RESTRICT_BACKGROUND);
@@ -1817,22 +1826,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
        if (LOGV) Slog.v(TAG, "removeUserStateUL()");
        boolean changed = false;

        // Remove entries from restricted background UID whitelist
        int[] wlUids = new int[0];
        for (int i = 0; i < mRestrictBackgroundWhitelistUids.size(); i++) {
            final int uid = mRestrictBackgroundWhitelistUids.keyAt(i);
            if (UserHandle.getUserId(uid) == userId) {
                wlUids = appendInt(wlUids, uid);
            }
        }

        if (wlUids.length > 0) {
            for (int uid : wlUids) {
                removeRestrictBackgroundWhitelistedUidUL(uid, false, false);
            }
            changed = true;
        }

        // Remove entries from revoked default restricted background UID whitelist
        for (int i = mRestrictBackgroundWhitelistRevokedUids.size() - 1; i >= 0; i--) {
            final int uid = mRestrictBackgroundWhitelistRevokedUids.keyAt(i);
@@ -2068,21 +2061,26 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
        }
    }

    /**
     * @deprecated - should use {@link #setUidPolicy(int, int)} directly.
     */
    @Override
    @Deprecated
    public void addRestrictBackgroundWhitelistedUid(int uid) {
        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
        final boolean oldStatus;
        final boolean needFirewallRules;
        int changed;
        synchronized (mUidRulesFirstLock) {
            oldStatus = mRestrictBackgroundWhitelistUids.get(uid);
            final int oldUidPolicy = mUidPolicy.get(uid, POLICY_NONE);
            oldStatus = (oldUidPolicy & POLICY_ALLOW_METERED_BACKGROUND) != 0;
            if (oldStatus) {
                if (LOGD) Slog.d(TAG, "uid " + uid + " is already whitelisted");
                return;
            }
            needFirewallRules = isUidValidForWhitelistRules(uid);
            Slog.i(TAG, "adding uid " + uid + " to restrict background whitelist");
            mRestrictBackgroundWhitelistUids.append(uid, true);
            setUidPolicyUncheckedUL(uid, oldUidPolicy, POLICY_ALLOW_METERED_BACKGROUND, false);
            if (mDefaultRestrictBackgroundWhitelistUids.get(uid)
                    && mRestrictBackgroundWhitelistRevokedUids.get(uid)) {
                if (LOGD) Slog.d(TAG, "Removing uid " + uid
@@ -2103,7 +2101,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
                Boolean.TRUE).sendToTarget();
    }

    /**
     * @deprecated - should use {@link #setUidPolicy(int, int)} directly.
     */
    @Override
    @Deprecated
    public void removeRestrictBackgroundWhitelistedUid(int uid) {
        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
        final boolean changed;
@@ -2120,7 +2122,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
     */
    private boolean removeRestrictBackgroundWhitelistedUidUL(int uid, boolean uidDeleted,
            boolean updateNow) {
        final boolean oldStatus = mRestrictBackgroundWhitelistUids.get(uid);
        final boolean oldStatus =
                (mUidPolicy.get(uid, POLICY_NONE) & POLICY_ALLOW_METERED_BACKGROUND) != 0;
        if (!oldStatus && !uidDeleted) {
            if (LOGD) Slog.d(TAG, "uid " + uid + " was not whitelisted before");
            return false;
@@ -2128,7 +2131,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
        final boolean needFirewallRules = uidDeleted || isUidValidForWhitelistRules(uid);
        if (oldStatus) {
            Slog.i(TAG, "removing uid " + uid + " from restrict background whitelist");
            mRestrictBackgroundWhitelistUids.delete(uid);
            mUidPolicy.delete(uid);
        }
        if (mDefaultRestrictBackgroundWhitelistUids.get(uid)
                && !mRestrictBackgroundWhitelistRevokedUids.get(uid)) {
@@ -2151,22 +2154,42 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
        return mRestrictBackground && needFirewallRules;
    }

    /**
     * @deprecated - should use {@link #getUidsWithPolicy(int)} instead, but first need to change
     * that method to use logical OR (|).
     */
    @Override
    @Deprecated
    public int[] getRestrictBackgroundWhitelistedUids() {
        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
        int[] whitelist = null;
        synchronized (mUidRulesFirstLock) {
            final int size = mRestrictBackgroundWhitelistUids.size();
            final int[] whitelist = new int[size];
            for (int i = 0; i < size; i++) {
                whitelist[i] = mRestrictBackgroundWhitelistUids.keyAt(i);
            // First calculate size
            int size = 0;
            int policySize = mUidPolicy.size();
            for (int i = 0; i < policySize; i++) {
                if ((mUidPolicy.valueAt(i) & POLICY_ALLOW_METERED_BACKGROUND) != 0) {
                    size ++;
                }
            }
            whitelist = new int[size];
            // Then populate it.
            if (size > 0) {
                int index = 0;
                for (int i = 0; i < policySize; i++) {
                    final int uid = mUidPolicy.keyAt(i);
                    if ((mUidPolicy.valueAt(i) & POLICY_ALLOW_METERED_BACKGROUND) != 0) {
                        whitelist[index++] = uid;
                    }
                }
            }
        }
        if (LOGV) {
            Slog.v(TAG, "getRestrictBackgroundWhitelistedUids(): "
                        + mRestrictBackgroundWhitelistUids);
                    + Arrays.toString(whitelist));
        }
        return whitelist;
    }
    }

    @Override
    public int getRestrictBackgroundByCaller() {
@@ -2189,7 +2212,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
            if (!mRestrictBackground) {
                return RESTRICT_BACKGROUND_STATUS_DISABLED;
            }
            return mRestrictBackgroundWhitelistUids.get(uid)
            return (mUidPolicy.get(uid) & POLICY_ALLOW_METERED_BACKGROUND) != 0
                    ? RESTRICT_BACKGROUND_STATUS_WHITELISTED
                    : RESTRICT_BACKGROUND_STATUS_ENABLED;
        }
@@ -2385,13 +2408,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
                    fout.decreaseIndent();
                }

                size = mRestrictBackgroundWhitelistUids.size();
                final int[] restrictBackgroundWhitelistUids =
                        getRestrictBackgroundWhitelistedUids();
                size = restrictBackgroundWhitelistUids.length;
                if (size > 0) {
                    fout.println("Restrict background whitelist uids:");
                    fout.increaseIndent();
                    for (int i = 0; i < size; i++) {
                        fout.print("UID=");
                        fout.print(mRestrictBackgroundWhitelistUids.keyAt(i));
                        fout.print(restrictBackgroundWhitelistUids[i]);
                        fout.println();
                    }
                    fout.decreaseIndent();
@@ -2915,7 +2940,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
        final boolean isForeground = isUidForegroundOnRestrictBackgroundUL(uid);

        final boolean isBlacklisted = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
        final boolean isWhitelisted = mRestrictBackgroundWhitelistUids.get(uid);
        final boolean isWhitelisted = (uidPolicy & POLICY_ALLOW_METERED_BACKGROUND) != 0;
        final int oldRule = oldUidRules & MASK_METERED_NETWORKS;
        int newRule = RULE_NONE;

+13 −0
Original line number Diff line number Diff line
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<whitelist>
  <restrict-background uid="10004" />
  <restrict-background uid="10008" />
  <restrict-background uid="10015" />
  <restrict-background uid="10016" />
</whitelist>
<policy-list version="10">
  <uid-policy uid="10004" policy="0" />
  <uid-policy uid="10008" policy="1" />
  <uid-policy uid="10015" policy="2" />
  <uid-policy uid="10016" policy="4" />
</policy-list>
+9 −0
Original line number Diff line number Diff line
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<policy-list version="10">
  <uid-policy uid="10004" policy="4" />
  <uid-policy uid="10008" policy="4" />
  <uid-policy uid="10015" policy="4" />
  <uid-policy uid="10016" policy="0" />
  <uid-policy uid="10023" policy="1" />
  <uid-policy uid="10042" policy="2" />
</policy-list>
Loading