From 480cc3123c5ee6ae4fff56599124794a0ff25aa4 Mon Sep 17 00:00:00 2001 From: Misha Wagner Date: Tue, 10 Aug 2021 13:57:57 +0100 Subject: [PATCH] Change CacheOomRanker's "uses" feature. The previous implementation was incorrect, as an app goes in and out of the cache several times during oom_adj calculation. If all apps started at the same time, then this would be OK - as they all get incremented the same amount, plus get incremented when they actually go in and out of the cache. This would result in the relative counts being correct. However, as all apps aren't started at the same time, the old implementation is instead a measure of how long the app has been started. So instead we use mSetProcState, which isn't changed on each oom_adj calculation. This measure should accurately reflect the number of times the process is used - whether that's by a user app open, or a content receiver call, or an intent being broadcast. See go/sim-v-impl for more details. Test: atest CacheOomRankerTest Bug: 196031723 Change-Id: I49d02362b8277f8472355e78412f79256c2289a1 --- core/java/android/app/ActivityManager.java | 5 +++++ .../com/android/server/am/ProcessStateRecord.java | 11 +++++------ .../src/com/android/server/am/CacheOomRankerTest.java | 9 +++++---- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index b29349ee47de6..365493ded1838 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -771,6 +771,11 @@ public class ActivityManager { return procState >= PROCESS_STATE_TRANSIENT_BACKGROUND; } + /** @hide Should this process state be considered in the cache? */ + public static final boolean isProcStateCached(int procState) { + return procState >= PROCESS_STATE_CACHED_ACTIVITY; + } + /** @hide Is this a foreground service type? */ public static boolean isForegroundService(int procState) { return procState == PROCESS_STATE_FOREGROUND_SERVICE; diff --git a/services/core/java/com/android/server/am/ProcessStateRecord.java b/services/core/java/com/android/server/am/ProcessStateRecord.java index 46144f586dbd1..e8e61f2c5734c 100644 --- a/services/core/java/com/android/server/am/ProcessStateRecord.java +++ b/services/core/java/com/android/server/am/ProcessStateRecord.java @@ -611,6 +611,10 @@ final class ProcessStateRecord { @GuardedBy({"mService", "mProcLock"}) void setSetProcState(int setProcState) { + if (ActivityManager.isProcStateCached(mSetProcState) + && !ActivityManager.isProcStateCached(setProcState)) { + mCacheOomRankerUseCount++; + } mSetProcState = setProcState; } @@ -874,12 +878,7 @@ final class ProcessStateRecord { @GuardedBy("mService") void setCached(boolean cached) { - if (mCached != cached) { - mCached = cached; - if (cached) { - ++mCacheOomRankerUseCount; - } - } + mCached = cached; } @GuardedBy("mService") diff --git a/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java index 15dfd266853ee..d0c9242969454 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java @@ -24,6 +24,7 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; +import android.app.ActivityManager; import android.app.IApplicationThread; import android.content.ComponentName; import android.content.Context; @@ -581,7 +582,7 @@ public class CacheOomRankerTest { } private ProcessRecord nextProcessRecord(int setAdj, long lastActivityTime, long lastRss, - int returnedToCacheCount) { + int wentToForegroundCount) { ApplicationInfo ai = new ApplicationInfo(); ai.packageName = "a.package.name" + mNextPackageName++; ProcessRecord app = new ProcessRecord(mAms, ai, ai.packageName + ":process", mNextUid++); @@ -593,9 +594,9 @@ public class CacheOomRankerTest { app.setLastActivityTime(lastActivityTime); app.mProfile.setLastRss(lastRss); app.mState.setCached(false); - for (int i = 0; i < returnedToCacheCount; ++i) { - app.mState.setCached(false); - app.mState.setCached(true); + for (int i = 0; i < wentToForegroundCount; ++i) { + app.mState.setSetProcState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE); + app.mState.setSetProcState(ActivityManager.PROCESS_STATE_CACHED_RECENT); } // Sets the thread returned by ProcessRecord#getThread, which we use to check whether the // app is currently launching.