🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
AMS handleApplicationCrash函数的代码如下: **ActivityManagerService.java::handleApplicationCrash** ~~~ public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfocrashInfo) { //找到对应的ProcessRecord信息,后面那个字符串“Crash”用于打印输出 ProcessRecord r = findAppProcess(app, "Crash"); finalString processName = app == null ? "system_server" : (r == null ? "unknown": r.processName); //添加crash信息到dropbox中 ddErrorToDropBox("crash", r, processName, null, null, null,null, null, crashInfo); //调用crashApplication函数 crashApplication(r, crashInfo); } ~~~ 上述代码中的crashApplication 函数的代码如下: **ActivityManagerService.java::crashApplication** ~~~ private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfocrashInfo) { longtimeMillis = System.currentTimeMillis(); //从应用进程传递过来的crashInfo中获取相关信息 StringshortMsg = crashInfo.exceptionClassName; StringlongMsg = crashInfo.exceptionMessage; StringstackTrace = crashInfo.stackTrace; if(shortMsg != null && longMsg != null) { longMsg = shortMsg + ": " + longMsg; } elseif (shortMsg != null) { longMsg = shortMsg; } AppErrorResult result = new AppErrorResult(); synchronized (this) { if(mController != null) { //通知监视者。目前仅MonkeyTest中会为AMS设置监听者。测试过程中可设定是否一检测 //到App Crash即停止测试。另外,Monkey测试也会将App Crash信息保存起来 //供开发人员分析 } final long origId =Binder.clearCallingIdentity(); if (r!= null && r.instrumentationClass != null) { ......// instrumentationClass不为空的情况 } //①调用makeAppCrashingLocked处理,如果返回false,则整个处理流程完毕 if (r == null || !makeAppCrashingLocked(r,shortMsg, longMsg, stackTrace)) { ...... return; } Message msg = Message.obtain(); msg.what = SHOW_ERROR_MSG; HashMap data = new HashMap(); data.put("result", result); data.put("app", r); msg.obj = data; //发送SHOW_ERROR_MSG消息给mHandler,默认处理是弹出一个对话框,提示用户某进程 //崩溃(Crash),用户可以选择“退出”或 “退出并报告” mHandler.sendMessage(msg); ...... }//synchronized(this)结束 //下面这个get函数是阻塞的,直到用户处理了对话框为止。注意,此处涉及两个线程: //handleApplicationCrash函数是在Binder调用线程中处理的,而对话框则是在mHandler所 //在线程中处理的 int res =result.get(); IntentappErrorIntent = null; synchronized (this) { if (r!= null) mProcessCrashTimes.put(r.info.processName, r.info.uid, SystemClock.uptimeMillis()); if (res== AppErrorDialog.FORCE_QUIT_AND_REPORT) //createAppErrorIntentLocked返回一个Intent,该Intent的Action是 //"android.intent.action.APP_ERROR",指定接收者是app. errorReportReceiver //成员,该成员变量在关键点makeAppCrashingLocked中被设置 appErrorIntent =createAppErrorIntentLocked(r, timeMillis, crashInfo); }//synchronized(this)结束 if(appErrorIntent != null) { try {//启动能处理APP_ERROR的应用进程,目前的源码中还没有地方处理它 mContext.startActivity(appErrorIntent); } ...... } } ~~~ 以上代码中还有一个关键函数makeAppCrashingLocked,其代码如下: **ActivityManagerService.java::makeAppCrashingLocked** ~~~ private booleanmakeAppCrashingLocked(ProcessRecord app, String shortMsg, String longMsg, String stackTrace) { app.crashing = true; //生成一个错误报告,存放在crashingReport变量中 app.crashingReport = generateProcessError(app, ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace); /* 在上边代码中,我们知道系统会通过APP_ERROR Intent启动一个Activity去处理错误报告, 实际上在此之前,系统需要为它找到指定的接收者(如果有)。代码在startAppProblemLocked 中,此处简单描述该函数的处理过程如下: 1 先查询Settings Secure表中“send_action_app_error”是否使能,如果没有使能,则 不能设置指定接收者 2 通过PKMS查询安装此Crash应用的应用是否能接收APP_ERROR Intent。必须注意 安装此应用的应用(例如通过“安卓市场”安装了该Crash应用)。如果没有,则转下一步处理 3 查询系统属性“ro.error.receiver.system.apps”是否指定了APP_ERROR处理者,如果 没有,则转下一步处理 4 查询系统属性“ro.error.receiver.default”是否指定了默认的处理者 5 处理者的信息保存在app的errorReportReceiver变量中 另外,如果该Crash应用正好是串行广播发送处理中的一员,则需要结束它的处理流程以 保证后续广播处理能正常执行。读者可参考skipCurrentReceiverLocked函数 */ startAppProblemLocked(app); app.stopFreezingAllLocked(); //调用handleAppCrashLocked做进一步处理。读者可自行阅读 returnhandleAppCrashLocked(app); } ~~~ 当App的Crash处理完后,事情并未就此结束,因为该应用进程退出后,之前AMS为它设置的讣告接收对象将被唤醒。接下来介绍AppDeathRecipientbinderDied的处理流程。