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

Commit 4dc30852 authored by Suprabh Shukla's avatar Suprabh Shukla Committed by Gerrit Code Review
Browse files

Merge "Filter out uninteresting UidObserver callbacks in NPMS" into main

parents c70419af 75215f12
Loading
Loading
Loading
Loading
+58 −9
Original line number Original line Diff line number Diff line
@@ -26,6 +26,8 @@ import static android.Manifest.permission.NETWORK_STACK;
import static android.Manifest.permission.OBSERVE_NETWORK_POLICY;
import static android.Manifest.permission.OBSERVE_NETWORK_POLICY;
import static android.Manifest.permission.READ_PHONE_STATE;
import static android.Manifest.permission.READ_PHONE_STATE;
import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;
import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;
import static android.app.ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
import static android.app.ActivityManager.PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK;
import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
import static android.app.ActivityManager.isProcStateConsideredInteraction;
import static android.app.ActivityManager.isProcStateConsideredInteraction;
import static android.app.ActivityManager.printCapabilitiesSummary;
import static android.app.ActivityManager.printCapabilitiesSummary;
@@ -85,8 +87,10 @@ import static android.net.NetworkPolicyManager.ALLOWED_REASON_POWER_SAVE_EXCEPT_
import static android.net.NetworkPolicyManager.ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS;
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_SYSTEM;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_TOP;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_TOP;
import static android.net.NetworkPolicyManager.BACKGROUND_THRESHOLD_STATE;
import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
import static android.net.NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE;
import static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
@@ -97,6 +101,7 @@ import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
import static android.net.NetworkPolicyManager.RULE_REJECT_RESTRICTED_MODE;
import static android.net.NetworkPolicyManager.RULE_REJECT_RESTRICTED_MODE;
import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED;
import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED;
import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_UNMETERED;
import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_UNMETERED;
import static android.net.NetworkPolicyManager.TOP_THRESHOLD_STATE;
import static android.net.NetworkPolicyManager.allowedReasonsToString;
import static android.net.NetworkPolicyManager.allowedReasonsToString;
import static android.net.NetworkPolicyManager.blockedReasonsToString;
import static android.net.NetworkPolicyManager.blockedReasonsToString;
import static android.net.NetworkPolicyManager.isProcStateAllowedNetworkWhileBackground;
import static android.net.NetworkPolicyManager.isProcStateAllowedNetworkWhileBackground;
@@ -468,7 +473,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
     */
     */
    private static final int MSG_PROCESS_BACKGROUND_TRANSITIONING_UIDS = 24;
    private static final int MSG_PROCESS_BACKGROUND_TRANSITIONING_UIDS = 24;


    private static final int UID_MSG_STATE_CHANGED = 100;
    @VisibleForTesting
    static final int UID_MSG_STATE_CHANGED = 100;
    private static final int UID_MSG_GONE = 101;
    private static final int UID_MSG_GONE = 101;


    private static final String PROP_SUB_PLAN_OWNER = "persist.sys.sub_plan_owner";
    private static final String PROP_SUB_PLAN_OWNER = "persist.sys.sub_plan_owner";
@@ -1074,8 +1080,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {


                final int cutpoint = mBackgroundNetworkRestricted ? PROCESS_STATE_UNKNOWN
                final int cutpoint = mBackgroundNetworkRestricted ? PROCESS_STATE_UNKNOWN
                        : NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE;
                        : NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE;
                // TODO (b/319728914): Filter out the unnecessary changes when using no cutpoint.

                mActivityManagerInternal.registerNetworkPolicyUidObserver(mUidObserver, changes,
                mActivityManagerInternal.registerNetworkPolicyUidObserver(mUidObserver, changes,
                        cutpoint, "android");
                        cutpoint, "android");
                mNetworkManager.registerObserver(mAlertObserver);
                mNetworkManager.registerObserver(mAlertObserver);
@@ -1184,6 +1188,51 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
    }
    }


    final private IUidObserver mUidObserver = new UidObserver() {
    final private IUidObserver mUidObserver = new UidObserver() {

        /**
         * Returns whether the uid state change information is relevant for the service. If the
         * state information does not lead to any change in the network rules, it can safely be
         * ignored.
         */
        @GuardedBy("mUidStateCallbackInfos")
        private boolean isUidStateChangeRelevant(UidStateCallbackInfo previousInfo,
                int newProcState, long newProcStateSeq, int newCapability) {
            if (previousInfo.procStateSeq == -1) {
                // No previous record. Always process the first state change callback.
                return true;
            }
            if (newProcStateSeq <= previousInfo.procStateSeq) {
                // Stale callback. Ignore.
                return false;
            }
            final int previousProcState = previousInfo.procState;
            if (mBackgroundNetworkRestricted && (previousProcState >= BACKGROUND_THRESHOLD_STATE)
                    != (newProcState >= BACKGROUND_THRESHOLD_STATE)) {
                // Proc-state change crossed BACKGROUND_THRESHOLD_STATE: Network rules for the
                // BACKGROUND chain may change.
                return true;
            }
            if ((previousProcState <= TOP_THRESHOLD_STATE)
                    != (newProcState <= TOP_THRESHOLD_STATE)) {
                // Proc-state change crossed TOP_THRESHOLD_STATE: Network rules for the
                // LOW_POWER_STANDBY chain may change.
                return true;
            }
            if ((previousProcState <= FOREGROUND_THRESHOLD_STATE)
                    != (newProcState <= FOREGROUND_THRESHOLD_STATE)) {
                // Proc-state change crossed FOREGROUND_THRESHOLD_STATE: Network rules for many
                // different chains may change.
                return true;
            }
            final int networkCapabilities = PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK
                    | PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK;
            if ((previousInfo.capability & networkCapabilities)
                    != (newCapability & networkCapabilities)) {
                return true;
            }
            return false;
        }

        @Override public void onUidStateChanged(int uid, int procState, long procStateSeq,
        @Override public void onUidStateChanged(int uid, int procState, long procStateSeq,
                @ProcessCapability int capability) {
                @ProcessCapability int capability) {
            synchronized (mUidStateCallbackInfos) {
            synchronized (mUidStateCallbackInfos) {
@@ -1192,9 +1241,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
                    callbackInfo = new UidStateCallbackInfo();
                    callbackInfo = new UidStateCallbackInfo();
                    mUidStateCallbackInfos.put(uid, callbackInfo);
                    mUidStateCallbackInfos.put(uid, callbackInfo);
                }
                }
                if (callbackInfo.procStateSeq == -1 || procStateSeq > callbackInfo.procStateSeq) {
                if (isUidStateChangeRelevant(callbackInfo, procState, procStateSeq, capability)) {
                    callbackInfo.update(uid, procState, procStateSeq, capability);
                    callbackInfo.update(uid, procState, procStateSeq, capability);
                }
                    if (!callbackInfo.isPending) {
                    if (!callbackInfo.isPending) {
                        mUidEventHandler.obtainMessage(UID_MSG_STATE_CHANGED, callbackInfo)
                        mUidEventHandler.obtainMessage(UID_MSG_STATE_CHANGED, callbackInfo)
                                .sendToTarget();
                                .sendToTarget();
@@ -1202,6 +1250,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
                    }
                    }
                }
                }
            }
            }
        }


        @Override public void onUidGone(int uid, boolean disabled) {
        @Override public void onUidGone(int uid, boolean disabled) {
            mUidEventHandler.obtainMessage(UID_MSG_GONE, uid, 0).sendToTarget();
            mUidEventHandler.obtainMessage(UID_MSG_GONE, uid, 0).sendToTarget();
+121 −15
Original line number Original line Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.net;


import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
import static android.Manifest.permission.NETWORK_STACK;
import static android.Manifest.permission.NETWORK_STACK;
import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
import static android.app.ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
import static android.app.ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
import static android.app.ActivityManager.PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK;
import static android.app.ActivityManager.PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK;
@@ -58,9 +59,11 @@ import static android.net.NetworkPolicyManager.ALLOWED_REASON_SYSTEM;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_TOP;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_TOP;
import static android.net.NetworkPolicyManager.BACKGROUND_THRESHOLD_STATE;
import static android.net.NetworkPolicyManager.BACKGROUND_THRESHOLD_STATE;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
import static android.net.NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE;
import static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.TOP_THRESHOLD_STATE;
import static android.net.NetworkPolicyManager.allowedReasonsToString;
import static android.net.NetworkPolicyManager.allowedReasonsToString;
import static android.net.NetworkPolicyManager.blockedReasonsToString;
import static android.net.NetworkPolicyManager.blockedReasonsToString;
import static android.net.NetworkPolicyManager.uidPoliciesToString;
import static android.net.NetworkPolicyManager.uidPoliciesToString;
@@ -88,6 +91,7 @@ import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT_SNOOZED;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT_SNOOZED;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_RAPID;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_RAPID;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_WARNING;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_WARNING;
import static com.android.server.net.NetworkPolicyManagerService.UID_MSG_STATE_CHANGED;
import static com.android.server.net.NetworkPolicyManagerService.UidBlockedState.getEffectiveBlockedReasons;
import static com.android.server.net.NetworkPolicyManagerService.UidBlockedState.getEffectiveBlockedReasons;
import static com.android.server.net.NetworkPolicyManagerService.normalizeTemplate;
import static com.android.server.net.NetworkPolicyManagerService.normalizeTemplate;


@@ -196,8 +200,6 @@ import com.android.server.LocalServices;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.usage.AppStandbyInternal;
import com.android.server.usage.AppStandbyInternal;


import com.google.common.util.concurrent.AbstractFuture;

import libcore.io.Streams;
import libcore.io.Streams;


import org.junit.After;
import org.junit.After;
@@ -241,10 +243,8 @@ import java.util.Map;
import java.util.Set;
import java.util.Set;
import java.util.TimeZone;
import java.util.TimeZone;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Collectors;


@@ -2246,6 +2246,123 @@ public class NetworkPolicyManagerServiceTest {
        assertTrue(mService.isUidNetworkingBlocked(UID_A, false));
        assertTrue(mService.isUidNetworkingBlocked(UID_A, false));
    }
    }


    @Test
    @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
    public void testUidObserverFiltersProcStateChanges() throws Exception {
        int testProcStateSeq = 0;
        try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
            // First callback for uid.
            callOnUidStatechanged(UID_A, BACKGROUND_THRESHOLD_STATE + 1, testProcStateSeq++,
                    PROCESS_CAPABILITY_NONE);
            assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
        }
        waitForUidEventHandlerIdle();
        try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
            // Doesn't cross the background threshold.
            callOnUidStatechanged(UID_A, BACKGROUND_THRESHOLD_STATE, testProcStateSeq++,
                    PROCESS_CAPABILITY_NONE);
            assertFalse(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
        }
        waitForUidEventHandlerIdle();
        try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
            // Crosses the background threshold.
            callOnUidStatechanged(UID_A, BACKGROUND_THRESHOLD_STATE - 1, testProcStateSeq++,
                    PROCESS_CAPABILITY_NONE);
            assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
        }
        waitForUidEventHandlerIdle();
        try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
            // Doesn't cross the foreground threshold.
            callOnUidStatechanged(UID_A, FOREGROUND_THRESHOLD_STATE + 1, testProcStateSeq++,
                    PROCESS_CAPABILITY_NONE);
            assertFalse(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
        }
        waitForUidEventHandlerIdle();
        try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
            // Crosses the foreground threshold.
            callOnUidStatechanged(UID_A, FOREGROUND_THRESHOLD_STATE, testProcStateSeq++,
                    PROCESS_CAPABILITY_NONE);
            assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
        }
        waitForUidEventHandlerIdle();
        try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
            // Doesn't cross the top threshold.
            callOnUidStatechanged(UID_A, TOP_THRESHOLD_STATE + 1, testProcStateSeq++,
                    PROCESS_CAPABILITY_NONE);
            assertFalse(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
        }
        waitForUidEventHandlerIdle();
        try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
            // Crosses the top threshold.
            callOnUidStatechanged(UID_A, TOP_THRESHOLD_STATE, testProcStateSeq++,
                    PROCESS_CAPABILITY_NONE);
            assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
        }
        waitForUidEventHandlerIdle();
        try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
            // Doesn't cross any other threshold.
            callOnUidStatechanged(UID_A, TOP_THRESHOLD_STATE - 1, testProcStateSeq++,
                    PROCESS_CAPABILITY_NONE);
            assertFalse(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
        }
        waitForUidEventHandlerIdle();
    }

    @Test
    @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
    public void testUidObserverFiltersStaleChanges() throws Exception {
        final int testProcStateSeq = 51;
        try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
            // First callback for uid.
            callOnUidStatechanged(UID_B, BACKGROUND_THRESHOLD_STATE + 100, testProcStateSeq,
                    PROCESS_CAPABILITY_NONE);
            assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
        }
        waitForUidEventHandlerIdle();
        try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
            // Stale callback because the procStateSeq is smaller.
            callOnUidStatechanged(UID_B, BACKGROUND_THRESHOLD_STATE - 100, testProcStateSeq - 10,
                    PROCESS_CAPABILITY_NONE);
            assertFalse(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
        }
        waitForUidEventHandlerIdle();
    }

    @Test
    @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
    public void testUidObserverFiltersCapabilityChanges() throws Exception {
        int testProcStateSeq = 0;
        try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
            // First callback for uid.
            callOnUidStatechanged(UID_A, TOP_THRESHOLD_STATE, testProcStateSeq++,
                    PROCESS_CAPABILITY_NONE);
            assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
        }
        waitForUidEventHandlerIdle();
        try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
            // The same process-state with one network capability added.
            callOnUidStatechanged(UID_A, TOP_THRESHOLD_STATE, testProcStateSeq++,
                    PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK);
            assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
        }
        waitForUidEventHandlerIdle();
        try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
            // The same process-state with another network capability added.
            callOnUidStatechanged(UID_A, TOP_THRESHOLD_STATE, testProcStateSeq++,
                    PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK
                            | PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK);
            assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
        }
        waitForUidEventHandlerIdle();
        try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
            // The same process-state with all capabilities, but no change in network capabilities.
            callOnUidStatechanged(UID_A, TOP_THRESHOLD_STATE, testProcStateSeq++,
                    PROCESS_CAPABILITY_ALL);
            assertFalse(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
        }
        waitForUidEventHandlerIdle();
    }

    @Test
    @Test
    public void testLowPowerStandbyAllowlist() throws Exception {
    public void testLowPowerStandbyAllowlist() throws Exception {
        // Chain background is also enabled but these procstates are important enough to be exempt.
        // Chain background is also enabled but these procstates are important enough to be exempt.
@@ -2559,17 +2676,6 @@ public class NetworkPolicyManagerServiceTest {
        verify(mStatsManager).setDefaultGlobalAlert(anyLong());
        verify(mStatsManager).setDefaultGlobalAlert(anyLong());
    }
    }


    private static class TestAbstractFuture<T> extends AbstractFuture<T> {
        @Override
        public T get() throws InterruptedException, ExecutionException {
            try {
                return get(5, TimeUnit.SECONDS);
            } catch (TimeoutException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private static void assertTimeEquals(long expected, long actual) {
    private static void assertTimeEquals(long expected, long actual) {
        if (expected != actual) {
        if (expected != actual) {
            fail("expected " + formatTime(expected) + " but was actually " + formatTime(actual));
            fail("expected " + formatTime(expected) + " but was actually " + formatTime(actual));