summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2012-04-10 15:25:43 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2012-04-10 15:25:43 -0700
commit2a854c13f864d5493846a7fc66bb6aefeaac8c8b (patch)
treeebd489d95dd9276e93a92f33af507c321c6d7a97 /services
parent4245ab34d12cf7d608f1789981326d9009cc304f (diff)
parent162bc0ea0d7862b92f18d0ce47310a85304205f7 (diff)
downloadframeworks_base-2a854c13f864d5493846a7fc66bb6aefeaac8c8b.zip
frameworks_base-2a854c13f864d5493846a7fc66bb6aefeaac8c8b.tar.gz
frameworks_base-2a854c13f864d5493846a7fc66bb6aefeaac8c8b.tar.bz2
Merge "Some small tweaks to improve memory management."
Diffstat (limited to 'services')
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java92
-rw-r--r--services/java/com/android/server/am/ActivityStack.java78
-rw-r--r--services/java/com/android/server/am/ProcessRecord.java2
3 files changed, 104 insertions, 68 deletions
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 42c42c9..78b441a 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -13444,7 +13444,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// an earlier hidden adjustment that isn't really for us... if
// so, use the new hidden adjustment.
if (!recursed && app.hidden) {
- app.curAdj = app.curRawAdj = hiddenAdj;
+ app.curAdj = app.curRawAdj = app.nonStoppingAdj = hiddenAdj;
}
return app.curRawAdj;
}
@@ -13468,7 +13468,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// below foreground, so it is not worth doing work for it.
app.adjType = "fixed";
app.adjSeq = mAdjSeq;
- app.curRawAdj = app.maxAdj;
+ app.curRawAdj = app.nonStoppingAdj = app.maxAdj;
app.foregroundActivities = false;
app.keeping = true;
app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
@@ -13545,6 +13545,8 @@ public final class ActivityManagerService extends ActivityManagerNative
app.adjType = "bg-empty";
}
+ boolean hasStoppingActivities = false;
+
// Examine all activities if not already foreground.
if (!app.foregroundActivities && activitiesSize > 0) {
for (int j = 0; j < activitiesSize; j++) {
@@ -13559,15 +13561,20 @@ public final class ActivityManagerService extends ActivityManagerNative
app.hidden = false;
app.foregroundActivities = true;
break;
- } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED
- || r.state == ActivityState.STOPPING) {
- // Only upgrade adjustment.
+ } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED) {
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
- app.adjType = "stopping";
+ app.adjType = "pausing";
}
app.hidden = false;
app.foregroundActivities = true;
+ } else if (r.state == ActivityState.STOPPING) {
+ // We will apply the actual adjustment later, because
+ // we want to allow this process to immediately go through
+ // any memory trimming that is in effect.
+ app.hidden = false;
+ app.foregroundActivities = true;
+ hasStoppingActivities = true;
}
}
}
@@ -13625,7 +13632,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// this gives us a baseline and makes sure we don't get into an
// infinite recursion.
app.adjSeq = mAdjSeq;
- app.curRawAdj = adj;
+ app.curRawAdj = app.nonStoppingAdj = adj;
if (mBackupTarget != null && app == mBackupTarget.app) {
// If possible we want to avoid killing apps while they're being backed up
@@ -13882,6 +13889,28 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
+ if (adj == ProcessList.SERVICE_ADJ) {
+ if (doingAll) {
+ app.serviceb = mNewNumServiceProcs > (mNumServiceProcs/3);
+ mNewNumServiceProcs++;
+ }
+ if (app.serviceb) {
+ adj = ProcessList.SERVICE_B_ADJ;
+ }
+ } else {
+ app.serviceb = false;
+ }
+
+ app.nonStoppingAdj = adj;
+
+ if (hasStoppingActivities) {
+ // Only upgrade adjustment.
+ if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
+ adj = ProcessList.PERCEPTIBLE_APP_ADJ;
+ app.adjType = "stopping";
+ }
+ }
+
app.curRawAdj = adj;
//Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
@@ -13915,18 +13944,6 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- if (adj == ProcessList.SERVICE_ADJ) {
- if (doingAll) {
- app.serviceb = mNewNumServiceProcs > (mNumServiceProcs/3);
- mNewNumServiceProcs++;
- }
- if (app.serviceb) {
- adj = ProcessList.SERVICE_B_ADJ;
- }
- } else {
- app.serviceb = false;
- }
-
app.curAdj = adj;
app.curSchedGroup = schedGroup;
@@ -14138,7 +14155,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
// If a process has held a wake lock for more
// than 50% of the time during this period,
- // that sounds pad. Kill!
+ // that sounds bad. Kill!
if (doWakeKills && realtimeSince > 0
&& ((wtimeUsed*100)/realtimeSince) >= 50) {
synchronized (stats) {
@@ -14186,23 +14203,6 @@ public final class ActivityManagerService extends ActivityManagerNative
computeOomAdjLocked(app, hiddenAdj, TOP_APP, false, doingAll);
if (app.curRawAdj != app.setRawAdj) {
- if (false) {
- // Removing for now. Forcing GCs is not so useful anymore
- // with Dalvik, and the new memory level hint facility is
- // better for what we need to do these days.
- if (app.curRawAdj > ProcessList.FOREGROUND_APP_ADJ
- && app.setRawAdj <= ProcessList.FOREGROUND_APP_ADJ) {
- // If this app is transitioning from foreground to
- // non-foreground, have it do a gc.
- scheduleAppGcLocked(app);
- } else if (app.curRawAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
- && app.setRawAdj < ProcessList.HIDDEN_APP_MIN_ADJ) {
- // Likewise do a gc when an app is moving in to the
- // background (such as a service stopping).
- scheduleAppGcLocked(app);
- }
- }
-
if (wasKeeping && !app.keeping) {
// This app is no longer something we want to keep. Note
// its current wake lock time to later know to kill it if
@@ -14319,6 +14319,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (factor < 1) factor = 1;
int step = 0;
int numHidden = 0;
+ int numTrimming = 0;
// First update the OOM adjustment for each of the
// application processes based on their current state.
@@ -14363,6 +14364,11 @@ public final class ActivityManagerService extends ActivityManagerNative
app.killedBackground = true;
Process.killProcessQuiet(app.pid);
}
+ if (app.nonStoppingAdj >= ProcessList.HOME_APP_ADJ
+ && app.nonStoppingAdj != ProcessList.SERVICE_B_ADJ
+ && !app.killedBackground) {
+ numTrimming++;
+ }
}
}
@@ -14376,7 +14382,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// memory they want.
if (numHidden <= (ProcessList.MAX_HIDDEN_APPS/2)) {
final int N = mLruProcesses.size();
- factor = numHidden/3;
+ factor = numTrimming/3;
int minFactor = 2;
if (mHomeProcess != null) minFactor++;
if (mPreviousProcess != null) minFactor++;
@@ -14393,8 +14399,8 @@ public final class ActivityManagerService extends ActivityManagerNative
int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
for (i=0; i<N; i++) {
ProcessRecord app = mLruProcesses.get(i);
- if (app.curAdj >= ProcessList.HOME_APP_ADJ
- && app.curAdj != ProcessList.SERVICE_B_ADJ
+ if (app.nonStoppingAdj >= ProcessList.HOME_APP_ADJ
+ && app.nonStoppingAdj != ProcessList.SERVICE_B_ADJ
&& !app.killedBackground) {
if (app.trimMemoryLevel < curLevel && app.thread != null) {
try {
@@ -14426,7 +14432,7 @@ public final class ActivityManagerService extends ActivityManagerNative
break;
}
}
- } else if (app.curAdj == ProcessList.HEAVY_WEIGHT_APP_ADJ) {
+ } else if (app.nonStoppingAdj == ProcessList.HEAVY_WEIGHT_APP_ADJ) {
if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
&& app.thread != null) {
try {
@@ -14437,7 +14443,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
} else {
- if ((app.curAdj > ProcessList.VISIBLE_APP_ADJ || app.systemNoUi)
+ if ((app.nonStoppingAdj > ProcessList.VISIBLE_APP_ADJ || app.systemNoUi)
&& app.pendingUiClean) {
// If this application is now in the background and it
// had done UI, then give it the special trim level to
@@ -14464,7 +14470,7 @@ public final class ActivityManagerService extends ActivityManagerNative
final int N = mLruProcesses.size();
for (i=0; i<N; i++) {
ProcessRecord app = mLruProcesses.get(i);
- if ((app.curAdj > ProcessList.VISIBLE_APP_ADJ || app.systemNoUi)
+ if ((app.nonStoppingAdj > ProcessList.VISIBLE_APP_ADJ || app.systemNoUi)
&& app.pendingUiClean) {
if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
&& app.thread != null) {
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index a01ed25..6596e1f 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -97,6 +97,11 @@ final class ActivityStack {
// next activity.
static final int PAUSE_TIMEOUT = 500;
+ // How long we wait for the activity to tell us it has stopped before
+ // giving up. This is a good amount of time because we really need this
+ // from the application in order to get its saved state.
+ static final int STOP_TIMEOUT = 10*1000;
+
// How long we can hold the sleep wake lock before giving up.
static final int SLEEP_TIMEOUT = 5*1000;
@@ -280,6 +285,7 @@ final class ActivityStack {
static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 5;
static final int RESUME_TOP_ACTIVITY_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 6;
static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 7;
+ static final int STOP_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 8;
final Handler mHandler = new Handler() {
//public Handler() {
@@ -364,6 +370,17 @@ final class ActivityStack {
resumeTopActivityLocked(null);
}
} break;
+ case STOP_TIMEOUT_MSG: {
+ ActivityRecord r = (ActivityRecord)msg.obj;
+ // We don't at this point know if the activity is fullscreen,
+ // so we need to be conservative and assume it isn't.
+ Slog.w(TAG, "Activity stop timeout for " + r);
+ synchronized (mService) {
+ if (r.isInHistory()) {
+ activityStoppedLocked(r, null, null, null);
+ }
+ }
+ } break;
}
}
};
@@ -1000,31 +1017,38 @@ final class ActivityStack {
final void activityStoppedLocked(ActivityRecord r, Bundle icicle, Bitmap thumbnail,
CharSequence description) {
if (DEBUG_SAVED_STATE) Slog.i(TAG, "Saving icicle of " + r + ": " + icicle);
- r.icicle = icicle;
- r.haveState = true;
- r.updateThumbnail(thumbnail, description);
- r.stopped = true;
- if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r + " (stop complete)");
- r.state = ActivityState.STOPPED;
- if (!r.finishing) {
- if (r.configDestroy) {
- destroyActivityLocked(r, true, false, "stop-config");
- resumeTopActivityLocked(null);
- } else {
- // Now that this process has stopped, we may want to consider
- // it to be the previous app to try to keep around in case
- // the user wants to return to it.
- ProcessRecord fgApp = null;
- if (mResumedActivity != null) {
- fgApp = mResumedActivity.app;
- } else if (mPausingActivity != null) {
- fgApp = mPausingActivity.app;
- }
- if (r.app != null && fgApp != null && r.app != fgApp
- && r.lastVisibleTime > mService.mPreviousProcessVisibleTime
- && r.app != mService.mHomeProcess) {
- mService.mPreviousProcess = r.app;
- mService.mPreviousProcessVisibleTime = r.lastVisibleTime;
+ if (icicle != null) {
+ // If icicle is null, this is happening due to a timeout, so we
+ // haven't really saved the state.
+ r.icicle = icicle;
+ r.haveState = true;
+ r.updateThumbnail(thumbnail, description);
+ }
+ if (!r.stopped) {
+ if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r + " (stop complete)");
+ mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
+ r.stopped = true;
+ r.state = ActivityState.STOPPED;
+ if (!r.finishing) {
+ if (r.configDestroy) {
+ destroyActivityLocked(r, true, false, "stop-config");
+ resumeTopActivityLocked(null);
+ } else {
+ // Now that this process has stopped, we may want to consider
+ // it to be the previous app to try to keep around in case
+ // the user wants to return to it.
+ ProcessRecord fgApp = null;
+ if (mResumedActivity != null) {
+ fgApp = mResumedActivity.app;
+ } else if (mPausingActivity != null) {
+ fgApp = mPausingActivity.app;
+ }
+ if (r.app != null && fgApp != null && r.app != fgApp
+ && r.lastVisibleTime > mService.mPreviousProcessVisibleTime
+ && r.app != mService.mHomeProcess) {
+ mService.mPreviousProcess = r.app;
+ mService.mPreviousProcessVisibleTime = r.lastVisibleTime;
+ }
}
}
}
@@ -3228,6 +3252,9 @@ final class ActivityStack {
if (mService.isSleeping()) {
r.setSleeping(true);
}
+ Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG);
+ msg.obj = r;
+ mHandler.sendMessageDelayed(msg, STOP_TIMEOUT);
} catch (Exception e) {
// Maybe just ignore exceptions here... if the process
// has crashed, our death notification will clean things
@@ -3694,6 +3721,7 @@ final class ActivityStack {
// Get rid of any pending idle timeouts.
mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
+ mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
r.finishLaunchTickingLocked();
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index b64261d..4529ecc 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -63,6 +63,7 @@ class ProcessRecord {
int hiddenAdj; // If hidden, this is the adjustment to use
int curRawAdj; // Current OOM unlimited adjustment for this process
int setRawAdj; // Last set OOM unlimited adjustment for this process
+ int nonStoppingAdj; // Adjustment not counting any stopping activities
int curAdj; // Current OOM adjustment for this process
int setAdj; // Last set OOM adjustment for this process
int curSchedGroup; // Currently desired scheduling class
@@ -199,6 +200,7 @@ class ProcessRecord {
pw.print(" hidden="); pw.print(hiddenAdj);
pw.print(" curRaw="); pw.print(curRawAdj);
pw.print(" setRaw="); pw.print(setRawAdj);
+ pw.print(" nonStopping="); pw.print(nonStoppingAdj);
pw.print(" cur="); pw.print(curAdj);
pw.print(" set="); pw.println(setAdj);
pw.print(prefix); pw.print("curSchedGroup="); pw.print(curSchedGroup);