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
Merged-In: I49d02362b8277f8472355e78412f79256c2289a1
(cherry picked from commit 480cc3123c)
This commit is contained in:
Misha Wagner
2021-09-20 13:42:27 +01:00
parent f81d50e255
commit 7d611c750c
3 changed files with 15 additions and 10 deletions

View File

@@ -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;

View File

@@ -577,6 +577,10 @@ final class ProcessStateRecord {
@GuardedBy({"mService", "mProcLock"})
void setSetProcState(int setProcState) {
if (ActivityManager.isProcStateCached(mSetProcState)
&& !ActivityManager.isProcStateCached(setProcState)) {
mCacheOomRankerUseCount++;
}
mSetProcState = setProcState;
}
@@ -840,12 +844,7 @@ final class ProcessStateRecord {
@GuardedBy("mService")
void setCached(boolean cached) {
if (mCached != cached) {
mCached = cached;
if (cached) {
++mCacheOomRankerUseCount;
}
}
mCached = cached;
}
@GuardedBy("mService")

View File

@@ -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.