Activity相关学习-kill process
2019-01-22 本文已影响0人
weiinter105
前言
当startActivity过程中,Activity所依赖进程被杀会发生什么呢,如一个AMS相关的稳定性问题
相关流程
注册死亡回调
ActivityManagerService#attachApplicationLocked
7706 @GuardedBy("this")
7707 private final boolean attachApplicationLocked(IApplicationThread thread,
7708 int pid, int callingUid, long startSeq) {
7709
7710 // Find the application record that is being attached... either via
7711 // the pid if we are running in multiple processes, or just pull the
7712 // next app record if we are emulating process with anonymous threads.
7713 ProcessRecord app;
7714 long startTime = SystemClock.uptimeMillis();
7715 if (pid != MY_PID && pid >= 0) {
7716 synchronized (mPidsSelfLocked) {
7717 app = mPidsSelfLocked.get(pid);
7718 }
7719 } else {
7720 app = null;
7721 }
7722
7723 // It's possible that process called attachApplication before we got a chance to
7724 // update the internal state.
7725 if (app == null && startSeq > 0) {
7726 final ProcessRecord pending = mPendingStarts.get(startSeq);
7727 if (pending != null && pending.startUid == callingUid
7728 && handleProcessStartedLocked(pending, pid, pending.usingWrapper,
7729 startSeq, true)) {
7730 app = pending;
7731 }
7732 }
7733
7734 if (app == null) {
7735 Slog.w(TAG, "No pending application record for pid " + pid
7736 + " (IApplicationThread " + thread + "); dropping process");
7737 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
7738 if (pid > 0 && pid != MY_PID) {
7739 killProcessQuiet(pid);
7740 //TODO: killProcessGroup(app.info.uid, pid);
7741 } else {
7742 try {
7743 thread.scheduleExit();
7744 } catch (Exception e) {
7745 // Ignore exceptions.
7746 }
7747 }
7748 return false;
7749 }
7750
7751 // If this application record is still attached to a previous
7752 // process, clean it up now.
7753 if (app.thread != null) {
7754 handleAppDiedLocked(app, true, true);
7755 }
7756
7757 // Tell the process all about itself.
7758
7759 if (DEBUG_ALL) Slog.v(
7760 TAG, "Binding process pid " + pid + " to record " + app);
7761
7762 final String processName = app.processName;
7763 try {
7764 AppDeathRecipient adr = new AppDeathRecipient(
7765 app, pid, thread);
7766 thread.asBinder().linkToDeath(adr, 0); //注册死亡回调
7767 app.deathRecipient = adr;
7768 } catch (RemoteException e) {
7769 app.resetPackageList(mProcessStats);
7770 startProcessLocked(app, "link fail", processName);
7771 return false;
7772 }
7773
7774 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.userId, app.pid, app.processName);
进程被杀时(如kill -9,lowmemorykiller)
ActivityManagerService#AppDeathRecipient
private final class AppDeathRecipient implements IBinder.DeathRecipient {
final ProcessRecord mApp;
final int mPid;
final IApplicationThread mAppThread;
AppDeathRecipient(ProcessRecord app, int pid,
IApplicationThread thread) {
if (DEBUG_ALL) Slog.v(
TAG, "New death recipient " + this
+ " for thread " + thread.asBinder());
mApp = app;
mPid = pid;
mAppThread = thread;
}
@Override
public void binderDied() {
if (DEBUG_ALL) Slog.v(
TAG, "Death received in " + this
+ " for thread " + mAppThread.asBinder());
synchronized(ActivityManagerService.this) {
appDiedLocked(mApp, mPid, mAppThread, true);
}
}
}
ActivityManagerService#appDiedLocked
6164 @GuardedBy("this")
6165 final void appDiedLocked(ProcessRecord app, int pid, IApplicationThread thread,
6166 boolean fromBinderDied) {
6167 // First check if this ProcessRecord is actually active for the pid.
6168 synchronized (mPidsSelfLocked) {
6169 ProcessRecord curProc = mPidsSelfLocked.get(pid);
6170 if (curProc != app) {
6171 Slog.w(TAG, "Spurious death for " + app + ", curProc for " + pid + ": " + curProc);
6172 return;
6173 }
6174 }
6175 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6176 synchronized (stats) {
6177 stats.noteProcessDiedLocked(app.info.uid, pid);
6178 }
6179
6180 if (!app.killed) {
6181 if (!fromBinderDied) {
6182 killProcessQuiet(pid);
6183 }
6184 killProcessGroup(app.uid, pid);
6185 app.killed = true;
6186 }
6187
6188 // Clean up already done if the process has been re-started.
6189 if (app.pid == pid && app.thread != null &&
6190 app.thread.asBinder() == thread.asBinder()) {
6191 boolean doLowMem = app.instr == null;
6192 boolean doOomAdj = doLowMem;
6193 if (!app.killedByAm) { //app.killedByAm会在ProcessRecord.kill中置为true
6194 reportUidInfoMessageLocked(TAG,
6195 "Process " + app.processName + " (pid " + pid + ") has died: "
6196 + ProcessList.makeOomAdjString(app.setAdj)
6197 + ProcessList.makeProcStateString(app.setProcState), app.info.uid);
6198 mAllowLowerMemLevel = true;
6199 if (mEnableNetOpts) {
6200 networkOptsCheck(1, app.processName);
6201 }
6202 } else {
6203 // Note that we always want to do oom adj to update our state with the
6204 // new number of procs.
6205 mAllowLowerMemLevel = false;
6206 doLowMem = false;
6207 }
6208 if (mUxPerf != null) {
6209 mUxPerf.perfUXEngine_events(BoostFramework.UXE_EVENT_KILL, 0, app.processName, 0);
6210 }
6211 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.userId, app.pid, app.processName,
6212 app.setAdj, app.setProcState);
6213 if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
6214 "Dying app: " + app + ", pid: " + pid + ", thread: " + thread.asBinder());
6215 handleAppDiedLocked(app, false, true);
6216
6217 if (doOomAdj) {
6218 updateOomAdjLocked();
6219 }
6220 if (doLowMem) {
6221 doLowMemReportIfNeededLocked(app);
6222 }
6223 } else if (app.pid != pid) {
6224 // A new process has already been started.
6225 reportUidInfoMessageLocked(TAG,
6226 "Process " + app.processName + " (pid " + pid
6227 + ") has died and restarted (pid " + app.pid + ").", app.info.uid);
6228 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.userId, app.pid, app.processName);
6229 } else if (DEBUG_PROCESSES) {
6230 Slog.d(TAG_PROCESSES, "Received spurious death notification for thread "
6231 + thread.asBinder());
6232 }
6233
6234 // On the device which doesn't have Cgroup, log LmkStateChanged which is used as a signal
6235 // for pulling memory stats of other running processes when this process died.
6236 if (!hasMemcg()) {
6237 StatsLog.write(StatsLog.APP_DIED, SystemClock.elapsedRealtime());
6238 }
6239 }
ActivityManagerService#killProcessGroup
static void killProcessGroup(int uid, int pid) {
if (sKillHandler != null) {
sKillHandler.sendMessage(
sKillHandler.obtainMessage(KillHandler.KILL_PROCESS_GROUP_MSG, uid, pid));
} else {
Slog.w(TAG, "Asked to kill process group before system bringup!");
Process.killProcessGroup(uid, pid);
}
}
...
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case KILL_PROCESS_GROUP_MSG:
{
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "killProcessGroup");
Process.killProcessGroup(msg.arg1 /* uid */, msg.arg2 /* pid */); //JNI调用
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
break;
default:
super.handleMessage(msg);
}
}
}
ActivityManagerService#handleAppDiedLocked
/**
* Main function for removing an existing process from the activity manager
* as a result of that process going away. Clears out all connections
* to the process.
*/
@GuardedBy("this")
private final void handleAppDiedLocked(ProcessRecord app,
boolean restarting, boolean allowRestart) {
int pid = app.pid;
boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1,
false /*replacingPid*/);
if (!kept && !restarting) {
removeLruProcessLocked(app);
if (pid > 0) {
ProcessList.remove(pid); //调用ProcessList的remove
}
}
if (mProfileProc == app) {
clearProfilerLocked();
}
// Remove this application's activities from active lists.
boolean hasVisibleActivities = mStackSupervisor.handleAppDiedLocked(app); (针对被kill进程的activity进程处理)
app.clearRecentTasks();
app.activities.clear();
if (app.instr != null) {
Slog.w(TAG, "Crash of app " + app.processName
+ " running instrumentation " + app.instr.mClass);
Bundle info = new Bundle();
info.putString("shortMsg", "Process crashed.");
finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
}
mWindowManager.deferSurfaceLayout();
try {
if (!restarting && hasVisibleActivities
&& !mStackSupervisor.resumeFocusedStackTopActivityLocked()) {
//最后还会调用到resumeFocusedStackTopActivityLocked
// If there was nothing to resume, and we are not already restarting this process, but
// there is a visible activity that is hosted by the process... then make sure all
// visible activities are running, taking care of restarting this process.
mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
} finally {
mWindowManager.continueSurfaceLayout();
}
}
ActivityManagerService#cleanUpApplicationRecordLocked
注意注释
Main code for cleaning up a process when it has gone away. This is called both as a result of the process dying, or directly when stopping a process when running in single process mode.
返回进程是否restart了
/**
* Main code for cleaning up a process when it has gone away. This is
* called both as a result of the process dying, or directly when stopping
* a process when running in single process mode.
*
* @return Returns true if the given process has been restarted, so the
* app that was passed in must remain on the process lists.
*/
@GuardedBy("this")
private final boolean cleanUpApplicationRecordLocked(ProcessRecord app,
boolean restarting, boolean allowRestart, int index, boolean replacingPid) {
if (index >= 0) {
removeLruProcessLocked(app);
ProcessList.remove(app.pid);
}
mProcessesToGc.remove(app);
mPendingPssProcesses.remove(app);
ProcessList.abortNextPssTime(app.procStateMemTracker);
// Dismiss any open dialogs.
if (app.crashDialog != null && !app.forceCrashReport) {
app.crashDialog.dismiss();
app.crashDialog = null;
}
if (app.anrDialog != null) {
app.anrDialog.dismiss();
app.anrDialog = null;
}
if (app.waitDialog != null) {
app.waitDialog.dismiss();
app.waitDialog = null;
}
app.crashing = false;
app.notResponding = false;
app.resetPackageList(mProcessStats);
app.unlinkDeathRecipient();
app.makeInactive(mProcessStats);
app.waitingToKill = null;
app.forcingToImportant = null;
updateProcessForegroundLocked(app, false, false);
app.foregroundActivities = false;
app.hasShownUi = false;
app.treatLikeActivity = false;
app.hasAboveClient = false;
app.hasClientActivities = false;
mServices.killServicesLocked(app, allowRestart); //做Service的清理工作
boolean restart = false;
// Remove published content providers.
//做ContentProvider的清理工作
//清除publish ContentProvider
for (int i = app.pubProviders.size() - 1; i >= 0; i--) {
ContentProviderRecord cpr = app.pubProviders.valueAt(i);
final boolean always = app.bad || !allowRestart;
boolean inLaunching = removeDyingProviderLocked(app, cpr, always);
if ((inLaunching || always) && cpr.hasConnectionOrHandle()) {
// We left the provider in the launching list, need to
// restart it.
restart = true;
}
cpr.provider = null;
cpr.proc = null;
}
app.pubProviders.clear();
// Take care of any launching providers waiting for this process.
if (cleanupAppInLaunchingProvidersLocked(app, false)) {
restart = true;
}
// Unregister from connected content providers.
//unregister工作
if (!app.conProviders.isEmpty()) {
for (int i = app.conProviders.size() - 1; i >= 0; i--) {
ContentProviderConnection conn = app.conProviders.get(i);
conn.provider.connections.remove(conn);
stopAssociationLocked(app.uid, app.processName, conn.provider.uid,
conn.provider.name);
}
app.conProviders.clear();
}
// At this point there may be remaining entries in mLaunchingProviders
// where we were the only one waiting, so they are no longer of use.
// Look for these and clean up if found.
// XXX Commented out for now. Trying to figure out a way to reproduce
// the actual situation to identify what is actually going on.
if (false) {
for (int i = mLaunchingProviders.size() - 1; i >= 0; i--) {
ContentProviderRecord cpr = mLaunchingProviders.get(i);
if (cpr.connections.size() <= 0 && !cpr.hasExternalProcessHandles()) {
synchronized (cpr) {
cpr.launchingApp = null;
cpr.notifyAll();
}
}
}
}
skipCurrentReceiverLocked(app);
// Unregister any receivers.
//unregister 动态注册广播接收者
for (int i = app.receivers.size() - 1; i >= 0; i--) {
removeReceiverLocked(app.receivers.valueAt(i));
}
app.receivers.clear();
// If the app is undergoing backup, tell the backup manager about it
if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
if (DEBUG_BACKUP || DEBUG_CLEANUP) Slog.d(TAG_CLEANUP, "App "
+ mBackupTarget.appInfo + " died during backup");
mHandler.post(new Runnable() {
@Override
public void run(){
try {
IBackupManager bm = IBackupManager.Stub.asInterface(
ServiceManager.getService(Context.BACKUP_SERVICE));
bm.agentDisconnected(app.info.packageName);
} catch (RemoteException e) {
// can't happen; backup manager is local
}
}
});
}
for (int i = mPendingProcessChanges.size() - 1; i >= 0; i--) {
ProcessChangeItem item = mPendingProcessChanges.get(i);
if (app.pid > 0 && item.pid == app.pid) {
mPendingProcessChanges.remove(i);
mAvailProcessChanges.add(item);
}
}
mUiHandler.obtainMessage(DISPATCH_PROCESS_DIED_UI_MSG, app.pid, app.info.uid,
null).sendToTarget();
// If the caller is restarting this app, then leave it in its
// current lists and let the caller take care of it.
if (restarting) {
return false;
}
if (!app.persistent || app.isolated) {
if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
"Removing non-persistent process during cleanup: " + app);
if (!replacingPid) {
removeProcessNameLocked(app.processName, app.uid, app); //将AMS中的mProcessNames保存的ProcessRecord记录移除
}
if (mHeavyWeightProcess == app) {
mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
mHeavyWeightProcess.userId, 0));
mHeavyWeightProcess = null;
}
} else if (!app.removed) {
// This app is persistent, so we need to keep its record around.
// If it is not already on the pending app list, add it there
// and start a new process for it.
if (mPersistentStartingProcesses.indexOf(app) < 0) {
mPersistentStartingProcesses.add(app);
restart = true;
}
}
if ((DEBUG_PROCESSES || DEBUG_CLEANUP) && mProcessesOnHold.contains(app)) Slog.v(
TAG_CLEANUP, "Clean-up removing on hold: " + app);
mProcessesOnHold.remove(app);
if (app == mHomeProcess) {
mHomeProcess = null;
}
if (app == mPreviousProcess) {
mPreviousProcess = null;
}
if (restart && !app.isolated) {
// We have components that still need to be running in the
// process, so re-launch it.
if (index < 0) {
ProcessList.remove(app.pid);
}
addProcessNameLocked(app);
app.pendingStart = false;
startProcessLocked(app, "restart", app.processName);
return true;
} else if (app.pid > 0 && app.pid != MY_PID) {
// Goodbye!
boolean removed;
synchronized (mPidsSelfLocked) {
mPidsSelfLocked.remove(app.pid);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
}
mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
if (app.isolated) {
mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
}
app.setPid(0);
}
return false;
}
ActiveServices#killServicesLocked
做进程关联的Service的相关清理工作
final void killServicesLocked(ProcessRecord app, boolean allowRestart) {
// Report disconnected services.
if (false) {
// XXX we are letting the client link to the service for
// death notifications.
if (app.services.size() > 0) {
Iterator<ServiceRecord> it = app.services.iterator();
while (it.hasNext()) {
ServiceRecord r = it.next();
for (int conni=r.connections.size()-1; conni>=0; conni--) {
ArrayList<ConnectionRecord> cl = r.connections.valueAt(conni);
for (int i=0; i<cl.size(); i++) {
ConnectionRecord c = cl.get(i);
if (c.binding.client != app) {
try {
//c.conn.connected(r.className, null);
} catch (Exception e) {
// todo: this should be asynchronous!
Slog.w(TAG, "Exception thrown disconnected servce "
+ r.shortName
+ " from app " + app.processName, e);
}
}
}
}
}
}
}
// Clean up any connections this application has to other services.
for (int i = app.connections.size() - 1; i >= 0; i--) {
ConnectionRecord r = app.connections.valueAt(i);
removeConnectionLocked(r, app, null);
}
updateServiceConnectionActivitiesLocked(app);
app.connections.clear();
app.whitelistManager = false;
// Clear app state from services.
for (int i = app.services.size() - 1; i >= 0; i--) {
ServiceRecord sr = app.services.valueAt(i);
synchronized (sr.stats.getBatteryStats()) {
sr.stats.stopLaunchedLocked();
}
if (sr.app != app && sr.app != null && !sr.app.persistent) {
sr.app.services.remove(sr);
}
sr.app = null;
sr.isolatedProc = null;
sr.executeNesting = 0;
sr.forceClearTracker();
if (mDestroyingServices.remove(sr)) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "killServices remove destroying " + sr);
}
final int numClients = sr.bindings.size();
for (int bindingi=numClients-1; bindingi>=0; bindingi--) {
IntentBindRecord b = sr.bindings.valueAt(bindingi);
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Killing binding " + b
+ ": shouldUnbind=" + b.hasBound);
b.binder = null;
b.requested = b.received = b.hasBound = false;
// If this binding is coming from a cached process and is asking to keep
// the service created, then we'll kill the cached process as well -- we
// don't want to be thrashing around restarting processes that are only
// there to be cached.
for (int appi=b.apps.size()-1; appi>=0; appi--) {
final ProcessRecord proc = b.apps.keyAt(appi);
// If the process is already gone, skip it.
if (proc.killedByAm || proc.thread == null) {
continue;
}
// Only do this for processes that have an auto-create binding;
// otherwise the binding can be left, because it won't cause the
// service to restart.
final AppBindRecord abind = b.apps.valueAt(appi);
boolean hasCreate = false;
for (int conni=abind.connections.size()-1; conni>=0; conni--) {
ConnectionRecord conn = abind.connections.valueAt(conni);
if ((conn.flags&(Context.BIND_AUTO_CREATE|Context.BIND_ALLOW_OOM_MANAGEMENT
|Context.BIND_WAIVE_PRIORITY)) == Context.BIND_AUTO_CREATE) {
hasCreate = true;
break;
}
}
if (!hasCreate) {
continue;
}
// XXX turned off for now until we have more time to get a better policy.
if (false && proc != null && !proc.persistent && proc.thread != null
&& proc.pid != 0 && proc.pid != ActivityManagerService.MY_PID
&& proc.setProcState >= ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
proc.kill("bound to service " + sr.name.flattenToShortString()
+ " in dying proc " + (app != null ? app.processName : "??"), true);
}
}
}
}
ServiceMap smap = getServiceMapLocked(app.userId);
// Now do remaining service cleanup.
for (int i=app.services.size()-1; i>=0; i--) {
ServiceRecord sr = app.services.valueAt(i);
// Unless the process is persistent, this process record is going away,
// so make sure the service is cleaned out of it.
if (!app.persistent) {
app.services.removeAt(i);
}
// Sanity check: if the service listed for the app is not one
// we actually are maintaining, just let it drop.
final ServiceRecord curRec = smap.mServicesByName.get(sr.name);
if (curRec != sr) {
if (curRec != null) {
Slog.wtf(TAG, "Service " + sr + " in process " + app
+ " not same as in map: " + curRec);
}
continue;
}
// Any services running in the application may need to be placed
// back in the pending list.
if (allowRestart && sr.crashCount >= mAm.mConstants.BOUND_SERVICE_MAX_CRASH_RETRY
&& (sr.serviceInfo.applicationInfo.flags
&ApplicationInfo.FLAG_PERSISTENT) == 0) {
Slog.w(TAG, "Service crashed " + sr.crashCount
+ " times, stopping: " + sr);
EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
sr.userId, sr.crashCount, sr.shortName, app.pid);
bringDownServiceLocked(sr);
} else if (!allowRestart
|| !mAm.mUserController.isUserRunning(sr.userId, 0)) {
bringDownServiceLocked(sr);
} else {
boolean canceled = scheduleServiceRestartLocked(sr, true);
// Should the service remain running? Note that in the
// extreme case of so many attempts to deliver a command
// that it failed we also will stop it here.
if (sr.startRequested && (sr.stopIfKilled || canceled)) {
if (sr.pendingStarts.size() == 0) {
sr.startRequested = false;
if (sr.tracker != null) {
sr.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(),
SystemClock.uptimeMillis());
}
if (!sr.hasAutoCreateConnections()) {
// Whoops, no reason to restart!
bringDownServiceLocked(sr);
}
}
}
}
}
if (!allowRestart) {
app.services.clear();
// Make sure there are no more restarting services for this process.
for (int i=mRestartingServices.size()-1; i>=0; i--) {
ServiceRecord r = mRestartingServices.get(i);
if (r.processName.equals(app.processName) &&
r.serviceInfo.applicationInfo.uid == app.info.uid) {
mRestartingServices.remove(i);
clearRestartingIfNeededLocked(r);
}
}
for (int i=mPendingServices.size()-1; i>=0; i--) {
ServiceRecord r = mPendingServices.get(i);
if (r.processName.equals(app.processName) &&
r.serviceInfo.applicationInfo.uid == app.info.uid) {
mPendingServices.remove(i);
}
}
}
// Make sure we have no more records on the stopping list.
int i = mDestroyingServices.size();
while (i > 0) {
i--;
ServiceRecord sr = mDestroyingServices.get(i);
if (sr.app == app) {
sr.forceClearTracker();
mDestroyingServices.remove(i);
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "killServices remove destroying " + sr);
}
}
app.executingServices.clear();
}
ActivityStackSupervior#handleAppDiedLocked
boolean handleAppDiedLocked(ProcessRecord app) {
boolean hasVisibleActivities = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = display.getChildAt(stackNdx);
hasVisibleActivities |= stack.handleAppDiedLocked(app);
}
}
return hasVisibleActivities;
}
ActivityStack#handleAppDiedLocked
针对ActivityStack的处理
/**
* Reset local parameters because an app's activity died.
* @param app The app of the activity that died.
* @return result from removeHistoryRecordsForAppLocked.
*/
boolean handleAppDiedLocked(ProcessRecord app) {
if (mPausingActivity != null && mPausingActivity.app == app) {
if (DEBUG_PAUSE || DEBUG_CLEANUP) Slog.v(TAG_PAUSE,
"App died while pausing: " + mPausingActivity);
mPausingActivity = null;
}
if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
return removeHistoryRecordsForAppLocked(app);
}
ActivityStack#removeHistoryRecordsForAppLocked
4501 private boolean removeHistoryRecordsForAppLocked(ProcessRecord app) {
4502 removeHistoryRecordsForAppLocked(mLRUActivities, app, "mLRUActivities"); //移除mLRUActivities中保存的Activity
4503 removeHistoryRecordsForAppLocked(mStackSupervisor.mStoppingActivities, app,
4504 "mStoppingActivities");
4505 removeHistoryRecordsForAppLocked(mStackSupervisor.mGoingToSleepActivities, app,
4506 "mGoingToSleepActivities");
4507 removeHistoryRecordsForAppLocked(mStackSupervisor.mActivitiesWaitingForVisibleActivity, app,
4508 "mActivitiesWaitingForVisibleActivity");
4509 removeHistoryRecordsForAppLocked(mStackSupervisor.mFinishingActivities, app,
4510 "mFinishingActivities");
4511
4512 boolean hasVisibleActivities = false;
4513
4514 // Clean out the history list.
4515 int i = numActivities();
4516 if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
4517 "Removing app " + app + " from history with " + i + " entries");
4518 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
4519 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
4520 mTmpActivities.clear();
4521 mTmpActivities.addAll(activities);
4522
4523 while (!mTmpActivities.isEmpty()) {
4524 final int targetIndex = mTmpActivities.size() - 1;
4525 final ActivityRecord r = mTmpActivities.remove(targetIndex);
4526 if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
4527 "Record #" + targetIndex + " " + r + ": app=" + r.app);
4528
4529 if (r.app == app) {
4530 if (r.visible) {
4531 hasVisibleActivities = true;
4532 }
4533 final boolean remove;
4534 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) { //此时r.finishing = false,说明不在
//haveState会在activityResumedLocked中被赋值为false;haveState在activityStoppedLocked中被置为true
//那么看起来进程被kill,r.finishing = false时,正常情况下只有最上面的resumed的Activity需要remove
4535 // Don't currently have state for the activity, or
4536 // it is finishing -- always remove it.
4537 remove = true; //是否需要remove
4538 } else if (!r.visible && r.launchCount > 2 &&
4539 r.lastLaunchTime > (SystemClock.uptimeMillis() - 60000)) {
4540 // We have launched this activity too many times since it was
4541 // able to run, so give up and remove it.
4542 // (Note if the activity is visible, we don't remove the record.
4543 // We leave the dead window on the screen but the process will
4544 // not be restarted unless user explicitly tap on it.)
4545 remove = true;
4546 } else {
4547 // The process may be gone, but the activity lives on!
4548 remove = false;
4549 }
4550 if (remove) {
4551 if (DEBUG_ADD_REMOVE || DEBUG_CLEANUP) Slog.i(TAG_ADD_REMOVE,
4552 "Removing activity " + r + " from stack at " + i
4553 + ": haveState=" + r.haveState
4554 + " stateNotNeeded=" + r.stateNotNeeded
4555 + " finishing=" + r.finishing
4556 + " state=" + r.getState() + " callers=" + Debug.getCallers(5));
4557 if (!r.finishing) {
4558 Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
4559 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
4560 r.userId, System.identityHashCode(r),
4561 r.getTask().taskId, r.shortComponentName,
4562 "proc died without state saved");
4563 if (r.getState() == RESUMED) {
4564 mService.updateUsageStats(r, false);
4565 }
4566 }
4567 } else {
4568 // We have the current state for this activity, so
4569 // it can be restarted later when needed.
4570 if (DEBUG_ALL) Slog.v(TAG, "Keeping entry, setting app to null");
4571 if (DEBUG_APP) Slog.v(TAG_APP,
4572 "Clearing app during removeHistory for activity " + r);
4573 r.app = null; //将r.app置为null
4574 // Set nowVisible to previous visible state. If the app was visible while
4575 // it died, we leave the dead window on screen so it's basically visible.
4576 // This is needed when user later tap on the dead window, we need to stop
4577 // other apps when user transfers focus to the restarted activity.
4578 r.nowVisible = r.visible;
4579 if (!r.haveState) {
4580 if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE,
4581 "App died, clearing saved state of " + r);
4582 r.icicle = null;
4583 }
4584 }
4585 cleanUpActivityLocked(r, true, true);
//此时调用cleanUpActivityLocked,cleanServices = true,setState = true
4586 if (remove) {
4587 removeActivityFromHistoryLocked(r, "appDied");
4588 }
4589 }
4590 }
4591 }
4592
4593 return hasVisibleActivities;
4594 }
ActivityStack#cleanUpActivityLocked
/**
* Perform the common clean-up of an activity record. This is called both
* as part of destroyActivityLocked() (when destroying the client-side
* representation) and cleaning things up as a result of its hosting
* processing going away, in which case there is no remaining client-side
* state to destroy so only the cleanup here is needed.
*
* Note: Call before #removeActivityFromHistoryLocked.
*/
private void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices, boolean setState) {
onActivityRemovedFromStack(r);
r.deferRelaunchUntilPaused = false;
r.frozenBeforeDestroy = false;
if (setState) {
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYED: " + r + " (cleaning up)"); //将Activity从
r.setState(DESTROYED, "cleanupActivityLocked"); //将Activity的状态置为destoryed
if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during cleanUp for activity " + r);
r.app = null; //将ActivityRecord.app置为null
}
// Inform supervisor the activity has been removed.
mStackSupervisor.cleanupActivity(r);
// Remove any pending results.
if (r.finishing && r.pendingResults != null) {
for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
PendingIntentRecord rec = apr.get();
if (rec != null) {
mService.cancelIntentSenderLocked(rec, false);
}
}
r.pendingResults = null;
}
if (cleanServices) {
cleanUpActivityServicesLocked(r);
}
// Get rid of any pending idle timeouts.
removeTimeoutsForActivityLocked(r);
// Clean-up activities are no longer relaunching (e.g. app process died). Notify window
// manager so it can update its bookkeeping.
mWindowManager.notifyAppRelaunchesCleared(r.appToken);
}
ActivityStack#removeActivityFromHistoryLocked
private void removeActivityFromHistoryLocked(ActivityRecord r, String reason) {
finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
r.makeFinishingLocked(); //首先将finishing属性置为true
if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
"Removing activity " + r + " from stack callers=" + Debug.getCallers(5));
r.takeFromHistory();
removeTimeoutsForActivityLocked(r);
if (DEBUG_STATES) Slog.v(TAG_STATES,
"Moving to DESTROYED: " + r + " (removed from history)");
r.setState(DESTROYED, "removeActivityFromHistoryLocked");
if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + r);
r.app = null;
r.removeWindowContainer();
final TaskRecord task = r.getTask();
final boolean lastActivity = task != null ? task.removeActivity(r) : false;
// If we are removing the last activity in the task, not including task overlay activities,
// then fall through into the block below to remove the entire task itself
final boolean onlyHasTaskOverlays = task != null
? task.onlyHasTaskOverlayActivities(false /* excludingFinishing */) : false;
if (lastActivity || onlyHasTaskOverlays) {
if (DEBUG_STACK) {
Slog.i(TAG_STACK,
"removeActivityFromHistoryLocked: last activity removed from " + this
+ " onlyHasTaskOverlays=" + onlyHasTaskOverlays);
}
// The following block can be executed multiple times if there is more than one overlay.
// {@link ActivityStackSupervisor#removeTaskByIdLocked} handles this by reverse lookup
// of the task by id and exiting early if not found.
if (onlyHasTaskOverlays) {
// When destroying a task, tell the supervisor to remove it so that any activity it
// has can be cleaned up correctly. This is currently the only place where we remove
// a task with the DESTROYING mode, so instead of passing the onlyHasTaskOverlays
// state into removeTask(), we just clear the task here before the other residual
// work.
// TODO: If the callers to removeTask() changes such that we have multiple places
// where we are destroying the task, move this back into removeTask()
mStackSupervisor.removeTaskByIdLocked(task.taskId, false /* killProcess */,
!REMOVE_FROM_RECENTS, PAUSE_IMMEDIATELY, reason);
}
// We must keep the task around until all activities are destroyed. The following
// statement will only execute once since overlays are also considered activities.
if (lastActivity) {
removeTask(task, reason, REMOVE_TASK_MODE_DESTROYING);
}
}
cleanUpActivityServicesLocked(r);
r.removeUriPermissionsLocked();
}
#######ActivityStack#removeTask
/**
* Removes the input task from this stack.
* @param task to remove.
* @param reason for removal.
* @param mode task removal mode. Either {@link #REMOVE_TASK_MODE_DESTROYING},
* {@link #REMOVE_TASK_MODE_MOVING}, {@link #REMOVE_TASK_MODE_MOVING_TO_TOP}.
*/
void removeTask(TaskRecord task, String reason, int mode) {
for (ActivityRecord record : task.mActivities) {
onActivityRemovedFromStack(record);
}
final boolean removed = mTaskHistory.remove(task);
if (removed) {
EventLog.writeEvent(EventLogTags.AM_REMOVE_TASK, task.taskId, getStackId());
}
removeActivitiesFromLRUListLocked(task);
updateTaskMovement(task, true);
if (mode == REMOVE_TASK_MODE_DESTROYING && task.mActivities.isEmpty()) {
// TODO: VI what about activity?
final boolean isVoiceSession = task.voiceSession != null;
if (isVoiceSession) {
try {
task.voiceSession.taskFinished(task.intent, task.taskId);
} catch (RemoteException e) {
}
}
if (task.autoRemoveFromRecents() || isVoiceSession) {
// Task creator asked to remove this when done, or this task was a voice
// interaction, so it should not remain on the recent tasks list.
mStackSupervisor.mRecentTasks.remove(task);
}
task.removeWindowContainer();
}
if (mTaskHistory.isEmpty()) {
if (DEBUG_STACK) Slog.i(TAG_STACK, "removeTask: removing stack=" + this);
// We only need to adjust focused stack if this stack is in focus and we are not in the
// process of moving the task to the top of the stack that will be focused.
if (isOnHomeDisplay() && mode != REMOVE_TASK_MODE_MOVING_TO_TOP
&& mStackSupervisor.isFocusedStack(this)) {
String myReason = reason + " leftTaskHistoryEmpty";
if (!inMultiWindowMode() || !adjustFocusToNextFocusableStack(myReason)) {
mStackSupervisor.moveHomeStackToFront(myReason); //将桌面stack移到前台
}
}
if (isAttached()) {
getDisplay().positionChildAtBottom(this); //stack中的task为空时,移到最后
}
if (!isActivityTypeHome()) {
remove();
}
}
task.setStack(null);
// Notify if a task from the pinned stack is being removed (or moved depending on the mode)
if (inPinnedWindowingMode()) {
mService.mTaskChangeNotificationController.notifyActivityUnpinned();
}
}
#######ActivityStack#remove
完全移除stack
733 /** Removes the stack completely. Also calls WindowManager to do the same on its side. */
734 void remove() {
735 removeFromDisplay();
736 mWindowContainerController.removeContainer();
737 mWindowContainerController = null;
738 onParentChanged();
739 }
在removeHistoryRecordsForAppLocked中说过
!r.haveState && !r.stateNotNeeded) || r.finishing时,remove = true;
haveState会在activityResumedLocked中被赋值为false;haveState在activityStoppedLocked中被置为true
那么可能只有最上面的resumed的Activity需要执行removeActivityFromHistoryLocked
如自己写一个demo,MainActivity->ActivityA->kill -9->dumpsys activity a
发现
Stack #18: type=standard mode=fullscreen
isSleeping=false
mBounds=Rect(0, 0 - 0, 0)
Task id #65
mBounds=Rect(0, 0 - 0, 0)
mMinWidth=-1
mMinHeight=-1
mLastNonFullscreenBounds=null
* TaskRecord{d186cc1 #65 A=com.test.weijuncheng.testactivity U=0 StackId=18 sz=1}
userId=0 effectiveUid=u0a159 mCallingUid=u0a27 mUserSetupComplete=true mCallingPackage=com.miui.home
affinity=com.test.weijuncheng.testactivity
intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.test.weijuncheng.testactivity/.MainActivity}
realActivity=com.test.weijuncheng.testactivity/.MainActivity
autoRemoveRecents=false isPersistable=true numFullscreen=1 activityType=1
rootWasReset=true mNeverRelinquishIdentity=true mReuseTask=false mLockTaskAuth=LOCK_TASK_AUTH_PINNABLE
Activities=[ActivityRecord{35f118b u0 com.test.weijuncheng.testactivity/.MainActivity t65}]
askedCompatMode=false inRecents=true isAvailable=true
stackId=18
hasBeenVisible=true mResizeMode=RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION mSupportsPictureInPicture=false isResizeable=true supportsSplitScreenWindowingMode=true lastActiveTime=14601609 (inactive for 586s)
* Hist #0: ActivityRecord{35f118b u0 com.test.weijuncheng.testactivity/.MainActivity t65}
packageName=com.test.weijuncheng.testactivity processName=com.test.weijuncheng.testactivity
launchedFromUid=10027 launchedFromPackage=com.miui.home userId=0
app=null
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.test.weijuncheng.testactivity/.MainActivity bnds=[584,778][752,946] (has extras) }
frontOfTask=true task=TaskRecord{d186cc1 #65 A=com.test.weijuncheng.testactivity U=0 StackId=18 sz=1}
taskAffinity=com.test.weijuncheng.testactivity
realActivity=com.test.weijuncheng.testactivity/.MainActivity
baseDir=/data/app/com.test.weijuncheng.testactivity-al6qKDybRW_UdbV4YRC9PQ==/base.apk
dataDir=/data/user/0/com.test.weijuncheng.testactivity
stateNotNeeded=false componentSpecified=true mActivityType=standard
compat={440dpi} labelRes=0x7f0b001d icon=0x7f0a0000 theme=0x7f0c0005
mLastReportedConfigurations:
mGlobalConfig={1.0 ?mcc?mnc [en_US] ldltr sw392dp w392dp h768dp 440dpi nrml long port finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 0, 0) mAppBounds=Rect(0, 80 - 1080, 2210) mWindowingMode=fullscreen mActivityType=undefined} s.8 themeChanged=0 themeChangedFlags=0}
mOverrideConfig={1.0 ?mcc?mnc [en_US] ldltr sw392dp w392dp h768dp 440dpi nrml long port finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1080, 2130) mAppBounds=Rect(0, 80 - 1080, 2210) mWindowingMode=fullscreen mActivityType=standard} s.8 themeChanged=0 themeChangedFlags=0}
CurrentConfiguration={1.0 ?mcc?mnc [en_US] ldltr sw392dp w392dp h768dp 440dpi nrml long port finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1080, 2130) mAppBounds=Rect(0, 80 - 1080, 2210) mWindowingMode=fullscreen mActivityType=standard} s.8 themeChanged=0 themeChangedFlags=0}
taskDescription: label="null" icon=null iconResource=0 iconFilename=null primaryColor=ff008577
backgroundColor=fffafafa
statusBarColor=ff00574b
navigationBarColor=ffffffff
launchFailed=false launchCount=0 lastLaunchTime=-9m49s25ms
haveState=true icicle=Bundle[mParcelledData.dataSize=1132]
state=DESTROYED stopped=true delayedResume=false finishing=false
keysPaused=false inHistory=true visible=false sleeping=false idle=true mStartingWindowState=STARTING_WINDOW_SHOWN
fullscreen=true noDisplay=false immersive=false launchMode=0
frozenBeforeDestroy=false forceNewConfig=false
mActivityType=standard
waitingVisible=false nowVisible=false lastVisibleTime=-9m47s613ms
resizeMode=RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION
mLastReportedMultiWindowMode=false mLastReportedPictureInPictureMode=false
realComponentName=com.test.weijuncheng.testactivity/.MainActivity
此时下方的ActivityRecord还能被dump出来(不同于正常回退的情况)
![](https://img.haomeiwen.com/i6635796/ded5fb09caf032f4.png)
![](https://img.haomeiwen.com/i6635796/bfe63304799b4646.png)