diff options
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityManagerService.java | 129 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ProcessRecord.java | 10 |
2 files changed, 96 insertions, 43 deletions
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index d11439755693..3bfd363de836 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -25,6 +25,7 @@ import static android.Manifest.permission.REMOVE_TASKS; import static android.app.ActivityManager.INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS; import static android.app.ActivityManager.INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL; import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY; +import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY; import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY; import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY; @@ -15711,7 +15712,7 @@ public class ActivityManagerService extends IActivityManager.Stub } private final boolean computeOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP, - boolean doingAll, long now) { + boolean doingAll, long now, boolean cycleReEval) { if (mAdjSeq == app.adjSeq) { if (app.adjSeq == app.completedAdjSeq) { // This adjustment has already been computed successfully. @@ -15777,20 +15778,21 @@ public class ActivityManagerService extends IActivityManager.Stub app.systemNoUi = false; } if (!app.systemNoUi) { - if (mWakefulness == PowerManagerInternal.WAKEFULNESS_AWAKE) { - // screen on, promote UI - app.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT_UI); - app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP); - } else { - // screen off, restrict UI scheduling - app.setCurProcState(ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE); - app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_RESTRICTED); - } + if (mWakefulness == PowerManagerInternal.WAKEFULNESS_AWAKE) { + // screen on, promote UI + app.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT_UI); + app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP); + } else { + // screen off, restrict UI scheduling + app.setCurProcState(ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE); + app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_RESTRICTED); + } } + app.setCurRawProcState(app.getCurProcState()); app.curAdj = app.maxAdj; app.completedAdjSeq = app.adjSeq; // if curAdj is less than prevAppAdj, then this process was promoted - return app.curAdj < prevAppAdj; + return app.curAdj < prevAppAdj || app.getCurProcState() < prevProcState; } app.systemNoUi = false; @@ -16032,8 +16034,13 @@ public class ActivityManagerService extends IActivityManager.Stub // By default, we use the computed adjustment. It may be changed if // there are applications dependent on our services or providers, but // this gives us a baseline and makes sure we don't get into an - // infinite recursion. - app.setCurRawAdj(adj); + // infinite recursion. If we're re-evaluating due to cycles, use the previously computed + // values. + app.setCurRawAdj(!cycleReEval ? adj : Math.min(adj, app.getCurRawAdj())); + app.setCurRawProcState(!cycleReEval + ? procState + : Math.min(procState, app.getCurRawProcState())); + app.hasStartedServices = false; app.adjSeq = mAdjSeq; @@ -16135,21 +16142,15 @@ public class ActivityManagerService extends IActivityManager.Stub boolean trackedProcState = false; if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) { ProcessRecord client = cr.binding.client; - computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now); - if (client.containsCycle) { - // We've detected a cycle. We should retry computeOomAdjLocked later in - // case a later-checked connection from a client would raise its - // priority legitimately. - app.containsCycle = true; - // If the client has not been completely evaluated, skip using its - // priority. Else use the conservative value for now and look for a - // better state in the next iteration. - if (client.completedAdjSeq < mAdjSeq) { - continue; - } + computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now, cycleReEval); + + if (shouldSkipDueToCycle(app, client, procState, adj, cycleReEval)) { + continue; } + int clientAdj = client.getCurRawAdj(); - int clientProcState = client.getCurProcState(); + int clientProcState = client.getCurRawProcState(); + if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) { // If the other app is cached for any reason, for purposes here // we are going to consider it empty. The specific cached state @@ -16234,6 +16235,7 @@ public class ActivityManagerService extends IActivityManager.Stub } if (adj > newAdj) { adj = newAdj; + app.setCurRawAdj(adj); adjType = "service"; } } @@ -16305,6 +16307,7 @@ public class ActivityManagerService extends IActivityManager.Stub } if (procState > clientProcState) { procState = clientProcState; + app.setCurRawProcState(procState); if (adjType == null) { adjType = "service"; } @@ -16336,6 +16339,7 @@ public class ActivityManagerService extends IActivityManager.Stub if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ && a.isActivityVisible()) { adj = ProcessList.FOREGROUND_APP_ADJ; + app.setCurRawAdj(adj); if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) { if ((cr.flags&Context.BIND_IMPORTANT) != 0) { schedGroup = ProcessList.SCHED_GROUP_TOP_APP_BOUND; @@ -16377,21 +16381,15 @@ public class ActivityManagerService extends IActivityManager.Stub // Being our own client is not interesting. continue; } - computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now); - if (client.containsCycle) { - // We've detected a cycle. We should retry computeOomAdjLocked later in - // case a later-checked connection from a client would raise its - // priority legitimately. - app.containsCycle = true; - // If the client has not been completely evaluated, skip using its - // priority. Else use the conservative value for now and look for a - // better state in the next iteration. - if (client.completedAdjSeq < mAdjSeq) { - continue; - } + computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now, cycleReEval); + + if (shouldSkipDueToCycle(app, client, procState, adj, cycleReEval)) { + continue; } + int clientAdj = client.getCurRawAdj(); - int clientProcState = client.getCurProcState(); + int clientProcState = client.getCurRawProcState(); + if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) { // If the other app is cached for any reason, for purposes here // we are going to consider it empty. @@ -16405,6 +16403,7 @@ public class ActivityManagerService extends IActivityManager.Stub } else { adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ ? clientAdj : ProcessList.FOREGROUND_APP_ADJ; + app.setCurRawAdj(adj); adjType = "provider"; } app.cached &= client.cached; @@ -16440,6 +16439,7 @@ public class ActivityManagerService extends IActivityManager.Stub conn.trackProcState(clientProcState, mAdjSeq, now); if (procState > clientProcState) { procState = clientProcState; + app.setCurRawProcState(procState); } if (client.getCurrentSchedulingGroup() > schedGroup) { schedGroup = ProcessList.SCHED_GROUP_DEFAULT; @@ -16465,6 +16465,7 @@ public class ActivityManagerService extends IActivityManager.Stub if (cpr.hasExternalProcessHandles()) { if (adj > ProcessList.FOREGROUND_APP_ADJ) { adj = ProcessList.FOREGROUND_APP_ADJ; + app.setCurRawAdj(adj); schedGroup = ProcessList.SCHED_GROUP_DEFAULT; app.cached = false; app.adjType = "ext-provider"; @@ -16476,6 +16477,7 @@ public class ActivityManagerService extends IActivityManager.Stub } if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) { procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; + app.setCurRawProcState(procState); if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to external provider: " + app); @@ -16620,6 +16622,7 @@ public class ActivityManagerService extends IActivityManager.Stub app.curAdj = app.modifyRawOomAdj(adj); app.setCurrentSchedulingGroup(schedGroup); app.setCurProcState(procState); + app.setCurRawProcState(procState); app.setHasForegroundActivities(foregroundActivities); app.completedAdjSeq = mAdjSeq; @@ -16627,6 +16630,44 @@ public class ActivityManagerService extends IActivityManager.Stub return app.curAdj < prevAppAdj || app.getCurProcState() < prevProcState; } + /** + * Checks if for the given app and client, there's a cycle that should skip over the client + * for now or use partial values to evaluate the effect of the client binding. + * @param app + * @param client + * @param procState procstate evaluated so far for this app + * @param adj oom_adj evaluated so far for this app + * @param cycleReEval whether we're currently re-evaluating due to a cycle, and not the first + * evaluation. + * @return whether to skip using the client connection at this time + */ + private boolean shouldSkipDueToCycle(ProcessRecord app, ProcessRecord client, + int procState, int adj, boolean cycleReEval) { + if (client.containsCycle) { + // We've detected a cycle. We should retry computeOomAdjLocked later in + // case a later-checked connection from a client would raise its + // priority legitimately. + app.containsCycle = true; + // If the client has not been completely evaluated, check if it's worth + // using the partial values. + if (client.completedAdjSeq < mAdjSeq) { + if (cycleReEval) { + // If the partial values are no better, skip until the next + // attempt + if (client.getCurRawProcState() >= procState + && client.getCurRawAdj() >= adj) { + return true; + } + // Else use the client's partial procstate and adj to adjust the + // effect of the binding + } else { + return true; + } + } + } + return false; + } + private static final class RecordPssRunnable implements Runnable { private final ActivityManagerService mService; private final ProcessRecord mProc; @@ -17493,7 +17534,7 @@ public class ActivityManagerService extends IActivityManager.Stub return false; } - computeOomAdjLocked(app, cachedAdj, TOP_APP, doingAll, now); + computeOomAdjLocked(app, cachedAdj, TOP_APP, doingAll, now, false); return applyOomAdjLocked(app, doingAll, now, SystemClock.elapsedRealtime()); } @@ -17868,12 +17909,14 @@ public class ActivityManagerService extends IActivityManager.Stub for (int i=N-1; i>=0; i--) { ProcessRecord app = mProcessList.mLruProcesses.get(i); app.containsCycle = false; + app.setCurRawProcState(PROCESS_STATE_CACHED_EMPTY); + app.setCurRawAdj(ProcessList.UNKNOWN_ADJ); } for (int i=N-1; i>=0; i--) { ProcessRecord app = mProcessList.mLruProcesses.get(i); if (!app.killedByAm && app.thread != null) { app.procStateChanged = false; - computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now); + computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now, false); // if any app encountered a cycle, we need to perform an additional loop later retryCycles |= app.containsCycle; @@ -17976,8 +18019,8 @@ public class ActivityManagerService extends IActivityManager.Stub for (int i=0; i<N; i++) { ProcessRecord app = mProcessList.mLruProcesses.get(i); if (!app.killedByAm && app.thread != null && app.containsCycle == true) { - - if (computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now)) { + if (computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now, + true)) { retryCycles = true; } } diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index c4b715042953..c15b7c7d82c2 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -153,6 +153,7 @@ final class ProcessRecord implements WindowProcessListener { int trimMemoryLevel; // Last selected memory trimming level private int mCurProcState = PROCESS_STATE_NONEXISTENT; // Currently computed process state private int mRepProcState = PROCESS_STATE_NONEXISTENT; // Last reported process state + private int mCurRawProcState = PROCESS_STATE_NONEXISTENT; // Temp state during computation int setProcState = PROCESS_STATE_NONEXISTENT; // Last set process state in process tracker int pssProcState = PROCESS_STATE_NONEXISTENT; // Currently requesting pss for int pssStatType; // The type of stat collection that we are currently requesting @@ -902,6 +903,7 @@ final class ProcessRecord implements WindowProcessListener { if (mRepProcState > newState) { mRepProcState = newState; setCurProcState(newState); + setCurRawProcState(newState); for (int ipkg = pkgList.size() - 1; ipkg >= 0; ipkg--) { StatsLog.write(StatsLog.PROCESS_STATE_CHANGED, uid, processName, pkgList.keyAt(ipkg), @@ -984,6 +986,14 @@ final class ProcessRecord implements WindowProcessListener { return mCurProcState; } + void setCurRawProcState(int curRawProcState) { + mCurRawProcState = curRawProcState; + } + + int getCurRawProcState() { + return mCurRawProcState; + } + void setReportedProcState(int repProcState) { mRepProcState = repProcState; for (int ipkg = pkgList.size() - 1; ipkg >= 0; ipkg--) { |