Skip computing proc states during app initialization

Now that app initialization covers class loading, there can be
hundreds of milliseconds delay before a top app activity gets
scheduled to start. During this delay, computing proc states
overrides the top app special case set at attachApplication to
boost the sched group.

This is fixed with the following changes:
1. Skip computing proc states when the application hasn't finished
attach application
2. Trigger a proc state update immediately after scheduling
bindApplication. This ensures that the special cased proc state is
applied as soon as possible

Test: atest MockingOomAdjusterTests
Bug: 253908737
Change-Id: Iae30a508b8b079dc88d6d5ffa027b7d805fec9e4
This commit is contained in:
Zim
2023-02-22 13:55:35 +00:00
parent 0683f76ebe
commit e9781e625f
3 changed files with 68 additions and 11 deletions

View File

@@ -4925,14 +4925,8 @@ public class ActivityManagerService extends IActivityManager.Stub
EventLogTags.writeAmProcBound(app.userId, pid, app.processName);
synchronized (mProcLock) {
app.mState.setCurAdj(ProcessList.INVALID_ADJ);
app.mState.setSetAdj(ProcessList.INVALID_ADJ);
app.mState.setVerifiedAdj(ProcessList.INVALID_ADJ);
mOomAdjuster.setAttachingSchedGroupLSP(app);
app.mState.setForcingToImportant(null);
mOomAdjuster.setAttachingProcessStatesLSP(app);
clearProcessForegroundLocked(app);
app.mState.setHasShownUi(false);
app.mState.setCached(false);
app.setDebugging(false);
app.setKilledByAm(false);
app.setKilled(false);
@@ -5100,8 +5094,14 @@ public class ActivityManagerService extends IActivityManager.Stub
app.makeActive(thread, mProcessStats);
checkTime(startTime, "attachApplicationLocked: immediately after bindApplication");
}
app.setPendingFinishAttach(true);
updateLruProcessLocked(app, false, null);
checkTime(startTime, "attachApplicationLocked: after updateLruProcessLocked");
updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);
checkTime(startTime, "attachApplicationLocked: after updateOomAdjLocked");
final long now = SystemClock.uptimeMillis();
synchronized (mAppProfiler.mProfilerLock) {
app.mProfile.setLastRequestedGc(now);
@@ -5117,8 +5117,6 @@ public class ActivityManagerService extends IActivityManager.Stub
if (!mConstants.mEnableWaitForFinishAttachApplication) {
finishAttachApplicationInner(startSeq, callingUid, pid);
} else {
app.setPendingFinishAttach(true);
}
} catch (Exception e) {
// We need kill the process group here. (b/148588589)

View File

@@ -1259,12 +1259,19 @@ public class OomAdjuster {
for (int i = numLru - 1; i >= 0; i--) {
ProcessRecord app = lruList.get(i);
final ProcessStateRecord state = app.mState;
if (!app.isKilledByAm() && app.getThread() != null && !app.isPendingFinishAttach()) {
if (!app.isKilledByAm() && app.getThread() != null) {
// We don't need to apply the update for the process which didn't get computed
if (state.getCompletedAdjSeq() == mAdjSeq) {
applyOomAdjLSP(app, true, now, nowElapsed, oomAdjReason);
}
if (app.isPendingFinishAttach()) {
// Avoid trimming processes that are still initializing. If they aren't
// hosting any components yet because they may be unfairly killed.
// We however apply any computed previously computed oom scores before skipping.
continue;
}
final ProcessServiceRecord psr = app.mServices;
// Count the number of process types.
switch (state.getCurProcState()) {
@@ -1698,6 +1705,19 @@ public class OomAdjuster {
return false;
}
if (app.isPendingFinishAttach()) {
state.setAdjSeq(mAdjSeq);
state.setCompletedAdjSeq(mAdjSeq);
// If the process is still initializing, we skip computing any states because we
// don't want to override the special states that have been set at
// AMS#attachApplication with OomAdjuster#setAttachingProcessStates.
// In this limbo state, the app has |PROC_START_TIMEOUT| to finish attach application
// and receive updated proc_state based on its importance.
// Note that in this state, the oom_score is INVALID_ADJ which is outside the standard
// oom score range and the app is safe from lmkd kills.
return false;
}
state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN);
state.setAdjSource(null);
state.setAdjTarget(null);
@@ -3211,7 +3231,7 @@ public class OomAdjuster {
}
@GuardedBy({"mService", "mProcLock"})
void setAttachingSchedGroupLSP(ProcessRecord app) {
void setAttachingProcessStatesLSP(ProcessRecord app) {
int initialSchedGroup = SCHED_GROUP_DEFAULT;
final ProcessStateRecord state = app.mState;
// If the process has been marked as foreground, it is starting as the top app (with
@@ -3231,6 +3251,15 @@ public class OomAdjuster {
state.setSetSchedGroup(initialSchedGroup);
state.setCurrentSchedulingGroup(initialSchedGroup);
state.setCurProcState(PROCESS_STATE_CACHED_EMPTY);
state.setCurCapability(PROCESS_CAPABILITY_NONE);
state.setCurAdj(ProcessList.FOREGROUND_APP_ADJ);
state.setSetAdj(ProcessList.FOREGROUND_APP_ADJ);
state.setVerifiedAdj(ProcessList.FOREGROUND_APP_ADJ);
state.setForcingToImportant(null);
state.setHasShownUi(false);
state.setCached(true);
}
// ONLY used for unit testing in OomAdjusterTests.java

View File

@@ -1966,6 +1966,36 @@ public class MockingOomAdjusterTests {
assertBfsl(app1);
}
@SuppressWarnings("GuardedBy")
@Test
public void testUpdateOomAdj_DoOne_PendingFinishAttach() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
app.setPendingFinishAttach(true);
app.mState.setHasForegroundActivities(false);
sService.mOomAdjuster.setAttachingProcessStatesLSP(app);
updateOomAdj(app);
assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, FOREGROUND_APP_ADJ,
SCHED_GROUP_DEFAULT);
}
@SuppressWarnings("GuardedBy")
@Test
public void testUpdateOomAdj_DoOne_TopApp_PendingFinishAttach() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
app.setPendingFinishAttach(true);
app.mState.setHasForegroundActivities(true);
sService.mOomAdjuster.setAttachingProcessStatesLSP(app);
updateOomAdj(app);
assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, FOREGROUND_APP_ADJ,
SCHED_GROUP_TOP_APP);
}
@SuppressWarnings("GuardedBy")
@Test
public void testUpdateOomAdj_UidIdle_StopService() {