9.2.1 app.kill[-> ProcessRecord.java] void kill(String reason, boolean noisy) { if (!killedByAm) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "kill"); if (noisy) { Slog.i(TAG, "Killing " + toShortString() + " (adj " + setAdj + "): " + reason); } EventLog.writeEvent(EventLogTags.AM_KILL, userId, pid, processName, setAdj, reason); Process.killProcessQuiet(pid); //杀进程 Process.killProcessGroup(info.uid, pid); //杀进程组,包括native进程 if (!persistent) { killed = true; killedByAm = true; } Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } } 此处reason为“crash”,关于杀进程的过程见我的另一篇文章 理解杀进程的实现原理. 9.2.2 handleAppDiedLocked[-> ActivityManagerService.java] private final void handleAppDiedLocked(ProcessRecordapp, boolean restarting, boolean allowRestart) { int pid = app.pid; //清除应用中service/receiver/ContentProvider信息 boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1); if (!kept && !restarting) { removeLruProcessLocked(app); if (pid > 0) { ProcessList.remove(pid); } } if (mProfileProc == app) { clearProfilerLocked(); } //清除应用中activity相关信息 boolean hasVisibleActivities = mStackSupervisor.handleAppDiedLocked(app); app.activities.clear(); ... if (!restarting && hasVisibleActivities && !mStackSupervisor.resumeTopActivitiesLocked()) { mStackSupervisor.ensureActivitiesVisibleLocked(null, 0); } } 9.3 ASS.resumeTopActivitiesLocked[-> ActivityStackSupervisor.java] boolean resumeTopActivitiesLocked() { return resumeTopActivitiesLocked(null, null, null); } boolean resumeTopActivitiesLocked(ActivityStacktargetStack, ActivityRecordtarget, BundletargetOptions) { if (targetStack == null) { targetStack = mFocusedStack; } boolean result = false; if (isFrontStack(targetStack)) { //【见小节9.3.1】 result = targetStack.resumeTopActivityLocked(target, targetOptions); } for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStackstack = stacks.get(stackNdx); if (stack == targetStack) { continue; //已经启动 } if (isFrontStack(stack)) { stack.resumeTopActivityLocked(null); } } } return result; } 此处 mFocusedStack 是当前正在等待接收input事件或者正在启动下一个activity的 ActivityStack 。 9.3.1 AS.resumeTopActivityLocked[-> ActivityStack.java] final boolean .resumeTopActivityLocked(ActivityRecordprev, Bundleoptions) { ... result = resumeTopActivityInnerLocked(prev, options);//【见小节9.3.2】 return result; } 9.3.2 AS.resumeTopActivityInnerLocked[-> ActivityStack.java] private boolean resumeTopActivityInnerLocked(ActivityRecordprev, Bundleoptions) { //找到mTaskHistory栈中第一个未处于finishing状态的Activity final ActivityRecordnext = topRunningActivityLocked(null); if (mResumedActivity == next && next.state == ActivityState.RESUMED && mStackSupervisor.allResumedActivitiesComplete()) { //当top activity已经处于resume,则无需操作; return false; } if (mService.isSleepingOrShuttingDown() && mLastPausedActivity == next && mStackSupervisor.allPausedActivitiesComplete()) { //当正处于sleeping状态,top activity处于paused,则无需操作 return false; } //正在启动app的activity,确保app不会被设置为stopped AppGlobals.getPackageManager().setPackageStoppedState( next.packageName, false, next.userId); //回调应用onResume方法 next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState, mService.isNextTransitionForward(), resumeAnimOptions); ... } 该方法代码比较长,这里就简单列举几条比较重要的代码。执行完该方法,应用也便完成了activity的resume过程。 9.4 finishTopRunningActivityLocked9.4.1 ASS.finishTopRunningActivityLocked[-> ActivityStackSupervisor.java] void finishTopRunningActivityLocked(ProcessRecordapp, String reason) { for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; final int numStacks = stacks.size(); for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { final ActivityStackstack = stacks.get(stackNdx); //此处reason= "force-crash"【见小节9.4.2】 stack.finishTopRunningActivityLocked(app, reason); } } } 9.4.2 AS.finishTopRunningActivityLockedfinal void finishTopRunningActivityLocked(ProcessRecordapp, String reason) { //找到栈顶第一个不处于finishing状态的activity ActivityRecord r = topRunningActivityLocked(null); if (r != null && r.app == app) { int taskNdx = mTaskHistory.indexOf(r.task); int activityNdx = r.task.mActivities.indexOf(r); //【见小节9.4.3】 finishActivityLocked(r, Activity.RESULT_CANCELED, null, reason, false); --activityNdx; if (activityNdx < 0) { do { --taskNdx; if (taskNdx < 0) { break; } activityNdx = mTaskHistory.get(taskNdx).mActivities.size() - 1; } while (activityNdx < 0); } if (activityNdx >= 0) { r = mTaskHistory.get(taskNdx).mActivities.get(activityNdx); if (r.state == ActivityState.RESUMED || r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED) { if (!r.isHomeActivity() || mService.mHomeProcess != r.app) { //【见小节9.4.3】 finishActivityLocked(r, Activity.RESULT_CANCELED, null, reason, false); } } } } } 9.4.3 AS.finishActivityLockedfinal boolean finishActivityLocked(ActivityRecord r, int resultCode, IntentresultData, String reason, boolean oomAdj) { if (r.finishing) { return false; //正在finishing则返回 } //设置finish状态的activity不可见 r.makeFinishingLocked(); //暂停key的分发事件 r.pauseKeyDispatchingLocked(); mWindowManager.prepareAppTransition(endTask ? AppTransition.TRANSIT_TASK_CLOSE : AppTransition.TRANSIT_ACTIVITY_CLOSE, false); mWindowManager.setAppVisibility(r.appToken, false); //回调activity的onPause方法 startPausingLocked(false, false, false, false); ... } 该方法最终会回调到activity的pause方法。 执行到这,我们还回过来看小节 5.crashApplication 中,处理完makeAppCrashingLocked,则会再发送消息SHOW_ERROR_MSG,弹出提示crash的对话框,接下来再看看该过程。 10. UiHandler通过mUiHandler发送message,且消息的msg.waht=SHOW_ERROR_MSG,接下来进入UiHandler来看看handleMessage的处理过程。 [-> ActivityManagerService.java] final class UiHandler extends Handler { public void handleMessage(Messagemsg) { switch (msg.what) { case SHOW_ERROR_MSG: { HashMap<String, Object> data = (HashMap<String, Object>) msg.obj; synchronized (ActivityManagerService.this) { ProcessRecordproc = (ProcessRecord)data.get("app"); AppErrorResultres = (AppErrorResult) data.get("result"); 、 boolean isBackground = (UserHandle.getAppId(proc.uid) >= Process.FIRST_APPLICATION_UID && proc.pid != MY_PID); ... if (mShowDialogs && !mSleeping && !mShuttingDown) { //创建提示crash对话框,等待用户选择,5分钟操作等待。 Dialog d = new AppErrorDialog(mContext, ActivityManagerService.this, res, proc); d.show(); proc.crashDialog = d; } else { //当处于sleep状态,则默认选择退出。 if (res != null) { res.set(0); } } } } break; ... } } 在发生crash时,默认系统会弹出提示crash的对话框,并阻塞等待用户选择是“退出”或 “退出并报告”,当用户不做任何选择时5min超时后,默认选择“退出”,当手机休眠时也默认选择“退出”。到这里也并没有真正结束,在小节 2.uncaughtException 中在 finnally 语句块还有一个杀进程的动作。 11. killProcessProcess.killProcess(Process.myPid()); System.exit(10); 通过finnally语句块保证能执行并彻底杀掉Crash进程,关于杀进程的过程见我的另一篇文章 理解杀进程的实现原理 .。当Crash进程被杀后,并没有完全结束,还有Binder死亡通知的流程还没有处理完成。 12. 小结当进程抛出未捕获异常时,则系统会处理该异常并进入crash处理流程。
其中最为核心的工作图中红色部分 AMS.handleAppCrashLocked 的主要功能:
另外, AMS.handleAppCrashLocked ,该方法内部主要调用链,如下: AMS.handleAppCrashLocked ASS.handleAppCrashLocked AS.handleAppCrashLocked AS.finishCurrentActivityLocked AMS.removeProcessLocked ProcessRecord.kill AMS.handleAppDiedLocked ASS.handleAppDiedLocked AMS.cleanUpApplicationRecordLocked AS.handleAppDiedLocked AS.removeHistoryRecordsForAppLocked ASS.resumeTopActivitiesLocked AS.resumeTopActivityLocked AS.resumeTopActivityInnerLocked ASS.finishTopRunningActivityLocked AS.finishTopRunningActivityLocked AS.finishActivityLocked 三、Binder死亡通知进程被杀,如果还记得Binder的死亡回调机制,在应用进程创建的过程中有一个 attachApplicationLocked 方法的过程中便会创建死亡通知。 [-> ActivityManagerService.java] private final boolean attachApplicationLocked(IApplicationThreadthread, int pid) { try { //创建binder死亡通知 AppDeathRecipientadr = 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 AppDeathRecipientimplements IBinder.DeathRecipient { public void binderDied() { synchronized(ActivityManagerService.this) { appDiedLocked(mApp, mPid, mAppThread, true);//【见小节2】 } } } 2. appDiedLockedfinal void appDiedLocked(ProcessRecordapp, int pid, IApplicationThreadthread, 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(ProcessRecordapp, 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(ProcessRecordapp, 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; }
4.2 清理ContentProviderprivate final boolean cleanUpApplicationRecordLocked(...) { ... for (int i = app.pubProviders.size() - 1; i >= 0; i--) { //获取该进程已发表的ContentProvider ContentProviderRecordcpr = 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--) { ContentProviderConnectionconn = 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 清理BroadcastReceiverprivate 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 清理Processprivate final boolean cleanUpApplicationRecordLocked(...) { ... //当app正在备份时的处理方式 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) { ... IBackupManagerbm = IBackupManager.Stub.asInterface( ServiceManager.getService(Context.BACKUP_SERVICE)); bm.agentDisconnected(app.info.packageName); } for (int i = mPendingProcessChanges.size() - 1; i >= 0; i--) { ProcessChangeItemitem = 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; } 对于需要重启进程的情形有:
5. 小结当crash进程执行kill操作后,进程被杀。此时需要掌握binder 死亡通知原理,由于Crash进程中拥有一个Binder服务端 ApplicationThread ,而应用进程在创建过程调用attachApplicationLocked(),从而attach到system_server进程,在system_server进程内有一个 ApplicationThreadProxy ,这是相对应的Binder客户端。当Binder服务端 ApplicationThread 所在进程(即Crash进程)挂掉后,则Binder客户端能收到相应的死亡通知,从而进入binderDied流程。更多关于bInder原理,这里就不细说,博客中有关于binder系列的专题。
四、 总结本文主要以源码的视角,详细介绍了到应用crash后系统的处理流程:
这基本就是整个应用Crash后系统的执行过程。 (责任编辑:好模板) |