diff options
author | Dianne Hackborn <hackbod@google.com> | 2013-10-09 19:11:20 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2013-10-10 16:10:32 -0700 |
commit | 32366b29c4c6acfb258ba3b2f5a181d336e13280 (patch) | |
tree | 5cb652fe40ddd704b8712e67e0bdbb40da16824b /services/java/com/android/server/am | |
parent | 94ba89763e2bd660662fbcf293968d3e8423ef68 (diff) | |
download | frameworks_base-32366b29c4c6acfb258ba3b2f5a181d336e13280.zip frameworks_base-32366b29c4c6acfb258ba3b2f5a181d336e13280.tar.gz frameworks_base-32366b29c4c6acfb258ba3b2f5a181d336e13280.tar.bz2 |
Fix issue #11157301: Bad process stats when apps are binding to long-running services
We now treat PROCESS_STATE_TOP more specially. When a process has another
client bound to it that is TOP, it will only allow itself to go in the TOP
state if it is not already running for another significant reason.
Change-Id: Ia3856406bd481bf6e98d55100a5513ccf4060e0d
Diffstat (limited to 'services/java/com/android/server/am')
-rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 90 |
1 files changed, 66 insertions, 24 deletions
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 6c6cc98..f7b7515 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -14267,6 +14267,8 @@ public final class ActivityManagerService extends ActivityManagerNative } } + boolean mayBeTop = false; + for (int is = app.services.size()-1; is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE @@ -14427,18 +14429,27 @@ public final class ActivityManagerService extends ActivityManagerNative if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) { schedGroup = Process.THREAD_GROUP_DEFAULT; } - if (clientProcState <= - ActivityManager.PROCESS_STATE_PERSISTENT_UI && - clientProcState >= - ActivityManager.PROCESS_STATE_PERSISTENT) { - // Persistent processes don't allow us to become top. - // However the top process DOES allow us to become top, - // because in that case we are running because the current - // top process wants us, so we should be counted as part - // of the top set and not just running for some random - // unknown reason in the background. - clientProcState = - ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; + if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) { + if (clientProcState == ActivityManager.PROCESS_STATE_TOP) { + // Special handling of clients who are in the top state. + // We *may* want to consider this process to be in the + // top state as well, but only if there is not another + // reason for it to be running. Being on the top is a + // special state, meaning you are specifically running + // for the current top app. If the process is already + // running in the background for some other reason, it + // is more important to continue considering it to be + // in the background state. + mayBeTop = true; + clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; + } else { + // Special handling for above-top states (persistent + // processes). These should not bring the current process + // into the top state, since they are not on top. Instead + // give them the best state after that. + clientProcState = + ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; + } } } else { if (clientProcState < @@ -14526,18 +14537,27 @@ public final class ActivityManagerService extends ActivityManagerNative app.adjSourceOom = clientAdj; app.adjTarget = cpr.name; } - if (clientProcState <= - ActivityManager.PROCESS_STATE_PERSISTENT_UI && - clientProcState >= - ActivityManager.PROCESS_STATE_PERSISTENT) { - // Persistent processes don't allow us to become top. - // However the top process DOES allow us to become top, - // because in that case we are running because the current - // top process wants us, so we should be counted as part - // of the top set and not just running for some random - // unknown reason in the background. - clientProcState = - ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; + if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) { + if (clientProcState == ActivityManager.PROCESS_STATE_TOP) { + // Special handling of clients who are in the top state. + // We *may* want to consider this process to be in the + // top state as well, but only if there is not another + // reason for it to be running. Being on the top is a + // special state, meaning you are specifically running + // for the current top app. If the process is already + // running in the background for some other reason, it + // is more important to continue considering it to be + // in the background state. + mayBeTop = true; + clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; + } else { + // Special handling for above-top states (persistent + // processes). These should not bring the current process + // into the top state, since they are not on top. Instead + // give them the best state after that. + clientProcState = + ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; + } } if (procState > clientProcState) { procState = clientProcState; @@ -14564,6 +14584,28 @@ public final class ActivityManagerService extends ActivityManagerNative } } + if (mayBeTop && procState > ActivityManager.PROCESS_STATE_TOP) { + // A client of one of our services or providers is in the top state. We + // *may* want to be in the top state, but not if we are already running in + // the background for some other reason. For the decision here, we are going + // to pick out a few specific states that we want to remain in when a client + // is top (states that tend to be longer-term) and otherwise allow it to go + // to the top state. + switch (procState) { + case ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND: + case ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND: + case ActivityManager.PROCESS_STATE_SERVICE: + // These all are longer-term states, so pull them up to the top + // of the background states, but not all the way to the top state. + procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; + break; + default: + // Otherwise, top is a better choice, so take it. + procState = ActivityManager.PROCESS_STATE_TOP; + break; + } + } + if (adj == ProcessList.SERVICE_ADJ) { if (doingAll) { app.serviceb = mNewNumAServiceProcs > (mNumServiceProcs/3); |