Skip to content

Commit 1866f68

Browse files
Dianne HackbornAndroid (Google) Code Review
authored andcommitted
Merge "Modify how the background process LRU list is handled." into jb-mr1-dev
2 parents 87c42b9 + ee7621c commit 1866f68

File tree

2 files changed

+147
-48
lines changed

2 files changed

+147
-48
lines changed

services/java/com/android/server/am/ActivityManagerService.java

Lines changed: 140 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)