diff options
Diffstat (limited to 'services/java/com/android/server/am/ActivityManagerService.java')
-rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 230 |
1 files changed, 161 insertions, 69 deletions
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 7cef0a4..844f464 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -33,7 +33,6 @@ import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IAppOpsService; import com.android.internal.app.ProcessStats; -import com.android.internal.app.ResolverActivity; import com.android.internal.os.BackgroundThread; import com.android.internal.os.BatteryStatsImpl; import com.android.internal.os.ProcessCpuTracker; @@ -217,6 +216,7 @@ public final class ActivityManagerService extends ActivityManagerNative static final boolean DEBUG_IMMERSIVE = localLOGV || false; static final boolean DEBUG_MU = localLOGV || false; static final boolean DEBUG_OOM_ADJ = localLOGV || false; + static final boolean DEBUG_LRU = localLOGV || false; static final boolean DEBUG_PAUSE = localLOGV || false; static final boolean DEBUG_POWER = localLOGV || false; static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false; @@ -1739,7 +1739,8 @@ public final class ActivityManagerService extends ActivityManagerNative synchronized (mSelf.mPidsSelfLocked) { mSelf.mPidsSelfLocked.put(app.pid, app); } - mSelf.updateLruProcessLocked(app, true, false); + mSelf.updateLruProcessLocked(app, false, null); + mSelf.updateOomAdjLocked(); } } catch (PackageManager.NameNotFoundException e) { throw new RuntimeException( @@ -2265,7 +2266,7 @@ public final class ActivityManagerService extends ActivityManagerNative int lrui = mLruProcesses.lastIndexOf(app); if (lrui < 0) { - Log.wtf(TAG, "Adding dependent process " + app + " not on LRU list: " + Slog.wtf(TAG, "Adding dependent process " + app + " not on LRU list: " + what + " " + obj + " from " + srcApp); return index; } @@ -2285,6 +2286,8 @@ public final class ActivityManagerService extends ActivityManagerNative if (index > 0) { index--; } + if (DEBUG_LRU) Slog.d(TAG, "Moving dep from " + lrui + " to " + index + + " in LRU list: " + app); mLruProcesses.add(index, app); return index; } @@ -2302,8 +2305,9 @@ public final class ActivityManagerService extends ActivityManagerNative } } - final void updateLruProcessLocked(ProcessRecord app, boolean oomAdj, boolean activityChange) { - final boolean hasActivity = app.activities.size() > 0; + final void updateLruProcessLocked(ProcessRecord app, boolean activityChange, + ProcessRecord client) { + final boolean hasActivity = app.activities.size() > 0 || app.hasClientActivities; final boolean hasService = false; // not impl yet. app.services.size() > 0; if (!activityChange && hasActivity) { // The process has activties, so we are only going to allow activity-based @@ -2317,8 +2321,65 @@ public final class ActivityManagerService extends ActivityManagerNative final long now = SystemClock.uptimeMillis(); app.lastActivityTime = now; + // First a quick reject: if the app is already at the position we will + // put it, then there is nothing to do. + if (hasActivity) { + final int N = mLruProcesses.size(); + if (N > 0 && mLruProcesses.get(N-1) == app) { + if (DEBUG_LRU) Slog.d(TAG, "Not moving, already top activity: " + app); + return; + } + } else { + if (mLruProcessServiceStart > 0 + && mLruProcesses.get(mLruProcessServiceStart-1) == app) { + if (DEBUG_LRU) Slog.d(TAG, "Not moving, already top other: " + app); + return; + } + } + int lrui = mLruProcesses.lastIndexOf(app); + if (app.persistent && lrui >= 0) { + // We don't care about the position of persistent processes, as long as + // they are in the list. + if (DEBUG_LRU) Slog.d(TAG, "Not moving, persistent: " + app); + return; + } + + /* In progress: compute new position first, so we can avoid doing work + if the process is not actually going to move. Not yet working. + int addIndex; + int nextIndex; + boolean inActivity = false, inService = false; + if (hasActivity) { + // Process has activities, put it at the very tipsy-top. + addIndex = mLruProcesses.size(); + nextIndex = mLruProcessServiceStart; + inActivity = true; + } else if (hasService) { + // Process has services, put it at the top of the service list. + addIndex = mLruProcessActivityStart; + nextIndex = mLruProcessServiceStart; + inActivity = true; + inService = true; + } else { + // Process not otherwise of interest, it goes to the top of the non-service area. + addIndex = mLruProcessServiceStart; + if (client != null) { + int clientIndex = mLruProcesses.lastIndexOf(client); + if (clientIndex < 0) Slog.d(TAG, "Unknown client " + client + " when updating " + + app); + if (clientIndex >= 0 && addIndex > clientIndex) { + addIndex = clientIndex; + } + } + nextIndex = addIndex > 0 ? addIndex-1 : addIndex; + } + + Slog.d(TAG, "Update LRU at " + lrui + " to " + addIndex + " (act=" + + mLruProcessActivityStart + "): " + app); + */ + if (lrui >= 0) { if (lrui < mLruProcessActivityStart) { mLruProcessActivityStart--; @@ -2326,23 +2387,91 @@ public final class ActivityManagerService extends ActivityManagerNative if (lrui < mLruProcessServiceStart) { mLruProcessServiceStart--; } + /* + if (addIndex > lrui) { + addIndex--; + } + if (nextIndex > lrui) { + nextIndex--; + } + */ mLruProcesses.remove(lrui); } + /* + mLruProcesses.add(addIndex, app); + if (inActivity) { + mLruProcessActivityStart++; + } + if (inService) { + mLruProcessActivityStart++; + } + */ + int nextIndex; if (hasActivity) { - // Process has activities, put it at the very tipsy-top. - mLruProcesses.add(app); - nextIndex = mLruProcessActivityStart; + final int N = mLruProcesses.size(); + if (app.activities.size() == 0 && mLruProcessActivityStart < (N-1)) { + // Process doesn't have activities, but has clients with + // activities... move it up, but one below the top (the top + // should always have a real activity). + if (DEBUG_LRU) Slog.d(TAG, "Adding to second-top of LRU activity list: " + app); + mLruProcesses.add(N-1, app); + // To keep it from spamming the LRU list (by making a bunch of clients), + // we will push down any other entries owned by the app. + final int uid = app.info.uid; + for (int i=N-2; i>mLruProcessActivityStart; i--) { + ProcessRecord subProc = mLruProcesses.get(i); + if (subProc.info.uid == uid) { + // We want to push this one down the list. If the process after + // it is for the same uid, however, don't do so, because we don't + // want them internally to be re-ordered. + if (mLruProcesses.get(i-1).info.uid != uid) { + if (DEBUG_LRU) Slog.d(TAG, "Pushing uid " + uid + " swapping at " + i + + ": " + mLruProcesses.get(i) + " : " + mLruProcesses.get(i-1)); + ProcessRecord tmp = mLruProcesses.get(i); + mLruProcesses.set(i, mLruProcesses.get(i-1)); + mLruProcesses.set(i-1, tmp); + i--; + } + } else { + // A gap, we can stop here. + break; + } + } + } else { + // Process has activities, put it at the very tipsy-top. + if (DEBUG_LRU) Slog.d(TAG, "Adding to top of LRU activity list: " + app); + mLruProcesses.add(app); + } + nextIndex = mLruProcessServiceStart; } else if (hasService) { // Process has services, put it at the top of the service list. + if (DEBUG_LRU) Slog.d(TAG, "Adding to top of LRU service list: " + app); mLruProcesses.add(mLruProcessActivityStart, app); nextIndex = mLruProcessServiceStart; mLruProcessActivityStart++; } else { // Process not otherwise of interest, it goes to the top of the non-service area. - mLruProcesses.add(mLruProcessServiceStart, app); - nextIndex = mLruProcessServiceStart-1; + int index = mLruProcessServiceStart; + if (client != null) { + // If there is a client, don't allow the process to be moved up higher + // in the list than that client. + int clientIndex = mLruProcesses.lastIndexOf(client); + if (DEBUG_LRU && clientIndex < 0) Slog.d(TAG, "Unknown client " + client + + " when updating " + app); + if (clientIndex <= lrui) { + // Don't allow the client index restriction to push it down farther in the + // list than it already is. + clientIndex = lrui; + } + if (clientIndex >= 0 && index > clientIndex) { + index = clientIndex; + } + } + if (DEBUG_LRU) Slog.d(TAG, "Adding at " + index + " of LRU list: " + app); + mLruProcesses.add(index, app); + nextIndex = index-1; mLruProcessActivityStart++; mLruProcessServiceStart++; } @@ -2353,23 +2482,19 @@ public final class ActivityManagerService extends ActivityManagerNative ConnectionRecord cr = app.connections.valueAt(j); if (cr.binding != null && !cr.serviceDead && cr.binding.service != null && cr.binding.service.app != null - && cr.binding.service.app.lruSeq != mLruSeq) { + && cr.binding.service.app.lruSeq != mLruSeq + && !cr.binding.service.app.persistent) { nextIndex = updateLruProcessInternalLocked(cr.binding.service.app, now, nextIndex, "service connection", cr, app); } } for (int j=app.conProviders.size()-1; j>=0; j--) { ContentProviderRecord cpr = app.conProviders.get(j).provider; - if (cpr.proc != null && cpr.proc.lruSeq != mLruSeq) { + if (cpr.proc != null && cpr.proc.lruSeq != mLruSeq && !cpr.proc.persistent) { nextIndex = updateLruProcessInternalLocked(cpr.proc, now, nextIndex, "provider reference", cpr, app); } } - - //Slog.i(TAG, "Putting proc to front: " + app.processName); - if (oomAdj) { - updateOomAdjLocked(); - } } final ProcessRecord getProcessRecordLocked(String processName, int uid, boolean keepIfLarge) { @@ -4826,7 +4951,7 @@ public final class ActivityManagerService extends ActivityManagerNative isRestrictedBackupMode || !normalMode, app.persistent, new Configuration(mConfiguration), app.compat, getCommonServicesLocked(), mCoreSettingsObserver.getCoreSettingsLocked()); - updateLruProcessLocked(app, false, false); + updateLruProcessLocked(app, false, null); app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis(); } catch (Exception e) { // todo: Yikes! What should we do? For now we will try to @@ -7414,7 +7539,7 @@ public final class ActivityManagerService extends ActivityManagerNative // make sure to count it as being accessed and thus // back up on the LRU list. This is good because // content providers are often expensive to start. - updateLruProcessLocked(cpr.proc, false, false); + updateLruProcessLocked(cpr.proc, false, null); } } @@ -8023,7 +8148,8 @@ public final class ActivityManagerService extends ActivityManagerNative if (isolated) { mIsolatedProcesses.put(app.uid, app); } - updateLruProcessLocked(app, true, false); + updateLruProcessLocked(app, false, null); + updateOomAdjLocked(); } // This package really, really can not be stopped. @@ -10095,7 +10221,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (app.persistent) { outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT; } - if (app.hasActivities) { + if (app.activities.size() > 0) { outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_HAS_ACTIVITIES; } outInfo.lastTrimLevel = app.trimMemoryLevel; @@ -11851,7 +11977,7 @@ public final class ActivityManagerService extends ActivityManagerNative thread = r.thread; pid = r.pid; oomAdj = r.getSetAdjWithServices(); - hasActivities = r.hasActivities; + hasActivities = r.activities.size() > 0; } if (thread != null) { if (!isCheckinRequest && dumpDetails) { @@ -14073,7 +14199,6 @@ public final class ActivityManagerService extends ActivityManagerNative app.adjTarget = null; app.empty = false; app.cached = false; - app.hasClientActivities = false; final int activitiesSize = app.activities.size(); @@ -14083,7 +14208,6 @@ public final class ActivityManagerService extends ActivityManagerNative app.adjType = "fixed"; app.adjSeq = mAdjSeq; app.curRawAdj = app.maxAdj; - app.hasActivities = false; app.foregroundActivities = false; app.keeping = true; app.curSchedGroup = Process.THREAD_GROUP_DEFAULT; @@ -14095,16 +14219,12 @@ public final class ActivityManagerService extends ActivityManagerNative app.systemNoUi = true; if (app == TOP_APP) { app.systemNoUi = false; - app.hasActivities = true; } else if (activitiesSize > 0) { for (int j = 0; j < activitiesSize; j++) { final ActivityRecord r = app.activities.get(j); if (r.visible) { app.systemNoUi = false; } - if (r.app == app) { - app.hasActivities = true; - } } } if (!app.systemNoUi) { @@ -14115,7 +14235,6 @@ public final class ActivityManagerService extends ActivityManagerNative app.keeping = false; app.systemNoUi = false; - app.hasActivities = false; // Determine the importance of the process, starting with most // important to least, and assign an appropriate OOM adjustment. @@ -14132,7 +14251,6 @@ public final class ActivityManagerService extends ActivityManagerNative app.adjType = "top-activity"; foregroundActivities = true; interesting = true; - app.hasActivities = true; procState = ActivityManager.PROCESS_STATE_TOP; } else if (app.instrumentationClass != null) { // Don't want to kill running instrumentation. @@ -14181,7 +14299,6 @@ public final class ActivityManagerService extends ActivityManagerNative + app + "?!?"); continue; } - app.hasActivities = true; if (r.visible) { // App has a visible activity; only upgrade adjustment. if (adj > ProcessList.VISIBLE_APP_ADJ) { @@ -14430,27 +14547,6 @@ public final class ActivityManagerService extends ActivityManagerNative clientAdj = adj; } } - } else if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) { - if ((cr.flags&Context.BIND_NOT_VISIBLE) == 0) { - // If this connection is keeping the service - // created, then we want to try to better follow - // its memory management semantics for activities. - // That is, if it is sitting in the background - // LRU list as a cached process (with activities), - // we don't want the service it is connected to - // to go into the empty LRU and quickly get killed, - // because all we'll do is just end up restarting - // the service. - if (client.hasActivities) { - if (procState > - ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT) { - procState = - ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT; - app.adjType = "cch-client-act"; - } - app.hasClientActivities = true; - } - } } if (adj > clientAdj) { // If this process has recently shown UI, and @@ -14668,6 +14764,12 @@ public final class ActivityManagerService extends ActivityManagerNative } } + if (procState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY && app.hasClientActivities) { + // This is a cached process, but with client activities. Mark it so. + procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT; + app.adjType = "cch-client-act"; + } + if (adj == ProcessList.SERVICE_ADJ) { if (doingAll) { app.serviceb = mNewNumAServiceProcs > (mNumServiceProcs/3); @@ -15296,7 +15398,6 @@ public final class ActivityManagerService extends ActivityManagerNative // application processes based on their current state. int curCachedAdj = ProcessList.CACHED_APP_MIN_ADJ; int nextCachedAdj = curCachedAdj+1; - int curClientCachedAdj = curCachedAdj+1; int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ; int nextEmptyAdj = curEmptyAdj+2; for (int i=N-1; i>=0; i--) { @@ -15311,11 +15412,15 @@ public final class ActivityManagerService extends ActivityManagerNative if (app.curAdj >= ProcessList.UNKNOWN_ADJ) { switch (app.curProcState) { case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY: + case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT: // This process is a cached process holding activities... // assign it the next cached value for that type, and then // step that cached level. app.curRawAdj = curCachedAdj; app.curAdj = app.modifyRawOomAdj(curCachedAdj); + if (DEBUG_LRU && false) Slog.d(TAG, "Assigning activity LRU #" + i + + " adj: " + app.curAdj + " (curCachedAdj=" + curCachedAdj + + ")"); if (curCachedAdj != nextCachedAdj) { stepCached++; if (stepCached >= cachedFactor) { @@ -15325,25 +15430,9 @@ public final class ActivityManagerService extends ActivityManagerNative if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) { nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ; } - if (curClientCachedAdj <= curCachedAdj) { - curClientCachedAdj = curCachedAdj + 1; - if (curClientCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) { - curClientCachedAdj = ProcessList.CACHED_APP_MAX_ADJ; - } - } } } break; - case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT: - // Special case for cached client processes... just step - // down from after regular cached processes. - app.curRawAdj = curClientCachedAdj; - app.curAdj = app.modifyRawOomAdj(curClientCachedAdj); - curClientCachedAdj++; - if (curClientCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) { - curClientCachedAdj = ProcessList.CACHED_APP_MAX_ADJ; - } - break; default: // For everything else, assign next empty cached process // level and bump that up. Note that this means that @@ -15352,6 +15441,9 @@ public final class ActivityManagerService extends ActivityManagerNative // state is still as a service), which is what we want. app.curRawAdj = curEmptyAdj; app.curAdj = app.modifyRawOomAdj(curEmptyAdj); + if (DEBUG_LRU && false) Slog.d(TAG, "Assigning empty LRU #" + i + + " adj: " + app.curAdj + " (curEmptyAdj=" + curEmptyAdj + + ")"); if (curEmptyAdj != nextEmptyAdj) { stepEmpty++; if (stepEmpty >= emptyFactor) { |