Merge "ActivityManagerService: explicitly break connection cycles" into pi-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
40ffa170ca
@@ -22995,18 +22995,27 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
private final int computeOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP,
|
||||
private final boolean computeOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP,
|
||||
boolean doingAll, long now) {
|
||||
if (mAdjSeq == app.adjSeq) {
|
||||
// This adjustment has already been computed.
|
||||
return app.curRawAdj;
|
||||
if (app.adjSeq == app.completedAdjSeq) {
|
||||
// This adjustment has already been computed successfully.
|
||||
return false;
|
||||
} else {
|
||||
// The process is being computed, so there is a cycle. We cannot
|
||||
// rely on this process's state.
|
||||
app.containsCycle = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (app.thread == null) {
|
||||
app.adjSeq = mAdjSeq;
|
||||
app.curSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
|
||||
app.curProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
|
||||
return (app.curAdj=app.curRawAdj=ProcessList.CACHED_APP_MAX_ADJ);
|
||||
app.curAdj=app.curRawAdj=ProcessList.CACHED_APP_MAX_ADJ;
|
||||
app.completedAdjSeq = app.adjSeq;
|
||||
return false;
|
||||
}
|
||||
|
||||
app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
|
||||
@@ -23019,6 +23028,8 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
final int appUid = app.info.uid;
|
||||
final int logUid = mCurOomAdjUid;
|
||||
|
||||
int prevAppAdj = app.curAdj;
|
||||
|
||||
if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {
|
||||
// The max adjustment doesn't allow this app to be anything
|
||||
// below foreground, so it is not worth doing work for it.
|
||||
@@ -23063,7 +23074,10 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
app.curSchedGroup = ProcessList.SCHED_GROUP_RESTRICTED;
|
||||
}
|
||||
}
|
||||
return (app.curAdj=app.maxAdj);
|
||||
app.curAdj = app.maxAdj;
|
||||
app.completedAdjSeq = app.adjSeq;
|
||||
// if curAdj is less than prevAppAdj, then this process was promoted
|
||||
return app.curAdj < prevAppAdj;
|
||||
}
|
||||
|
||||
app.systemNoUi = false;
|
||||
@@ -23075,6 +23089,8 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
int adj;
|
||||
int schedGroup;
|
||||
int procState;
|
||||
int cachedAdjSeq;
|
||||
|
||||
boolean foregroundActivities = false;
|
||||
mTmpBroadcastQueue.clear();
|
||||
if (PROCESS_STATE_CUR_TOP == ActivityManager.PROCESS_STATE_TOP && app == TOP_APP) {
|
||||
@@ -23388,9 +23404,9 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
// there are applications dependent on our services or providers, but
|
||||
// this gives us a baseline and makes sure we don't get into an
|
||||
// infinite recursion.
|
||||
app.adjSeq = mAdjSeq;
|
||||
app.curRawAdj = adj;
|
||||
app.hasStartedServices = false;
|
||||
app.adjSeq = mAdjSeq;
|
||||
|
||||
if (mBackupTarget != null && app == mBackupTarget.app) {
|
||||
// If possible we want to avoid killing apps while they're being backed up
|
||||
@@ -23489,8 +23505,15 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
|
||||
if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
|
||||
ProcessRecord client = cr.binding.client;
|
||||
int clientAdj = computeOomAdjLocked(client, cachedAdj,
|
||||
TOP_APP, doingAll, now);
|
||||
computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now);
|
||||
if (client.containsCycle) {
|
||||
// We've detected a cycle. We should ignore this connection and allow
|
||||
// this process to retry computeOomAdjLocked later in case a later-checked
|
||||
// connection from a client would raise its priority legitimately.
|
||||
app.containsCycle = true;
|
||||
continue;
|
||||
}
|
||||
int clientAdj = client.curRawAdj;
|
||||
int clientProcState = client.curProcState;
|
||||
if (clientProcState >= ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
|
||||
// If the other app is cached for any reason, for purposes here
|
||||
@@ -23709,7 +23732,15 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
// Being our own client is not interesting.
|
||||
continue;
|
||||
}
|
||||
int clientAdj = computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now);
|
||||
computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now);
|
||||
if (client.containsCycle) {
|
||||
// We've detected a cycle. We should ignore this connection and allow
|
||||
// this process to retry computeOomAdjLocked later in case a later-checked
|
||||
// connection from a client would raise its priority legitimately.
|
||||
app.containsCycle = true;
|
||||
continue;
|
||||
}
|
||||
int clientAdj = client.curRawAdj;
|
||||
int clientProcState = client.curProcState;
|
||||
if (clientProcState >= ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
|
||||
// If the other app is cached for any reason, for purposes here
|
||||
@@ -23937,8 +23968,10 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
app.curSchedGroup = schedGroup;
|
||||
app.curProcState = procState;
|
||||
app.foregroundActivities = foregroundActivities;
|
||||
app.completedAdjSeq = mAdjSeq;
|
||||
|
||||
return app.curRawAdj;
|
||||
// if curAdj is less than prevAppAdj, then this process was promoted
|
||||
return app.curAdj < prevAppAdj;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -24912,12 +24945,23 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
int nextCachedAdj = curCachedAdj+1;
|
||||
int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ;
|
||||
int nextEmptyAdj = curEmptyAdj+2;
|
||||
|
||||
boolean retryCycles = false;
|
||||
|
||||
// need to reset cycle state before calling computeOomAdjLocked because of service connections
|
||||
for (int i=N-1; i>=0; i--) {
|
||||
ProcessRecord app = mLruProcesses.get(i);
|
||||
app.containsCycle = false;
|
||||
}
|
||||
for (int i=N-1; i>=0; i--) {
|
||||
ProcessRecord app = mLruProcesses.get(i);
|
||||
if (!app.killedByAm && app.thread != null) {
|
||||
app.procStateChanged = false;
|
||||
computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now);
|
||||
|
||||
// if any app encountered a cycle, we need to perform an additional loop later
|
||||
retryCycles |= app.containsCycle;
|
||||
|
||||
// If we haven't yet assigned the final cached adj
|
||||
// to the process, do that now.
|
||||
if (app.curAdj >= ProcessList.UNKNOWN_ADJ) {
|
||||
@@ -24971,6 +25015,39 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Cycle strategy:
|
||||
// - Retry computing any process that has encountered a cycle.
|
||||
// - Continue retrying until no process was promoted.
|
||||
// - Iterate from least important to most important.
|
||||
int cycleCount = 0;
|
||||
while (retryCycles) {
|
||||
cycleCount++;
|
||||
retryCycles = false;
|
||||
|
||||
for (int i=0; i<N; i++) {
|
||||
ProcessRecord app = mLruProcesses.get(i);
|
||||
if (!app.killedByAm && app.thread != null && app.containsCycle == true) {
|
||||
app.adjSeq--;
|
||||
app.completedAdjSeq--;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<N; i++) {
|
||||
ProcessRecord app = mLruProcesses.get(i);
|
||||
if (!app.killedByAm && app.thread != null && app.containsCycle == true) {
|
||||
if (computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now)) {
|
||||
retryCycles = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i=N-1; i>=0; i--) {
|
||||
ProcessRecord app = mLruProcesses.get(i);
|
||||
if (!app.killedByAm && app.thread != null) {
|
||||
applyOomAdjLocked(app, true, now, nowElapsed);
|
||||
|
||||
// Count the number of process types.
|
||||
|
||||
@@ -149,6 +149,8 @@ final class ProcessRecord {
|
||||
String waitingToKill; // Process is waiting to be killed when in the bg, and reason
|
||||
Object forcingToImportant; // Token that is forcing this process to be important
|
||||
int adjSeq; // Sequence id for identifying oom_adj assignment cycles
|
||||
int completedAdjSeq; // Sequence id for identifying oom_adj assignment cycles
|
||||
boolean containsCycle; // Whether this app has encountered a cycle in the most recent update
|
||||
int lruSeq; // Sequence id for identifying LRU update cycles
|
||||
CompatibilityInfo compat; // last used compatibility mode
|
||||
IBinder.DeathRecipient deathRecipient; // Who is watching for the death.
|
||||
|
||||
Reference in New Issue
Block a user