summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
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
commit32366b29c4c6acfb258ba3b2f5a181d336e13280 (patch)
tree5cb652fe40ddd704b8712e67e0bdbb40da16824b
parent94ba89763e2bd660662fbcf293968d3e8423ef68 (diff)
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
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java90
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 6c6cc9839687..f7b751597813 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);