Android系统中当应用进程被kill杀掉时,底层会有该进程的Binder服务端的死亡回调通知。在应用进程创建的过程中有一个attachApplicationLocked
方法的过程中便会创建死亡通知。
[-> ActivityManagerService.java]
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
try {
//创建binder死亡通知
AppDeathRecipient adr = new AppDeathRecipient(
app, pid, thread);
thread.asBinder().linkToDeath(adr, 0);
app.deathRecipient = adr;
} catch (RemoteException e) {
app.resetPackageList(mProcessStats);
startProcessLocked(app, "link fail", processName);
return false;
}
...
}
当binder服务端挂了之后,便会通过binder的DeathRecipient来通知AMS进行相应的清理收尾工作。发生crash的进程会被系统kill掉,那么当该进程会杀,则会回调到binderDied()方法。
1. binderDied
[-> ActivityManagerService.java]
private final class AppDeathRecipient implements IBinder.DeathRecipient {
public void binderDied() {
synchronized(ActivityManagerService.this) {
appDiedLocked(mApp, mPid, mAppThread, true);//【见小节2】
}
}
}
2. appDiedLocked
final void appDiedLocked(ProcessRecord app, int pid, IApplicationThread thread,
boolean fromBinderDied) {
...
if (!app.killed) {
if (!fromBinderDied) {
Process.killProcessQuiet(pid);
}
killProcessGroup(app.info.uid, pid);
app.killed = true;
}
// Clean up already done if the process has been re-started.
if (app.pid == pid && app.thread != null &&
app.thread.asBinder() == thread.asBinder()) {
boolean doLowMem = app.instrumentationClass == null;
boolean doOomAdj = doLowMem;
if (!app.killedByAm) {
mAllowLowerMemLevel = true;
} else {
mAllowLowerMemLevel = false;
doLowMem = false;
}
//【见小节3】
handleAppDiedLocked(app, false, true);
if (doOomAdj) {
updateOomAdjLocked();
}
if (doLowMem) {
doLowMemReportIfNeededLocked(app);
}
}
...
}
3 handleAppDiedLocked
[-> ActivityManagerService.java]
private final void handleAppDiedLocked(ProcessRecord app,
boolean restarting, boolean allowRestart) {
int pid = app.pid;
//清理应用程序service, BroadcastReceiver, ContentProvider相关信息【见小节4】
boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1);
if (!kept && !restarting) {
removeLruProcessLocked(app);
if (pid > 0) {
ProcessList.remove(pid);
}
}
//清理activity相关信息
boolean hasVisibleActivities = mStackSupervisor.handleAppDiedLocked(app);
app.activities.clear();
...
//恢复栈顶第一个非finish的activity
if (!restarting && hasVisibleActivities && !mStackSupervisor.resumeTopActivitiesLocked()) {
mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
}
}
4 cleanUpApplicationRecordLocked
该方法清理应用程序service, BroadcastReceiver, ContentProvider,process相关信息,为了便于说明将该方法划分为4个部分讲解
4.1 清理service
参数restarting = false, allowRestart =true, index =-1
private final boolean cleanUpApplicationRecordLocked(ProcessRecord app,
boolean restarting, boolean allowRestart, int index) {
...
mProcessesToGc.remove(app);
mPendingPssProcesses.remove(app);
//如果存在,则清除crash/anr/wait对话框
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的死亡通告
app.makeInactive(mProcessStats);
app.waitingToKill = null;
app.forcingToForeground = null;
//将app移除前台进程
updateProcessForegroundLocked(app, false, false);
app.foregroundActivities = false;
app.hasShownUi = false;
app.treatLikeActivity = false;
app.hasAboveClient = false;
app.hasClientActivities = false;
//清理service信息,这个过程也比较复杂,后续再展开
mServices.killServicesLocked(app, allowRestart);
boolean restart = false;
}
- mProcessesToGc:记录着需要尽快执行gc的进程列表
- mPendingPssProcesses:记录着需要收集内存信息的进程列表
4.2 清理ContentProvider
private final boolean cleanUpApplicationRecordLocked(...) {
...
for (int i = app.pubProviders.size() - 1; i >= 0; i--) {
//获取该进程已发表的ContentProvider
ContentProviderRecord cpr = app.pubProviders.valueAt(i);
final boolean always = app.bad || !allowRestart;
//ContentProvider服务端被杀,则client端进程也会被杀
boolean inLaunching = removeDyingProviderLocked(app, cpr, always);
if ((inLaunching || always) && cpr.hasConnectionOrHandle()) {
restart = true; //需要重启
}
cpr.provider = null;
cpr.proc = null;
}
app.pubProviders.clear();
//处理正在启动并且是有client端正在等待的ContentProvider
if (cleanupAppInLaunchingProvidersLocked(app, false)) {
restart = true;
}
//取消已连接的ContentProvider的注册
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();
}
4.3 清理BroadcastReceiver
private final boolean cleanUpApplicationRecordLocked(...) {
...
skipCurrentReceiverLocked(app);
// 取消注册的广播接收者
for (int i = app.receivers.size() - 1; i >= 0; i--) {
removeReceiverLocked(app.receivers.valueAt(i));
}
app.receivers.clear();
}
4.4 清理Process
private final boolean cleanUpApplicationRecordLocked(...) {
...
//当app正在备份时的处理方式
if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
...
IBackupManager bm = IBackupManager.Stub.asInterface(
ServiceManager.getService(Context.BACKUP_SERVICE));
bm.agentDisconnected(app.info.packageName);
}
for (int i = mPendingProcessChanges.size() - 1; i >= 0; i--) {
ProcessChangeItem item = mPendingProcessChanges.get(i);
if (item.pid == app.pid) {
mPendingProcessChanges.remove(i);
mAvailProcessChanges.add(item);
}
}
mUiHandler.obtainMessage(DISPATCH_PROCESS_DIED, app.pid, app.info.uid, null).sendToTarget();
if (!app.persistent || app.isolated) {
removeProcessNameLocked(app.processName, app.uid);
if (mHeavyWeightProcess == app) {
mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
mHeavyWeightProcess.userId, 0));
mHeavyWeightProcess = null;
}
} else if (!app.removed) {
//对于persistent应用,则需要重启
if (mPersistentStartingProcesses.indexOf(app) < 0) {
mPersistentStartingProcesses.add(app);
restart = true;
}
}
//mProcessesOnHold:记录着试图在系统ready之前就启动的进程。
//在那时并不启动这些进程,先记录下来,等系统启动完成则启动这些进程。
mProcessesOnHold.remove(app);
if (app == mHomeProcess) {
mHomeProcess = null;
}
if (app == mPreviousProcess) {
mPreviousProcess = null;
}
if (restart && !app.isolated) {
//仍有组件需要运行在该进程中,因此重启该进程
if (index < 0) {
ProcessList.remove(app.pid);
}
addProcessNameLocked(app);
startProcessLocked(app, "restart", app.processName);
return true;
} else if (app.pid > 0 && app.pid != MY_PID) {
//移除该进程相关信息
boolean removed;
synchronized (mPidsSelfLocked) {
mPidsSelfLocked.remove(app.pid);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
}
app.setPid(0);
}
return false;
}
对于需要重启进程的情形有:
mLaunchingProviders
:记录着存在client端等待的ContentProvider。应用当前正在启动中,当ContentProvider一旦发布则将该ContentProvider将从该list去除。当进程包含这样的ContentProvider,则需要重启进程。mPersistentStartingProcesses
:记录着试图在系统ready之前就启动的进程。在那时并不启动这些进程,先记录下来,等系统启动完成则启动这些进程。当进程属于这种类型也需要重启。
5. 小结
当crash进程执行kill操作后,进程被杀。此时需要掌握binder 死亡通知原理,由于Crash进程中拥有一个Binder服务端ApplicationThread
,而应用进程在创建过程调用attachApplicationLocked(),从而attach到system_server进程,在system_server进程内有一个ApplicationThreadProxy
,这是相对应的Binder客户端。当Binder服务端ApplicationThread
所在进程(即Crash进程)挂掉后,则Binder客户端能收到相应的死亡通知,从而进入binderDied流程。
更多参考:https://blog.csdn.net/wxlinwzl/article/details/77749619