From e69f7fdbb6504985891bc824ce634757d1170bb4 Mon Sep 17 00:00:00 2001 From: Sudheer Shanka Date: Wed, 30 Mar 2022 12:28:28 -0700 Subject: [PATCH] Inform NPMS about the app coming to the TOP state early. It's possible for an app to come to the TOP state before the oomAdj computation is done and we cannot wait for oomAdj computation to complete and then inform NPMS about the state change. So, inform NPMS early about the state change when we know the app is going to the TOP state. Bug: 226299593 Test: atest tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java Change-Id: I5d582618652cead179c419f7fe084283dd89d514 --- .../android/app/ActivityManagerInternal.java | 11 +++++++++ .../server/am/ActivityManagerService.java | 23 +++++++++++++++++++ .../com/android/server/am/ProcessList.java | 7 ++++-- .../net/NetworkPolicyManagerService.java | 2 +- .../net/NetworkPolicyManagerServiceTest.java | 4 ++-- 5 files changed, 42 insertions(+), 5 deletions(-) diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 95ac799e53d16..c022bf370e7e5 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -842,4 +842,15 @@ public abstract class ActivityManagerInternal { * Returns some summary statistics of the current PendingIntent queue - sizes and counts. */ public abstract List getPendingIntentStats(); + + /** + * Register the UidObserver for NetworkPolicyManager service. + * + * This is equivalent to calling + * {@link IActivityManager#registerUidObserver(IUidObserver, int, int, String)} but having a + * separate method for NetworkPolicyManager service so that it's UidObserver can be called + * separately outside the usual UidObserver flow. + */ + public abstract void registerNetworkPolicyUidObserver(@NonNull IUidObserver observer, + int which, int cutpoint, @NonNull String callingPackage); } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index be0d797760698..2904b74df7ea2 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -30,6 +30,7 @@ import static android.app.ActivityManager.INSTR_FLAG_DISABLE_ISOLATED_STORAGE; import static android.app.ActivityManager.INSTR_FLAG_DISABLE_TEST_API_CHECKS; import static android.app.ActivityManager.INSTR_FLAG_NO_RESTART; import static android.app.ActivityManager.INTENT_SENDER_ACTIVITY; +import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL; import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; import static android.app.ActivityManager.PROCESS_STATE_TOP; @@ -1483,6 +1484,7 @@ public class ActivityManagerService extends IActivityManager.Stub final ActivityThread mSystemThread; final UidObserverController mUidObserverController; + private volatile IUidObserver mNetworkPolicyUidObserver; final AppRestrictionController mAppRestrictionController; @@ -17300,6 +17302,19 @@ public class ActivityManagerService extends IActivityManager.Stub if (isNewPending && mOomAdjuster != null) { // It can be null in unit test. mOomAdjuster.mCachedAppOptimizer.unfreezeProcess(pid); } + // We need to update the network rules for the app coming to the top state so that + // it can access network when the device or the app is in a restricted state + // (e.g. battery/data saver) but since waiting for updateOomAdj to complete and then + // informing NetworkPolicyManager might get delayed, informing the state change as soon + // as we know app is going to come to the top state. + if (mNetworkPolicyUidObserver != null) { + try { + mNetworkPolicyUidObserver.onUidStateChanged(uid, PROCESS_STATE_TOP, + mProcessList.getProcStateSeqCounter(), PROCESS_CAPABILITY_ALL); + } catch (RemoteException e) { + // Should not happen; call is within the same process + } + } } @Override @@ -17497,6 +17512,14 @@ public class ActivityManagerService extends IActivityManager.Stub public void restart() { ActivityManagerService.this.restart(); } + + @Override + public void registerNetworkPolicyUidObserver(@NonNull IUidObserver observer, + int which, int cutpoint, @NonNull String callingPackage) { + mNetworkPolicyUidObserver = observer; + mUidObserverController.register(observer, which, cutpoint, callingPackage, + Binder.getCallingUid()); + } } long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) { diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 6629a3018f81d..bad7782fad77e 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -423,9 +423,8 @@ public final class ProcessList { * Having a global counter ensures that seq numbers are monotonically increasing for a * particular uid even when the uidRecord is re-created. */ - @GuardedBy("mService") @VisibleForTesting - long mProcStateSeqCounter = 0; + volatile long mProcStateSeqCounter = 0; /** * A global counter for generating sequence numbers to uniquely identify pending process starts. @@ -4860,6 +4859,10 @@ public final class ProcessList { } } + long getProcStateSeqCounter() { + return mProcStateSeqCounter; + } + /** * Create a server socket in system_server, zygote will connect to it * in order to send unsolicited messages to system_server. diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index a04204d903026..d7127acadfaa0 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -996,7 +996,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final int changes = ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_CAPABILITY; - mActivityManager.registerUidObserver(mUidObserver, changes, + mActivityManagerInternal.registerNetworkPolicyUidObserver(mUidObserver, changes, NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE, "android"); mNetworkManager.registerObserver(mAlertObserver); } catch (RemoteException e) { diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java index 7634b09b4dc6c..6c7f87244cfe2 100644 --- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java @@ -441,14 +441,14 @@ public class NetworkPolicyManagerServiceTest { setNetpolicyXml(context); doAnswer(new Answer() { - @Override public Void answer(InvocationOnMock invocation) throws Throwable { mUidObserver = (IUidObserver) invocation.getArguments()[0]; Log.d(TAG, "set mUidObserver to " + mUidObserver); return null; } - }).when(mActivityManager).registerUidObserver(any(), anyInt(), anyInt(), any(String.class)); + }).when(mActivityManagerInternal).registerNetworkPolicyUidObserver(any(), + anyInt(), anyInt(), any(String.class)); mFutureIntent = newRestrictBackgroundChangedFuture(); mDeps = new TestDependencies(mServiceContext);