am 17c21a30: am 2c09e8cd: Merge "Fix issue #11157301: Bad process stats when apps are binding to long-running services" into klp-dev
* commit '17c21a3007a2321ae8805a397c3566411a60cba0':
Fix issue #11157301: Bad process stats when apps are binding to long-running services
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 7d7c500..9c1c863 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -14267,6 +14267,8 @@
}
}
+ 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 @@
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 @@
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 @@
}
}
+ 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);