From 64a4c4ec66e9077cbf7ea4c0f95fe4a40fb04a72 Mon Sep 17 00:00:00 2001 From: Hui Yu Date: Mon, 14 Feb 2022 23:00:46 -0800 Subject: [PATCH] The uid with the newest timestamp in mPendingStartActivityUids gets the best score. getProcessStatesAndOomScoresForPIDs() returns the procstate and oom_adj score of a list of uid. If OomAdjuster does not update procstate fast enough after WindowManager switches activity to foreground, we use mPendingStartActivityUids to save the uid that moves to foreground. Then OomAdjuster removes the uid from mPendingStartActivityUids later. Because OomAdjust has latencty, the uid may be delayed to be deleted from mPendingStartActivityUids. This ends up with multiple uids in the mPendingStartActivityUids. When these multiple uids compete for camera, getProcessStatesAndOomScoresForPIDs() can not distinguish procstate and scores for these uids. This CL will compare the elapsedRealtime these uids are added into mPendingStartActivityUids, the uid with the newest timestamp gets the best score. Bug: 218947003 Test: b/218947003 reproduce steps, fast swipe between Messaging and Camera app for many times. Change-Id: Ic28a617d234a20a3f8e33982c42e2e2c3ffd5dbd --- .../server/am/ActivityManagerService.java | 33 +++++++++++++++---- .../server/am/PendingStartActivityUids.java | 19 ++++++++--- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 2371101d7c9fd..9e78af82709dc 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -5614,15 +5614,29 @@ public class ActivityManagerService extends IActivityManager.Stub synchronized (mProcLock) { synchronized (mPidsSelfLocked) { + int newestTimeIndex = -1; + long newestTime = Long.MIN_VALUE; for (int i = 0; i < pids.length; i++) { ProcessRecord pr = mPidsSelfLocked.get(pids[i]); if (pr != null) { - final boolean isPendingTop = - mPendingStartActivityUids.isPendingTopPid(pr.uid, pids[i]); - states[i] = isPendingTop ? PROCESS_STATE_TOP : pr.mState.getCurProcState(); - if (scores != null) { - scores[i] = isPendingTop - ? (ProcessList.FOREGROUND_APP_ADJ - 1) : pr.mState.getCurAdj(); + final long pendingTopTime = + mPendingStartActivityUids.getPendingTopPidTime(pr.uid, pids[i]); + if (pendingTopTime != PendingStartActivityUids.INVALID_TIME) { + // The uid in mPendingStartActivityUids gets the TOP process state. + states[i] = PROCESS_STATE_TOP; + if (scores != null) { + // The uid in mPendingStartActivityUids gets a better score. + scores[i] = ProcessList.FOREGROUND_APP_ADJ - 1; + } + if (pendingTopTime > newestTime) { + newestTimeIndex = i; + newestTime = pendingTopTime; + } + } else { + states[i] = pr.mState.getCurProcState(); + if (scores != null) { + scores[i] = pr.mState.getCurAdj(); + } } } else { states[i] = PROCESS_STATE_NONEXISTENT; @@ -5631,6 +5645,13 @@ public class ActivityManagerService extends IActivityManager.Stub } } } + // The uid with the newest timestamp in mPendingStartActivityUids gets the best + // score. + if (newestTimeIndex != -1) { + if (scores != null) { + scores[newestTimeIndex] = ProcessList.FOREGROUND_APP_ADJ - 2; + } + } } } } diff --git a/services/core/java/com/android/server/am/PendingStartActivityUids.java b/services/core/java/com/android/server/am/PendingStartActivityUids.java index 6bf9d4e5c3f0f..802ea001e28c3 100644 --- a/services/core/java/com/android/server/am/PendingStartActivityUids.java +++ b/services/core/java/com/android/server/am/PendingStartActivityUids.java @@ -35,6 +35,8 @@ import android.util.SparseArray; final class PendingStartActivityUids { static final String TAG = ActivityManagerService.TAG; + public static final long INVALID_TIME = 0; + // Key is uid, value is Pair of pid and SystemClock.elapsedRealtime() when the // uid is added. private final SparseArray> mPendingUids = new SparseArray(); @@ -63,13 +65,20 @@ final class PendingStartActivityUids { } } - synchronized boolean isPendingTopPid(int uid, int pid) { + /** + * Return the elapsedRealtime when the uid is added to the mPendingUids map. + * @param uid + * @param pid + * @return elapsedRealtime if the uid is in the mPendingUids map; + * INVALID_TIME if the uid is not in the mPendingUids map. + */ + synchronized long getPendingTopPidTime(int uid, int pid) { + long ret = INVALID_TIME; final Pair pendingPid = mPendingUids.get(uid); - if (pendingPid != null) { - return pendingPid.first == pid; - } else { - return false; + if (pendingPid != null && pendingPid.first == pid) { + ret = pendingPid.second; } + return ret; } synchronized boolean isPendingTopUid(int uid) {