@@ -685,6 +685,18 @@ private class Identity {
685685 */
686686 int mLruSeq = 0;
687687
688+ /**
689+ * Keep track of the non-hidden/empty process we last found, to help
690+ * determine how to distribute hidden/empty processes next time.
691+ */
692+ int mNumNonHiddenProcs = 0;
693+
694+ /**
695+ * Keep track of the number of hidden procs, to balance oom adj
696+ * distribution between those and empty procs.
697+ */
698+ int mNumHiddenProcs = 0;
699+
688700 /**
689701 * Keep track of the number of service processes we last found, to
690702 * determine on the next iteration which should be B services.
@@ -9081,7 +9093,9 @@ boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
90819093 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
90829094 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
90839095 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
9084- pw.println(" mNumServiceProcs=" + mNumServiceProcs
9096+ pw.println(" mNumNonHiddenProcs=" + mNumNonHiddenProcs
9097+ + " mNumHiddenProcs=" + mNumHiddenProcs
9098+ + " mNumServiceProcs=" + mNumServiceProcs
90859099 + " mNewNumServiceProcs=" + mNewNumServiceProcs);
90869100 }
90879101
@@ -9746,6 +9760,7 @@ public int compare(Pair<ProcessRecord, Integer> object1,
97469760 pw.print(" ");
97479761 pw.print("oom: max="); pw.print(r.maxAdj);
97489762 pw.print(" hidden="); pw.print(r.hiddenAdj);
9763+ pw.print(" empty="); pw.print(r.emptyAdj);
97499764 pw.print(" curRaw="); pw.print(r.curRawAdj);
97509765 pw.print(" setRaw="); pw.print(r.setRawAdj);
97519766 pw.print(" cur="); pw.print(r.curAdj);
@@ -11966,22 +11981,23 @@ private BroadcastQueue isReceivingBroadcast(ProcessRecord app) {
1196611981 }
1196711982
1196811983 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11969- ProcessRecord TOP_APP, boolean recursed, boolean doingAll) {
11984+ int emptyAdj, ProcessRecord TOP_APP, boolean recursed, boolean doingAll) {
1197011985 if (mAdjSeq == app.adjSeq) {
1197111986 // This adjustment has already been computed. If we are calling
1197211987 // from the top, we may have already computed our adjustment with
1197311988 // an earlier hidden adjustment that isn't really for us... if
1197411989 // so, use the new hidden adjustment.
1197511990 if (!recursed && app.hidden) {
11976- app.curAdj = app.curRawAdj = app.nonStoppingAdj = hiddenAdj;
11991+ app.curAdj = app.curRawAdj = app.nonStoppingAdj =
11992+ app.hasActivities ? hiddenAdj : emptyAdj;
1197711993 }
1197811994 return app.curRawAdj;
1197911995 }
1198011996
1198111997 if (app.thread == null) {
1198211998 app.adjSeq = mAdjSeq;
1198311999 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
11984- return (app.curAdj=ProcessList.HIDDEN_APP_MAX_ADJ);
12000+ return (app.curAdj=app.curRawAdj= ProcessList.HIDDEN_APP_MAX_ADJ);
1198512001 }
1198612002
1198712003 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
@@ -11998,6 +12014,7 @@ private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
1199812014 app.adjType = "fixed";
1199912015 app.adjSeq = mAdjSeq;
1200012016 app.curRawAdj = app.nonStoppingAdj = app.maxAdj;
12017+ app.hasActivities = false;
1200112018 app.foregroundActivities = false;
1200212019 app.keeping = true;
1200312020 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
@@ -12008,12 +12025,15 @@ private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
1200812025 app.systemNoUi = true;
1200912026 if (app == TOP_APP) {
1201012027 app.systemNoUi = false;
12028+ app.hasActivities = true;
1201112029 } else if (activitiesSize > 0) {
1201212030 for (int j = 0; j < activitiesSize; j++) {
1201312031 final ActivityRecord r = app.activities.get(j);
1201412032 if (r.visible) {
1201512033 app.systemNoUi = false;
12016- break;
12034+ }
12035+ if (r.app == app) {
12036+ app.hasActivities = true;
1201712037 }
1201812038 }
1201912039 }
@@ -12022,6 +12042,7 @@ private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
1202212042
1202312043 app.keeping = false;
1202412044 app.systemNoUi = false;
12045+ app.hasActivities = false;
1202512046
1202612047 // Determine the importance of the process, starting with most
1202712048 // important to least, and assign an appropriate OOM adjustment.
@@ -12037,6 +12058,7 @@ private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
1203712058 app.adjType = "top-activity";
1203812059 foregroundActivities = true;
1203912060 interesting = true;
12061+ app.hasActivities = true;
1204012062 } else if (app.instrumentationClass != null) {
1204112063 // Don't want to kill running instrumentation.
1204212064 adj = ProcessList.FOREGROUND_APP_ADJ;
@@ -12058,21 +12080,13 @@ private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
1205812080 adj = ProcessList.FOREGROUND_APP_ADJ;
1205912081 schedGroup = Process.THREAD_GROUP_DEFAULT;
1206012082 app.adjType = "exec-service";
12061- } else if (activitiesSize > 0) {
12062- // This app is in the background with paused activities.
12063- // We inspect activities to potentially upgrade adjustment further below.
12064- adj = hiddenAdj;
12065- schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12066- app.hidden = true;
12067- app.adjType = "bg-activities";
1206812083 } else {
12069- // A very not-needed process. If this is lower in the lru list,
12070- // we will push it in to the empty bucket .
12084+ // Assume process is hidden (has activities); we will correct
12085+ // later if this is not the case .
1207112086 adj = hiddenAdj;
1207212087 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
1207312088 app.hidden = true;
12074- app.empty = true;
12075- app.adjType = "bg-empty";
12089+ app.adjType = "bg-activities";
1207612090 }
1207712091
1207812092 boolean hasStoppingActivities = false;
@@ -12089,6 +12103,7 @@ private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
1208912103 }
1209012104 schedGroup = Process.THREAD_GROUP_DEFAULT;
1209112105 app.hidden = false;
12106+ app.hasActivities = true;
1209212107 foregroundActivities = true;
1209312108 break;
1209412109 } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED) {
@@ -12106,9 +12121,20 @@ private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
1210612121 foregroundActivities = true;
1210712122 hasStoppingActivities = true;
1210812123 }
12124+ if (r.app == app) {
12125+ app.hasActivities = true;
12126+ }
1210912127 }
1211012128 }
1211112129
12130+ if (adj == hiddenAdj && !app.hasActivities) {
12131+ // Whoops, this process is completely empty as far as we know
12132+ // at this point.
12133+ adj = emptyAdj;
12134+ app.empty = true;
12135+ app.adjType = "bg-empty";
12136+ }
12137+
1211212138 if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
1211312139 if (app.foregroundServices) {
1211412140 // The user is aware of this app, so make it visible.
@@ -12242,8 +12268,16 @@ private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
1224212268 myHiddenAdj = ProcessList.VISIBLE_APP_ADJ;
1224312269 }
1224412270 }
12245- clientAdj = computeOomAdjLocked(
12246- client, myHiddenAdj, TOP_APP, true, doingAll);
12271+ int myEmptyAdj = emptyAdj;
12272+ if (myEmptyAdj > client.emptyAdj) {
12273+ if (client.emptyAdj >= ProcessList.VISIBLE_APP_ADJ) {
12274+ myEmptyAdj = client.emptyAdj;
12275+ } else {
12276+ myEmptyAdj = ProcessList.VISIBLE_APP_ADJ;
12277+ }
12278+ }
12279+ clientAdj = computeOomAdjLocked(client, myHiddenAdj,
12280+ myEmptyAdj, TOP_APP, true, doingAll);
1224712281 String adjType = null;
1224812282 if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
1224912283 // Not doing bind OOM management, so treat
@@ -12382,8 +12416,16 @@ private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
1238212416 myHiddenAdj = ProcessList.FOREGROUND_APP_ADJ;
1238312417 }
1238412418 }
12385- int clientAdj = computeOomAdjLocked(
12386- client, myHiddenAdj, TOP_APP, true, doingAll);
12419+ int myEmptyAdj = emptyAdj;
12420+ if (myEmptyAdj > client.emptyAdj) {
12421+ if (client.emptyAdj > ProcessList.FOREGROUND_APP_ADJ) {
12422+ myEmptyAdj = client.emptyAdj;
12423+ } else {
12424+ myEmptyAdj = ProcessList.FOREGROUND_APP_ADJ;
12425+ }
12426+ }
12427+ int clientAdj = computeOomAdjLocked(client, myHiddenAdj,
12428+ myEmptyAdj, TOP_APP, true, doingAll);
1238712429 if (adj > clientAdj) {
1238812430 if (app.hasShownUi && app != mHomeProcess
1238912431 && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
@@ -12796,9 +12838,10 @@ final void checkExcessivePowerUsageLocked(boolean doKills) {
1279612838 }
1279712839 }
1279812840
12799- private final boolean updateOomAdjLocked(
12800- ProcessRecord app, int hiddenAdj , ProcessRecord TOP_APP, boolean doingAll) {
12841+ private final boolean updateOomAdjLocked(ProcessRecord app, int hiddenAdj,
12842+ int emptyAdj , ProcessRecord TOP_APP, boolean doingAll) {
1280112843 app.hiddenAdj = hiddenAdj;
12844+ app.emptyAdj = emptyAdj;
1280212845
1280312846 if (app.thread == null) {
1280412847 return false;
@@ -12808,7 +12851,7 @@ private final boolean updateOomAdjLocked(
1280812851
1280912852 boolean success = true;
1281012853
12811- computeOomAdjLocked(app, hiddenAdj, TOP_APP, false, doingAll);
12854+ computeOomAdjLocked(app, hiddenAdj, emptyAdj, TOP_APP, false, doingAll);
1281212855
1281312856 if (app.curRawAdj != app.setRawAdj) {
1281412857 if (wasKeeping && !app.keeping) {
@@ -12895,7 +12938,8 @@ final boolean updateOomAdjLocked(ProcessRecord app) {
1289512938
1289612939 mAdjSeq++;
1289712940
12898- boolean success = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP, false);
12941+ boolean success = updateOomAdjLocked(app, app.hiddenAdj, app.emptyAdj,
12942+ TOP_APP, false);
1289912943 final boolean nowHidden = app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
1290012944 && app.curAdj <= ProcessList.HIDDEN_APP_MAX_ADJ;
1290112945 if (nowHidden != wasHidden) {
@@ -12923,43 +12967,91 @@ final void updateOomAdjLocked() {
1292312967 // how many slots we have for background processes; we may want
1292412968 // to put multiple processes in a slot of there are enough of
1292512969 // them.
12926- int numSlots = ProcessList.HIDDEN_APP_MAX_ADJ - ProcessList.HIDDEN_APP_MIN_ADJ + 1;
12927- int factor = (mLruProcesses.size()-4)/numSlots;
12928- if (factor < 1) factor = 1;
12929- int step = 0;
12970+ int numSlots = (ProcessList.HIDDEN_APP_MAX_ADJ
12971+ - ProcessList.HIDDEN_APP_MIN_ADJ + 1) / 2;
12972+ int emptyFactor = (mLruProcesses.size()-mNumNonHiddenProcs-mNumHiddenProcs)/numSlots;
12973+ if (emptyFactor < 1) emptyFactor = 1;
12974+ int hiddenFactor = (mNumHiddenProcs > 0 ? mNumHiddenProcs : 1)/numSlots;
12975+ if (hiddenFactor < 1) hiddenFactor = 1;
12976+ int stepHidden = 0;
12977+ int stepEmpty = 0;
12978+ final int emptyProcessLimit = mProcessLimit > 1 ? mProcessLimit / 2 : mProcessLimit;
12979+ final int hiddenProcessLimit = mProcessLimit > 1 ? mProcessLimit / 2 : mProcessLimit;
1293012980 int numHidden = 0;
12981+ int numEmpty = 0;
1293112982 int numTrimming = 0;
12932-
12983+
12984+ mNumNonHiddenProcs = 0;
12985+ mNumHiddenProcs = 0;
12986+
1293312987 // First update the OOM adjustment for each of the
1293412988 // application processes based on their current state.
1293512989 int i = mLruProcesses.size();
1293612990 int curHiddenAdj = ProcessList.HIDDEN_APP_MIN_ADJ;
12991+ int nextHiddenAdj = curHiddenAdj+1;
12992+ int curEmptyAdj = ProcessList.HIDDEN_APP_MIN_ADJ;
12993+ int nextEmptyAdj = curEmptyAdj+2;
1293712994 while (i > 0) {
1293812995 i--;
1293912996 ProcessRecord app = mLruProcesses.get(i);
1294012997 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
12941- updateOomAdjLocked(app, curHiddenAdj, TOP_APP, true);
12942- if (curHiddenAdj < ProcessList.HIDDEN_APP_MAX_ADJ
12943- && app.curAdj == curHiddenAdj) {
12944- step++;
12945- if (step >= factor) {
12946- step = 0;
12947- curHiddenAdj++;
12948- }
12949- }
12998+ updateOomAdjLocked(app, curHiddenAdj, curEmptyAdj, TOP_APP, true);
1295012999 if (!app.killedBackground) {
12951- if (app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
13000+ if (app.curRawAdj == curHiddenAdj && app.hasActivities) {
13001+ // This process was assigned as a hidden process... step the
13002+ // hidden level.
13003+ mNumHiddenProcs++;
13004+ if (curHiddenAdj != nextHiddenAdj) {
13005+ stepHidden++;
13006+ if (stepHidden >= hiddenFactor) {
13007+ stepHidden = 0;
13008+ curHiddenAdj = nextHiddenAdj;
13009+ nextHiddenAdj += 2;
13010+ if (nextHiddenAdj > ProcessList.HIDDEN_APP_MAX_ADJ) {
13011+ nextHiddenAdj = ProcessList.HIDDEN_APP_MAX_ADJ;
13012+ }
13013+ }
13014+ }
1295213015 numHidden++;
12953- if (numHidden > mProcessLimit ) {
13016+ if (numHidden > hiddenProcessLimit ) {
1295413017 Slog.i(TAG, "No longer want " + app.processName
1295513018 + " (pid " + app.pid + "): hidden #" + numHidden);
1295613019 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
1295713020 app.processName, app.setAdj, "too many background");
1295813021 app.killedBackground = true;
1295913022 Process.killProcessQuiet(app.pid);
1296013023 }
13024+ } else {
13025+ if (app.curRawAdj == curEmptyAdj || app.curRawAdj == curHiddenAdj) {
13026+ // This process was assigned as an empty process... step the
13027+ // empty level.
13028+ if (curEmptyAdj != nextEmptyAdj) {
13029+ stepEmpty++;
13030+ if (stepEmpty >= emptyFactor) {
13031+ stepEmpty = 0;
13032+ curEmptyAdj = nextEmptyAdj;
13033+ nextEmptyAdj += 2;
13034+ if (nextEmptyAdj > ProcessList.HIDDEN_APP_MAX_ADJ) {
13035+ nextEmptyAdj = ProcessList.HIDDEN_APP_MAX_ADJ;
13036+ }
13037+ }
13038+ }
13039+ } else if (app.curRawAdj < ProcessList.HIDDEN_APP_MIN_ADJ) {
13040+ mNumNonHiddenProcs++;
13041+ }
13042+ if (app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
13043+ numEmpty++;
13044+ if (numEmpty > emptyProcessLimit) {
13045+ Slog.i(TAG, "No longer want " + app.processName
13046+ + " (pid " + app.pid + "): empty #" + numEmpty);
13047+ EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13048+ app.processName, app.setAdj, "too many background");
13049+ app.killedBackground = true;
13050+ Process.killProcessQuiet(app.pid);
13051+ }
13052+ }
1296113053 }
12962- if (!app.killedBackground && app.isolated && app.services.size() <= 0) {
13054+ if (app.isolated && app.services.size() <= 0) {
1296313055 // If this is an isolated process, and there are no
1296413056 // services running in it, then the process is no longer
1296513057 // needed. We agressively kill these because we can by
@@ -12989,18 +13081,20 @@ final void updateOomAdjLocked() {
1298913081 // are managing to keep around is less than half the maximum we desire;
1299013082 // if we are keeping a good number around, we'll let them use whatever
1299113083 // memory they want.
12992- if (numHidden <= (ProcessList.MAX_HIDDEN_APPS/2)) {
13084+ if (numHidden <= (ProcessList.MAX_HIDDEN_APPS/4)
13085+ && numEmpty <= (ProcessList.MAX_HIDDEN_APPS/4)) {
13086+ final int numHiddenAndEmpty = numHidden + numEmpty;
1299313087 final int N = mLruProcesses.size();
12994- factor = numTrimming/3;
13088+ int factor = numTrimming/3;
1299513089 int minFactor = 2;
1299613090 if (mHomeProcess != null) minFactor++;
1299713091 if (mPreviousProcess != null) minFactor++;
1299813092 if (factor < minFactor) factor = minFactor;
12999- step = 0;
13093+ int step = 0;
1300013094 int fgTrimLevel;
13001- if (numHidden <= (ProcessList.MAX_HIDDEN_APPS/5)) {
13095+ if (numHiddenAndEmpty <= (ProcessList.MAX_HIDDEN_APPS/5)) {
1300213096 fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
13003- } else if (numHidden <= (ProcessList.MAX_HIDDEN_APPS/3)) {
13097+ } else if (numHiddenAndEmpty <= (ProcessList.MAX_HIDDEN_APPS/3)) {
1300413098 fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
1300513099 } else {
1300613100 fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
0 commit comments