diff options
4 files changed, 109 insertions, 13 deletions
| diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java index 72e62c37106d..8ad60e6a0782 100644 --- a/services/core/java/com/android/server/am/ActivityManagerConstants.java +++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java @@ -243,7 +243,7 @@ final class ActivityManagerConstants extends ContentObserver {      /**       * The default value to {@link #KEY_ENABLE_NEW_OOMADJ}.       */ -    private static final boolean DEFAULT_ENABLE_NEW_OOM_ADJ = false; +    private static final boolean DEFAULT_ENABLE_NEW_OOM_ADJ = Flags.oomadjusterCorrectnessRewrite();      /**       * Same as {@link TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED} diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index f49e25af79d3..ef7a0e058db0 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -1385,6 +1385,8 @@ public class OomAdjuster {                          break;                  } +                // TODO: b/319163103 - limit isolated/sandbox trimming to just the processes +                //  evaluated in the current update.                  if (app.isolated && psr.numberOfRunningServices() <= 0                          && app.getIsolatedEntryPoint() == null) {                      // If this is an isolated process, there are no services diff --git a/services/core/java/com/android/server/am/OomAdjusterModernImpl.java b/services/core/java/com/android/server/am/OomAdjusterModernImpl.java index 7cc7c517fa9c..5a3fbe9a66ac 100644 --- a/services/core/java/com/android/server/am/OomAdjusterModernImpl.java +++ b/services/core/java/com/android/server/am/OomAdjusterModernImpl.java @@ -724,24 +724,13 @@ public class OomAdjusterModernImpl extends OomAdjuster {          if (fullUpdate) {              assignCachedAdjIfNecessary(mProcessList.getLruProcessesLOSP()); -            postUpdateOomAdjInnerLSP(oomAdjReason, activeUids, now, nowElapsed, oldTime);          } else {              activeProcesses.clear();              activeProcesses.addAll(targetProcesses);              assignCachedAdjIfNecessary(activeProcesses); - -            for (int  i = activeUids.size() - 1; i >= 0; i--) { -                final UidRecord uidRec = activeUids.valueAt(i); -                uidRec.forEachProcess(this::updateAppUidRecIfNecessaryLSP); -            } -            updateUidsLSP(activeUids, nowElapsed); - -            for (int i = 0, size = targetProcesses.size(); i < size; i++) { -                applyOomAdjLSP(targetProcesses.valueAt(i), false, now, nowElapsed, oomAdjReason); -            } -              activeProcesses.clear();          } +        postUpdateOomAdjInnerLSP(oomAdjReason, activeUids, now, nowElapsed, oldTime);          targetProcesses.clear();          if (startProfiling) { diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java index f386c3bf6a15..e4b6206f7f54 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java @@ -80,10 +80,13 @@ import static org.mockito.Mockito.doCallRealMethod;  import static org.mockito.Mockito.doNothing;  import static org.mockito.Mockito.doReturn;  import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never;  import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify;  import android.app.ActivityManager;  import android.app.AppOpsManager; +import android.app.ApplicationExitInfo;  import android.app.IApplicationThread;  import android.app.IServiceConnection;  import android.content.ComponentName; @@ -94,6 +97,7 @@ import android.content.pm.ServiceInfo;  import android.os.Build;  import android.os.IBinder;  import android.os.PowerManagerInternal; +import android.os.Process;  import android.os.SystemClock;  import android.os.UserHandle;  import android.platform.test.annotations.Presubmit; @@ -148,6 +152,9 @@ public class MockingOomAdjusterTests {      private static final String MOCKAPP5_PROCESSNAME = "test #5";      private static final String MOCKAPP5_PACKAGENAME = "com.android.test.test5";      private static final int MOCKAPP2_UID_OTHER = MOCKAPP2_UID + UserHandle.PER_USER_RANGE; +    private static final int MOCKAPP_ISOLATED_UID = Process.FIRST_ISOLATED_UID + 321; +    private static final String MOCKAPP_ISOLATED_PROCESSNAME = "isolated test #1"; +      private static int sFirstCachedAdj = ProcessList.CACHED_APP_MIN_ADJ                                            + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;      private static Context sContext; @@ -286,6 +293,20 @@ public class MockingOomAdjusterTests {      }      /** +     * Run updateOomAdjPendingTargetsLocked(). +     * - enqueues all provided processes to the pending list and lru before running +     */ +    @SuppressWarnings("GuardedBy") +    private void updateOomAdjPending(ProcessRecord... apps) { +        setProcessesToLru(apps); +        for (ProcessRecord app : apps) { +            sService.mOomAdjuster.enqueueOomAdjTargetLocked(app); +        } +        sService.mOomAdjuster.updateOomAdjPendingTargetsLocked(OOM_ADJ_REASON_NONE); +        sService.mProcessList.getLruProcessesLOSP().clear(); +    } + +    /**       * Fix up the pointers in the {@link ProcessRecordNode#mApp}:       * because we used the mokito spy objects all over the tests here, but the internal       * pointers in the {@link ProcessRecordNode#mApp} actually point to the real object. @@ -2651,6 +2672,90 @@ public class MockingOomAdjusterTests {          assertNotEquals(FOREGROUND_APP_ADJ, app.mState.getSetAdj());      } +    @SuppressWarnings("GuardedBy") +    @Test +    public void testUpdateOomAdj_DoAll_Isolated_stopService() { +        ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_ISOLATED_UID, +                MOCKAPP_ISOLATED_PROCESSNAME, MOCKAPP_PACKAGENAME, false)); + +        setProcessesToLru(app); +        ServiceRecord s = makeServiceRecord(app); +        s.startRequested = true; +        s.lastActivity = SystemClock.uptimeMillis(); +        sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE); +        updateOomAdj(); +        assertProcStates(app, PROCESS_STATE_SERVICE, SERVICE_ADJ, SCHED_GROUP_BACKGROUND); + +        app.mServices.stopService(s); +        updateOomAdj(); +        // isolated process should be killed immediately after service stop. +        verify(app).killLocked("isolated not needed", ApplicationExitInfo.REASON_OTHER, +                ApplicationExitInfo.SUBREASON_ISOLATED_NOT_NEEDED, true); +    } + +    @SuppressWarnings("GuardedBy") +    @Test +    public void testUpdateOomAdj_DoPending_Isolated_stopService() { +        ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_ISOLATED_UID, +                MOCKAPP_ISOLATED_PROCESSNAME, MOCKAPP_PACKAGENAME, false)); + +        ServiceRecord s = makeServiceRecord(app); +        s.startRequested = true; +        s.lastActivity = SystemClock.uptimeMillis(); +        sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE); +        updateOomAdjPending(app); +        assertProcStates(app, PROCESS_STATE_SERVICE, SERVICE_ADJ, SCHED_GROUP_BACKGROUND); + +        app.mServices.stopService(s); +        updateOomAdjPending(app); +        // isolated process should be killed immediately after service stop. +        verify(app).killLocked("isolated not needed", ApplicationExitInfo.REASON_OTHER, +                ApplicationExitInfo.SUBREASON_ISOLATED_NOT_NEEDED, true); +    } + +    @SuppressWarnings("GuardedBy") +    @Test +    public void testUpdateOomAdj_DoAll_Isolated_stopServiceWithEntryPoint() { +        ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_ISOLATED_UID, +                MOCKAPP_ISOLATED_PROCESSNAME, MOCKAPP_PACKAGENAME, false)); +        app.setIsolatedEntryPoint("test"); + +        setProcessesToLru(app); +        ServiceRecord s = makeServiceRecord(app); +        s.startRequested = true; +        s.lastActivity = SystemClock.uptimeMillis(); +        sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE); +        updateOomAdj(); +        assertProcStates(app, PROCESS_STATE_SERVICE, SERVICE_ADJ, SCHED_GROUP_BACKGROUND); + +        app.mServices.stopService(s); +        updateOomAdj(); +        // isolated process with entry point should not be killed +        verify(app, never()).killLocked("isolated not needed", ApplicationExitInfo.REASON_OTHER, +                ApplicationExitInfo.SUBREASON_ISOLATED_NOT_NEEDED, true); +    } + +    @SuppressWarnings("GuardedBy") +    @Test +    public void testUpdateOomAdj_DoPending_Isolated_stopServiceWithEntryPoint() { +        ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_ISOLATED_UID, +                MOCKAPP_ISOLATED_PROCESSNAME, MOCKAPP_PACKAGENAME, false)); +        app.setIsolatedEntryPoint("test"); + +        ServiceRecord s = makeServiceRecord(app); +        s.startRequested = true; +        s.lastActivity = SystemClock.uptimeMillis(); +        sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE); +        updateOomAdjPending(app); +        assertProcStates(app, PROCESS_STATE_SERVICE, SERVICE_ADJ, SCHED_GROUP_BACKGROUND); + +        app.mServices.stopService(s); +        updateOomAdjPending(app); +        // isolated process with entry point should not be killed +        verify(app, never()).killLocked("isolated not needed", ApplicationExitInfo.REASON_OTHER, +                ApplicationExitInfo.SUBREASON_ISOLATED_NOT_NEEDED, true); +    } +      private ProcessRecord makeDefaultProcessRecord(int pid, int uid, String processName,              String packageName, boolean hasShownUi) {          long now = SystemClock.uptimeMillis(); |