Loading services/java/com/android/server/am/ActiveServices.java +53 −2 Original line number Diff line number Diff line Loading @@ -564,7 +564,7 @@ public final class ActiveServices { if (r.isForeground) { r.isForeground = false; if (r.app != null) { mAm.updateLruProcessLocked(r.app, false, false); mAm.updateLruProcessLocked(r.app, false, null); updateServiceForegroundLocked(r.app, true); } } Loading Loading @@ -597,6 +597,42 @@ public final class ActiveServices { } } private boolean updateServiceClientActivitiesLocked(ProcessRecord proc, ConnectionRecord modCr) { if (modCr != null && modCr.binding.client != null) { if (modCr.binding.client.activities.size() <= 0) { // This connection is from a client without activities, so adding // and removing is not interesting. return false; } } boolean anyClientActivities = false; for (int i=proc.services.size()-1; i>=0 && !anyClientActivities; i--) { ServiceRecord sr = proc.services.valueAt(i); for (int conni=sr.connections.size()-1; conni>=0 && !anyClientActivities; conni--) { ArrayList<ConnectionRecord> clist = sr.connections.valueAt(conni); for (int cri=clist.size()-1; cri>=0; cri--) { ConnectionRecord cr = clist.get(cri); if (cr.binding.client == null || cr.binding.client == proc) { // Binding to ourself is not interesting. continue; } if (cr.binding.client.activities.size() > 0) { anyClientActivities = true; break; } } } } if (anyClientActivities != proc.hasClientActivities) { proc.hasClientActivities = anyClientActivities; mAm.updateLruProcessLocked(proc, anyClientActivities, null); return true; } return false; } int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, int flags, int userId) { Loading Loading @@ -698,6 +734,9 @@ public final class ActiveServices { if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) { b.client.hasAboveClient = true; } if (s.app != null) { updateServiceClientActivitiesLocked(s.app, c); } clist = mServiceConnections.get(binder); if (clist == null) { clist = new ArrayList<ConnectionRecord>(); Loading @@ -714,6 +753,7 @@ public final class ActiveServices { if (s.app != null) { // This could have made the service more important. mAm.updateLruProcessLocked(s.app, s.app.hasClientActivities, b.client); mAm.updateOomAdjLocked(s.app); } Loading Loading @@ -1316,7 +1356,8 @@ public final class ActiveServices { app.services.add(r); bumpServiceExecutingLocked(r, execInFg, "create"); mAm.updateLruProcessLocked(app, true, false); mAm.updateLruProcessLocked(app, false, null); mAm.updateOomAdjLocked(); boolean created = false; try { Loading Loading @@ -1601,6 +1642,9 @@ public final class ActiveServices { if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) { b.client.updateHasAboveClientLocked(); } if (s.app != null) { updateServiceClientActivitiesLocked(s.app, c); } } clist = mServiceConnections.get(binder); if (clist != null) { Loading @@ -1621,6 +1665,13 @@ public final class ActiveServices { && b.intent.hasBound) { try { bumpServiceExecutingLocked(s, false, "unbind"); if (b.client != s.app && (c.flags&Context.BIND_WAIVE_PRIORITY) == 0 && s.app.setProcState <= ActivityManager.PROCESS_STATE_RECEIVER) { // If this service's process is not already in the cached list, // then update it in the LRU list here because this may be causing // it to go down there and we want it to start out near the top. mAm.updateLruProcessLocked(s.app, false, null); } mAm.updateOomAdjLocked(s.app); b.intent.hasBound = false; // Assume the client doesn't want to know about a rebind; Loading services/java/com/android/server/am/ActivityManagerService.java +161 −69 Original line number Diff line number Diff line Loading @@ -34,7 +34,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; Loading Loading @@ -218,6 +217,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; Loading Loading @@ -1743,7 +1743,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( Loading Loading @@ -2269,7 +2270,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; } Loading @@ -2289,6 +2290,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; } Loading @@ -2306,8 +2309,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 Loading @@ -2321,8 +2325,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--; Loading @@ -2330,23 +2391,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) { 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 = mLruProcessActivityStart; } 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++; } Loading @@ -2357,23 +2486,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) { Loading Loading @@ -4831,7 +4956,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 Loading Loading @@ -7419,7 +7544,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); } } Loading Loading @@ -8028,7 +8153,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. Loading Loading @@ -10101,7 +10227,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; Loading Loading @@ -11857,7 +11983,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) { Loading Loading @@ -14079,7 +14205,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(); Loading @@ -14089,7 +14214,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; Loading @@ -14101,16 +14225,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) { Loading @@ -14121,7 +14241,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. Loading @@ -14138,7 +14257,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. Loading Loading @@ -14187,7 +14305,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) { Loading Loading @@ -14436,27 +14553,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 Loading Loading @@ -14674,6 +14770,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); Loading Loading @@ -15302,7 +15404,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--) { Loading @@ -15317,11 +15418,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) { Loading @@ -15331,24 +15436,8 @@ 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 Loading @@ -15358,6 +15447,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) { Loading
services/java/com/android/server/am/ActiveServices.java +53 −2 Original line number Diff line number Diff line Loading @@ -564,7 +564,7 @@ public final class ActiveServices { if (r.isForeground) { r.isForeground = false; if (r.app != null) { mAm.updateLruProcessLocked(r.app, false, false); mAm.updateLruProcessLocked(r.app, false, null); updateServiceForegroundLocked(r.app, true); } } Loading Loading @@ -597,6 +597,42 @@ public final class ActiveServices { } } private boolean updateServiceClientActivitiesLocked(ProcessRecord proc, ConnectionRecord modCr) { if (modCr != null && modCr.binding.client != null) { if (modCr.binding.client.activities.size() <= 0) { // This connection is from a client without activities, so adding // and removing is not interesting. return false; } } boolean anyClientActivities = false; for (int i=proc.services.size()-1; i>=0 && !anyClientActivities; i--) { ServiceRecord sr = proc.services.valueAt(i); for (int conni=sr.connections.size()-1; conni>=0 && !anyClientActivities; conni--) { ArrayList<ConnectionRecord> clist = sr.connections.valueAt(conni); for (int cri=clist.size()-1; cri>=0; cri--) { ConnectionRecord cr = clist.get(cri); if (cr.binding.client == null || cr.binding.client == proc) { // Binding to ourself is not interesting. continue; } if (cr.binding.client.activities.size() > 0) { anyClientActivities = true; break; } } } } if (anyClientActivities != proc.hasClientActivities) { proc.hasClientActivities = anyClientActivities; mAm.updateLruProcessLocked(proc, anyClientActivities, null); return true; } return false; } int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, int flags, int userId) { Loading Loading @@ -698,6 +734,9 @@ public final class ActiveServices { if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) { b.client.hasAboveClient = true; } if (s.app != null) { updateServiceClientActivitiesLocked(s.app, c); } clist = mServiceConnections.get(binder); if (clist == null) { clist = new ArrayList<ConnectionRecord>(); Loading @@ -714,6 +753,7 @@ public final class ActiveServices { if (s.app != null) { // This could have made the service more important. mAm.updateLruProcessLocked(s.app, s.app.hasClientActivities, b.client); mAm.updateOomAdjLocked(s.app); } Loading Loading @@ -1316,7 +1356,8 @@ public final class ActiveServices { app.services.add(r); bumpServiceExecutingLocked(r, execInFg, "create"); mAm.updateLruProcessLocked(app, true, false); mAm.updateLruProcessLocked(app, false, null); mAm.updateOomAdjLocked(); boolean created = false; try { Loading Loading @@ -1601,6 +1642,9 @@ public final class ActiveServices { if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) { b.client.updateHasAboveClientLocked(); } if (s.app != null) { updateServiceClientActivitiesLocked(s.app, c); } } clist = mServiceConnections.get(binder); if (clist != null) { Loading @@ -1621,6 +1665,13 @@ public final class ActiveServices { && b.intent.hasBound) { try { bumpServiceExecutingLocked(s, false, "unbind"); if (b.client != s.app && (c.flags&Context.BIND_WAIVE_PRIORITY) == 0 && s.app.setProcState <= ActivityManager.PROCESS_STATE_RECEIVER) { // If this service's process is not already in the cached list, // then update it in the LRU list here because this may be causing // it to go down there and we want it to start out near the top. mAm.updateLruProcessLocked(s.app, false, null); } mAm.updateOomAdjLocked(s.app); b.intent.hasBound = false; // Assume the client doesn't want to know about a rebind; Loading
services/java/com/android/server/am/ActivityManagerService.java +161 −69 Original line number Diff line number Diff line Loading @@ -34,7 +34,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; Loading Loading @@ -218,6 +217,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; Loading Loading @@ -1743,7 +1743,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( Loading Loading @@ -2269,7 +2270,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; } Loading @@ -2289,6 +2290,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; } Loading @@ -2306,8 +2309,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 Loading @@ -2321,8 +2325,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--; Loading @@ -2330,23 +2391,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) { 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 = mLruProcessActivityStart; } 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++; } Loading @@ -2357,23 +2486,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) { Loading Loading @@ -4831,7 +4956,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 Loading Loading @@ -7419,7 +7544,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); } } Loading Loading @@ -8028,7 +8153,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. Loading Loading @@ -10101,7 +10227,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; Loading Loading @@ -11857,7 +11983,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) { Loading Loading @@ -14079,7 +14205,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(); Loading @@ -14089,7 +14214,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; Loading @@ -14101,16 +14225,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) { Loading @@ -14121,7 +14241,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. Loading @@ -14138,7 +14257,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. Loading Loading @@ -14187,7 +14305,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) { Loading Loading @@ -14436,27 +14553,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 Loading Loading @@ -14674,6 +14770,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); Loading Loading @@ -15302,7 +15404,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--) { Loading @@ -15317,11 +15418,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) { Loading @@ -15331,24 +15436,8 @@ 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 Loading @@ -15358,6 +15447,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) {