ActivityManager中提供了几种方式来杀进程,比如有forceStopPackage、removeTask、killBackgroundProcesses等。
下面我们就来看看它们的背后都做了些什么。
我们之前已经写了一篇《关于Android的浅杀》来介绍这个方法的变迁,大家可以回忆一下找找感觉。
复习一下removeTask的好处是,相对后面几个,它的逻辑要简单得多。
这是目前(截止至API24)唯一官方公开建议使用的方法,其它的都是隐藏的API。
我们先看一张这个API背后调用的简图:
另外有一个被废弃的restartPackage方法,现在只是killBackgroundProcesses的马甲。
2400 @Deprecated
2401 public void restartPackage(String packageName) {
2402 killBackgroundProcesses(packageName);
2403 }
调用killBackgroundProcesses需要权限android.Manifest.permission.KILL_BACKGROUND_PROCESSES
按照惯例,这个方法肯定是通过IPC调用到AMS中:
2418 public void killBackgroundProcesses(String packageName) {
2419 try {
2420 ActivityManagerNative.getDefault().killBackgroundProcesses(packageName,
2421 UserHandle.myUserId());
2422 } catch (RemoteException e) {
2423 }
2424 }
我们直接来看AMS中的killBackgroundProcesses:
5202 @Override
5203 public void killBackgroundProcesses(final String packageName, int userId) {
首先就是检查KILL_BACKGROUND_PROCESSES的权限:
5204 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
5205 != PackageManager.PERMISSION_GRANTED &&
5206 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
5207 != PackageManager.PERMISSION_GRANTED) {
5208 String msg = "Permission Denial: killBackgroundProcesses() from pid="
5209 + Binder.getCallingPid()
5210 + ", uid=" + Binder.getCallingUid()
5211 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
5212 Slog.w(TAG, msg);
5213 throw new SecurityException(msg);
5214 }
5215
下面正式开始干活:
5216 userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
5217 userId, true, ALLOW_FULL_ONLY, "killBackgroundProcesses", null);
5218 long callingId = Binder.clearCallingIdentity();
5219 try {
5220 IPackageManager pm = AppGlobals.getPackageManager();
5221 synchronized(this) {
5222 int appId = -1;
5223 try {
5224 appId = UserHandle.getAppId(pm.getPackageUid(packageName, 0));
5225 } catch (RemoteException e) {
5226 }
5227 if (appId == -1) {
5228 Slog.w(TAG, "Invalid packageName: " + packageName);
5229 return;
5230 }
真正的逻辑都在killPackageProcessesLocked中。调用进来的时候只有包名和用户ID两个参数,但是killPackageProcessesLocked却搞出来9个参数。
5231 killPackageProcessesLocked(packageName, appId, userId,
5232 ProcessList.SERVICE_ADJ, false, true, true, false, "kill background");
5233 }
5234 } finally {
5235 Binder.restoreCallingIdentity(callingId);
5236 }
5237 }
5541 private final boolean killPackageProcessesLocked(String packageName, int appId,
5542 int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart,
5543 boolean doit, boolean evenPersistent, String reason) {
5544 ArrayList procs = new ArrayList<>();
5545
5546 // Remove all processes this package may have touched: all with the
5547 // same UID (except for the system or root user), and all whose name
5548 // matches the package name.
5549 final int NP = mProcessNames.getMap().size();
5550 for (int ip=0; ip5551 SparseArray apps = mProcessNames.getMap().valueAt(ip);
5552 final int NA = apps.size();
5553 for (int ia=0; ia5554 ProcessRecord app = apps.valueAt(ia);
5555 if (app.persistent && !evenPersistent) {
5556 // we don't kill persistent processes
5557 continue;
5558 }
5559 if (app.removed) {
5560 if (doit) {
5561 procs.add(app);
5562 }
5563 continue;
5564 }
5565
5566 // Skip process if it doesn't meet our oom adj requirement.
5567 if (app.setAdj < minOomAdj) {
5568 continue;
5569 }
5570
5571 // If no package is specified, we call all processes under the
5572 // give user id.
5573 if (packageName == null) {
5574 if (userId != UserHandle.USER_ALL && app.userId != userId) {
5575 continue;
5576 }
5577 if (appId >= 0 && UserHandle.getAppId(app.uid) != appId) {
5578 continue;
5579 }
5580 // Package has been specified, we want to hit all processes
5581 // that match it. We need to qualify this by the processes
5582 // that are running under the specified app and user ID.
5583 } else {
5584 final boolean isDep = app.pkgDeps != null
5585 && app.pkgDeps.contains(packageName);
5586 if (!isDep && UserHandle.getAppId(app.uid) != appId) {
5587 continue;
5588 }
5589 if (userId != UserHandle.USER_ALL && app.userId != userId) {
5590 continue;
5591 }
5592 if (!app.pkgList.containsKey(packageName) && !isDep) {
5593 continue;
5594 }
5595 }
5596
5597 // Process has passed all conditions, kill it!
5598 if (!doit) {
5599 return true;
5600 }
5601 app.removed = true;
5602 procs.add(app);
5603 }
5604 }
前面各种条件都准备好了之后,针对每一个proc去调用removeProcessLocked.
5606 int N = procs.size();
5607 for (int i=0; i5608 removeProcessLocked(procs.get(i), callerWillRestart, allowRestart, reason);
5609 }
5610 updateOomAdjLocked();
5611 return N > 0;
5612 }
5916 private final boolean removeProcessLocked(ProcessRecord app,
5917 boolean callerWillRestart, boolean allowRestart, String reason) {
5918 final String name = app.processName;
5919 final int uid = app.uid;
...
下面再调用两个参数的removeProcessNameLocked.
5923 removeProcessNameLocked(name, uid);
5924 if (mHeavyWeightProcess == app) {
5925 mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
5926 mHeavyWeightProcess.userId, 0));
5927 mHeavyWeightProcess = null;
5928 }
5929 boolean needRestart = false;
5930 if (app.pid > 0 && app.pid != MY_PID) {
5931 int pid = app.pid;
5932 synchronized (mPidsSelfLocked) {
5933 mPidsSelfLocked.remove(pid);
5934 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5935 }
5936 mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
5937 if (app.isolated) {
5938 mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
5939 }
5940 boolean willRestart = false;
5941 if (app.persistent && !app.isolated) {
5942 if (!callerWillRestart) {
5943 willRestart = true;
5944 } else {
5945 needRestart = true;
5946 }
5947 }
前面的该通知的都通知到了,终于可以正式开杀了。
5948 app.kill(reason, true);
5949 handleAppDiedLocked(app, willRestart, allowRestart);
5950 if (willRestart) {
5951 removeLruProcessLocked(app);
5952 addAppLocked(app.info, false, null /* ABI override */);
5953 }
5954 } else {
5955 mRemovedProcesses.add(app);
5956 }
5957
5958 return needRestart;
5959 }
543 void kill(String reason, boolean noisy) {
544 if (!killedByAm) {
545 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "kill");
546 if (noisy) {
547 Slog.i(TAG, "Killing " + toShortString() + " (adj " + setAdj + "): " + reason);
548 }
549 EventLog.writeEvent(EventLogTags.AM_KILL, userId, pid, processName, setAdj, reason);
550 Process.killProcessQuiet(pid);
551 Process.killProcessGroup(info.uid, pid);
552 if (!persistent) {
553 killed = true;
554 killedByAm = true;
555 }
556 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
557 }
558 }
非常省事儿,发给一个SIGNAL_KILL出去就是了。
1068 public static final void killProcessQuiet(int pid) {
1069 sendSignalQuiet(pid, SIGNAL_KILL);
1070 }
这个直接用native写的。
public static final native int killProcessGroup(int uid, int pid);
JNI函数只是一个简单地对libprocessgroup中的killProcessGroup的封装
1035jint android_os_Process_killProcessGroup(JNIEnv* env, jobject clazz, jint uid, jint pid)
1036{
1037 return killProcessGroup(uid, pid, SIGKILL);
1038}
这是我们的逻辑头一次走进/system/core/中,位于/system/core/libprocessgroup/processgroup.cpp
252int killProcessGroup(uid_t uid, int initialPid, int signal)
253{
254 int processes;
255 const int sleep_us = 5 * 1000; // 5ms
256 int64_t startTime = android::uptimeMillis();
257 int retry = 40;
258
259 while ((processes = killProcessGroupOnce(uid, initialPid, signal)) > 0) {
260 SLOGV("killed %d processes for processgroup %d\n", processes, initialPid);
261 if (retry > 0) {
262 usleep(sleep_us);
263 --retry;
264 } else {
265 SLOGE("failed to kill %d processes for processgroup %d\n",
266 processes, initialPid);
267 break;
268 }
269 }
270
271 SLOGV("Killed process group uid %d pid %d in %" PRId64 "ms, %d procs remain", uid, initialPid,
272 android::uptimeMillis()-startTime, processes);
273
274 if (processes == 0) {
275 return removeProcessGroup(uid, initialPid);
276 } else {
277 return -1;
278 }
279}
216static int killProcessGroupOnce(uid_t uid, int initialPid, int signal)
217{
218 int processes = 0;
219 struct ctx ctx;
220 pid_t pid;
221
222 ctx.initialized = false;
223
224 while ((pid = getOneAppProcess(uid, initialPid, &ctx)) >= 0) {
225 processes++;
226 if (pid == 0) {
227 // Should never happen... but if it does, trying to kill this
228 // will boomerang right back and kill us! Let's not let that happen.
229 SLOGW("Yikes, we've been told to kill pid 0! How about we don't do that.");
230 continue;
231 }
232 if (pid != initialPid) {
233 // We want to be noisy about killing processes so we can understand
234 // what is going on in the log; however, don't be noisy about the base
235 // process, since that it something we always kill, and we have already
236 // logged elsewhere about killing it.
237 SLOGI("Killing pid %d in uid %d as part of process group %d", pid, uid, initialPid);
238 }
239 int ret = kill(pid, signal);
240 if (ret == -1) {
241 SLOGW("failed to kill pid %d: %s", pid, strerror(errno));
242 }
243 }
244
245 if (ctx.initialized) {
246 close(ctx.fd);
247 }
248
249 return processes;
250}
我们再跟一下这个有趣的函数:getOneAppProcess
112static pid_t getOneAppProcess(uid_t uid, int appProcessPid, struct ctx *ctx)
113{
114 if (!ctx->initialized) {
115 int ret = initCtx(uid, appProcessPid, ctx);
116 if (ret < 0) {
117 return ret;
118 }
119 }
120
121 char *eptr;
122 while ((eptr = (char *)memchr(ctx->buf_ptr, '\n', ctx->buf_len)) == NULL) {
123 int ret = refillBuffer(ctx);
124 if (ret == 0) {
125 return -ERANGE;
126 }
127 if (ret < 0) {
128 return ret;
129 }
130 }
131
132 *eptr = '\0';
133 char *pid_eptr = NULL;
134 errno = 0;
135 long pid = strtol(ctx->buf_ptr, &pid_eptr, 10);
136 if (errno != 0) {
137 return -errno;
138 }
139 if (pid_eptr != eptr) {
140 return -EINVAL;
141 }
142
143 ctx->buf_len -= (eptr - ctx->buf_ptr) + 1;
144 ctx->buf_ptr = eptr + 1;
145
146 return (pid_t)pid;
147}
回头我们再看看removeProcessGroup,还要把对应的目录删掉。
149static int removeProcessGroup(uid_t uid, int pid)
150{
151 int ret;
152 char path[PROCESSGROUP_MAX_PATH_LEN] = {0};
153
154 convertUidPidToPath(path, sizeof(path), uid, pid);
155 ret = rmdir(path);
156
157 convertUidToPath(path, sizeof(path), uid);
158 rmdir(path);
159
160 return ret;
161}
5872 private final ProcessRecord removeProcessNameLocked(final String name, final int uid) {
5873 ProcessRecord old = mProcessNames.remove(name, uid);
5874 if (old != null) {
5875 old.uidRecord.numProcs--;
5876 if (old.uidRecord.numProcs == 0) {
5877 // No more processes using this uid, tell clients it is gone.
5878 if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
5879 "No more processes in " + old.uidRecord);
5880 enqueueUidChangeLocked(old.uidRecord, true);
5881 mActiveUids.remove(uid);
5882 }
5883 old.uidRecord = null;
5884 }
5885 mIsolatedProcesses.remove(uid);
5886 return old;
5887 }
18855 private final void enqueueUidChangeLocked(UidRecord uidRec, boolean gone) {
18856 if (uidRec.pendingChange == null) {
18857 if (mPendingUidChanges.size() == 0) {
...
18860 mUiHandler.obtainMessage(DISPATCH_UIDS_CHANGED_MSG).sendToTarget();
18861 }
18862 final int NA = mAvailUidChanges.size();
18863 if (NA > 0) {
18864 uidRec.pendingChange = mAvailUidChanges.remove(NA-1);
...
18867 } else {
18868 uidRec.pendingChange = new UidRecord.ChangeItem();
...
18871 }
18872 uidRec.pendingChange.uidRecord = uidRec;
18873 uidRec.pendingChange.uid = uidRec.uid;
18874 mPendingUidChanges.add(uidRec.pendingChange);
18875 }
18876 uidRec.pendingChange.gone = gone;
18877 uidRec.pendingChange.processState = uidRec.setProcState;
18878 }
DISPATCH_UIDS_CHANGED_MSG消息在Handler中是如何处理的呢?我们查AMS中的UiHandler:
1611 case DISPATCH_UIDS_CHANGED_MSG: {
1612 dispatchUidsChanged();
1613 } break;
3787 private void dispatchUidsChanged() {
3788 int N;
3789 synchronized (this) {
3790 N = mPendingUidChanges.size();
3791 if (mActiveUidChanges.length < N) {
3792 mActiveUidChanges = new UidRecord.ChangeItem[N];
3793 }
3794 for (int i=0; i3795 final UidRecord.ChangeItem change = mPendingUidChanges.get(i);
3796 mActiveUidChanges[i] = change;
3797 change.uidRecord.pendingChange = null;
3798 change.uidRecord = null;
3799 }
3800 mPendingUidChanges.clear();
...
3803 }
3804
3805 if (mLocalPowerManager != null) {
3806 for (int j=0; j3807 UidRecord.ChangeItem item = mActiveUidChanges[j];
3808 if (item.gone) {
3809 mLocalPowerManager.uidGone(item.uid);
3810 } else {
3811 mLocalPowerManager.updateUidProcState(item.uid, item.processState);
3812 }
3813 }
3814 }
3815
3816 int i = mUidObservers.beginBroadcast();
3817 while (i > 0) {
3818 i--;
3819 final IUidObserver observer = mUidObservers.getBroadcastItem(i);
3820 if (observer != null) {
3821 try {
3822 for (int j=0; j3823 UidRecord.ChangeItem item = mActiveUidChanges[j];
3824 if (item.gone) {
...
3827 observer.onUidGone(item.uid);
3828 } else {
...
3832 observer.onUidStateChanged(item.uid, item.processState);
3833 }
3834 }
3835 } catch (RemoteException e) {
3836 }
3837 }
3838 }
3839 mUidObservers.finishBroadcast();
3840
3841 synchronized (this) {
3842 for (int j=0; j3843 mAvailUidChanges.add(mActiveUidChanges[j]);
3844 }
3845 }
3846 }
最后我们再看一下handleAppDiedLocked,杀了之后,埋的事情也还是要管的。
4564 private final void handleAppDiedLocked(ProcessRecord app,
4565 boolean restarting, boolean allowRestart) {
4566 int pid = app.pid;
后面大家可以看到这个清理用了180多行的代码,而这还不是全部。
4567 boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1);
mLruProcesses也是要清理的。
4568 if (!kept && !restarting) {
4569 removeLruProcessLocked(app);
4570 if (pid > 0) {
4571 ProcessList.remove(pid);
4572 }
4573 }
4574
4575 if (mProfileProc == app) {
4576 clearProfilerLocked();
4577 }
每个Activity负责去做自己的清理,这部分暂时先不分析了,以后用到了再说。
4579 // Remove this application's activities from active lists.
4580 boolean hasVisibleActivities = mStackSupervisor.handleAppDiedLocked(app);
4581
4582 app.activities.clear();
4583
4584 if (app.instrumentationClass != null) {
4585 Slog.w(TAG, "Crash of app " + app.processName
4586 + " running instrumentation " + app.instrumentationClass);
4587 Bundle info = new Bundle();
4588 info.putString("shortMsg", "Process crashed.");
4589 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4590 }
4591
4592 if (!restarting && hasVisibleActivities && !mStackSupervisor.resumeTopActivitiesLocked()) {
4593 // If there was nothing to resume, and we are not already
4594 // restarting this process, but there is a visible activity that
4595 // is hosted by the process... then make sure all visible
4596 // activities are running, taking care of restarting this
4597 // process.
4598 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
4599 }
4600 }
不光remove LRU,如果没杀掉的话,这里还会再杀一次。
2811 final void removeLruProcessLocked(ProcessRecord app) {
2812 int lrui = mLruProcesses.lastIndexOf(app);
2813 if (lrui >= 0) {
2814 if (!app.killed) {
2815 Slog.wtfStack(TAG, "Removing process that hasn't been killed: " + app);
2816 Process.killProcessQuiet(app.pid);
2817 killProcessGroup(app.info.uid, app.pid);
2818 }
2819 if (lrui <= mLruProcessActivityStart) {
2820 mLruProcessActivityStart--;
2821 }
2822 if (lrui <= mLruProcessServiceStart) {
2823 mLruProcessServiceStart--;
2824 }
2825 mLruProcesses.remove(lrui);
2826 }
2827 }
这段就不细解释了,原文贴出来的原因是希望大家都体会到,埋葬还有这么多事情要做的。
15504 private final boolean cleanUpApplicationRecordLocked(ProcessRecord app,
15505 boolean restarting, boolean allowRestart, int index) {
15506 if (index >= 0) {
15507 removeLruProcessLocked(app);
15508 ProcessList.remove(app.pid);
15509 }
15510
15511 mProcessesToGc.remove(app);
15512 mPendingPssProcesses.remove(app);
15513
15514 // Dismiss any open dialogs.
15515 if (app.crashDialog != null && !app.forceCrashReport) {
15516 app.crashDialog.dismiss();
15517 app.crashDialog = null;
15518 }
15519 if (app.anrDialog != null) {
15520 app.anrDialog.dismiss();
15521 app.anrDialog = null;
15522 }
15523 if (app.waitDialog != null) {
15524 app.waitDialog.dismiss();
15525 app.waitDialog = null;
15526 }
15527
15528 app.crashing = false;
15529 app.notResponding = false;
15530
15531 app.resetPackageList(mProcessStats);
15532 app.unlinkDeathRecipient();
15533 app.makeInactive(mProcessStats);
15534 app.waitingToKill = null;
15535 app.forcingToForeground = null;
15536 updateProcessForegroundLocked(app, false, false);
15537 app.foregroundActivities = false;
15538 app.hasShownUi = false;
15539 app.treatLikeActivity = false;
15540 app.hasAboveClient = false;
15541 app.hasClientActivities = false;
15542
15543 mServices.killServicesLocked(app, allowRestart);
15544
15545 boolean restart = false;
15546
15547 // Remove published content providers.
15548 for (int i = app.pubProviders.size() - 1; i >= 0; i--) {
15549 ContentProviderRecord cpr = app.pubProviders.valueAt(i);
15550 final boolean always = app.bad || !allowRestart;
15551 boolean inLaunching = removeDyingProviderLocked(app, cpr, always);
15552 if ((inLaunching || always) && cpr.hasConnectionOrHandle()) {
15553 // We left the provider in the launching list, need to
15554 // restart it.
15555 restart = true;
15556 }
15557
15558 cpr.provider = null;
15559 cpr.proc = null;
15560 }
15561 app.pubProviders.clear();
15562
15563 // Take care of any launching providers waiting for this process.
15564 if (cleanupAppInLaunchingProvidersLocked(app, false)) {
15565 restart = true;
15566 }
15567
15568 // Unregister from connected content providers.
15569 if (!app.conProviders.isEmpty()) {
15570 for (int i = app.conProviders.size() - 1; i >= 0; i--) {
15571 ContentProviderConnection conn = app.conProviders.get(i);
15572 conn.provider.connections.remove(conn);
15573 stopAssociationLocked(app.uid, app.processName, conn.provider.uid,
15574 conn.provider.name);
15575 }
15576 app.conProviders.clear();
15577 }
15578
15579 // At this point there may be remaining entries in mLaunchingProviders
15580 // where we were the only one waiting, so they are no longer of use.
15581 // Look for these and clean up if found.
15582 // XXX Commented out for now. Trying to figure out a way to reproduce
15583 // the actual situation to identify what is actually going on.
15584 if (false) {
15585 for (int i = mLaunchingProviders.size() - 1; i >= 0; i--) {
15586 ContentProviderRecord cpr = mLaunchingProviders.get(i);
15587 if (cpr.connections.size() <= 0 && !cpr.hasExternalProcessHandles()) {
15588 synchronized (cpr) {
15589 cpr.launchingApp = null;
15590 cpr.notifyAll();
15591 }
15592 }
15593 }
15594 }
15595
15596 skipCurrentReceiverLocked(app);
15597
15598 // Unregister any receivers.
15599 for (int i = app.receivers.size() - 1; i >= 0; i--) {
15600 removeReceiverLocked(app.receivers.valueAt(i));
15601 }
15602 app.receivers.clear();
15603
15604 // If the app is undergoing backup, tell the backup manager about it
15605 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
15606 if (DEBUG_BACKUP || DEBUG_CLEANUP) Slog.d(TAG_CLEANUP, "App "
15607 + mBackupTarget.appInfo + " died during backup");
15608 try {
15609 IBackupManager bm = IBackupManager.Stub.asInterface(
15610 ServiceManager.getService(Context.BACKUP_SERVICE));
15611 bm.agentDisconnected(app.info.packageName);
15612 } catch (RemoteException e) {
15613 // can't happen; backup manager is local
15614 }
15615 }
15616
15617 for (int i = mPendingProcessChanges.size() - 1; i >= 0; i--) {
15618 ProcessChangeItem item = mPendingProcessChanges.get(i);
15619 if (item.pid == app.pid) {
15620 mPendingProcessChanges.remove(i);
15621 mAvailProcessChanges.add(item);
15622 }
15623 }
15624 mUiHandler.obtainMessage(DISPATCH_PROCESS_DIED, app.pid, app.info.uid, null).sendToTarget();
15625
15626 // If the caller is restarting this app, then leave it in its
15627 // current lists and let the caller take care of it.
15628 if (restarting) {
15629 return false;
15630 }
15631
15632 if (!app.persistent || app.isolated) {
15633 if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
15634 "Removing non-persistent process during cleanup: " + app);
15635 removeProcessNameLocked(app.processName, app.uid);
15636 if (mHeavyWeightProcess == app) {
15637 mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
15638 mHeavyWeightProcess.userId, 0));
15639 mHeavyWeightProcess = null;
15640 }
15641 } else if (!app.removed) {
15642 // This app is persistent, so we need to keep its record around.
15643 // If it is not already on the pending app list, add it there
15644 // and start a new process for it.
15645 if (mPersistentStartingProcesses.indexOf(app) < 0) {
15646 mPersistentStartingProcesses.add(app);
15647 restart = true;
15648 }
15649 }
15650 if ((DEBUG_PROCESSES || DEBUG_CLEANUP) && mProcessesOnHold.contains(app)) Slog.v(
15651 TAG_CLEANUP, "Clean-up removing on hold: " + app);
15652 mProcessesOnHold.remove(app);
15653
15654 if (app == mHomeProcess) {
15655 mHomeProcess = null;
15656 }
15657 if (app == mPreviousProcess) {
15658 mPreviousProcess = null;
15659 }
15660
15661 if (restart && !app.isolated) {
15662 // We have components that still need to be running in the
15663 // process, so re-launch it.
15664 if (index < 0) {
15665 ProcessList.remove(app.pid);
15666 }
15667 addProcessNameLocked(app);
15668 startProcessLocked(app, "restart", app.processName);
15669 return true;
15670 } else if (app.pid > 0 && app.pid != MY_PID) {
15671 // Goodbye!
15672 boolean removed;
15673 synchronized (mPidsSelfLocked) {
15674 mPidsSelfLocked.remove(app.pid);
15675 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
15676 }
15677 mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
15678 if (app.isolated) {
15679 mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
15680 }
15681 app.setPid(0);
15682 }
15683 return false;
15684 }