深入理解|深入理解 Android 9.0 Crash 机制(二)

阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容:

九、 AppErrors.handleAppCrashLocked()
十、UIHandler
十一、 killProcess
十二、小结
本篇文章续接 深入理解 Android 9.0 Crash 机制(一),Crash 之前详细步骤请看上篇文章。
九、 AppErrors.handleAppCrashLocked() 【深入理解|深入理解 Android 9.0 Crash 机制(二)】AppErrors.java
1.当同一进程在时间间隔小于1分钟时连续两次Crash,则执行的情况下:
对于非persistent进程:
  • [9.1] mStackSupervisor.handleAppCrashLocked(app);
  • [9.2] removeProcessLocked(app, false, false, “crash”);
  • [9.3] mStackSupervisor.resumeTopActivitiesLocked();
对于persistent进程,则只执行
  • [9.3] mStackSupervisor.resumeTopActivitiesLocked();
2.否则执行
  • [9.4] mStackSupervisor.finishTopCrashedActivitiesLocked(app, reason);
boolean handleAppCrashLocked(ProcessRecord app, String reason, String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) { final long now = SystemClock.uptimeMillis(); final boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0; final boolean procIsBoundForeground = (app.curProcState == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE); Long crashTime; Long crashTimePersistent; boolean tryAgain = false; if (!app.isolated) { crashTime = mProcessCrashTimes.get(app.info.processName, app.uid); crashTimePersistent = mProcessCrashTimesPersistent.get(app.info.processName, app.uid); } else { crashTime = crashTimePersistent = null; }// Bump up the crash count of any services currently running in the proc. //运行在当前进程中的所有服务的crash次数操作 for (int i = app.services.size() - 1; i >= 0; i--) { // list 所有的Service ServiceRecord sr = app.services.valueAt(i); // Service 一会自动起来 重置count 为1,否则+1 if (now > sr.restartTime + ProcessList.MIN_CRASH_INTERVAL) { sr.crashCount = 1; } else { sr.crashCount++; } // 允许重启正在Crash的服务以及 前台Service,wallpapers 等 if (sr.crashCount < mService.mConstants.BOUND_SERVICE_MAX_CRASH_RETRY && (sr.isForeground || procIsBoundForeground)) { tryAgain = true; } } //当同一个进程,连续两次crash的时间间隔小于1分钟时,则认为crash太过于频繁 if (crashTime != null && now < crashTime + ProcessList.MIN_CRASH_INTERVAL) {Slog.w(TAG, "Process " + app.info.processName + " has crashed too many times: killing!"); EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH, app.userId, app.info.processName, app.uid); //【见小节9.1】 mService.mStackSupervisor.handleAppCrashLocked(app); if (!app.persistent) {//不再重启非persistent进程,除非用户显式地调用 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.userId, app.uid, app.info.processName); if (!app.isolated) { //将当前app加入到mBadProcesses mBadProcesses.put(app.info.processName, app.uid, new BadProcessInfo(now, shortMsg, longMsg, stackTrace)); mProcessCrashTimes.remove(app.info.processName, app.uid); } app.bad = true; app.removed = true; //移除非persistent 进程的所有服务,保证不再重启【见小节9.2】 mService.removeProcessLocked(app, false, tryAgain, "crash"); //恢复最顶部的Activity【见小节9.3】 mService.mStackSupervisor.resumeFocusedStackTopActivityLocked(); if (!showBackground) { return false; } } mService.mStackSupervisor.resumeFocusedStackTopActivityLocked(); } else { //此处reason="force-crash"【见小节9.4】 final TaskRecord affectedTask = mService.mStackSupervisor.finishTopRunningActivityLockedfinishTopRunningActivityLocked(app, reason); if (data != null) { data.task = affectedTask; } if (data != null && crashTimePersistent != null && now < crashTimePersistent + ProcessList.MIN_CRASH_INTERVAL) { data.repeating = true; } }if (data != null && tryAgain) { data.isRestartableForService = true; }//当桌面Home 进程 应用crash,并且被三方app所取代,那么需要清空桌面应用的偏爱选项。 final ArrayList activities = app.activities; if (app == mService.mHomeProcess && activities.size() > 0 && (mService.mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { final ActivityRecord r = activities.get(activityNdx); if (r.isActivityTypeHome()) { Log.i(TAG, "Clearing package preferred activities from " + r.packageName); try { //清空偏爱应用 ActivityThread.getPackageManager() .clearPackagePreferredActivities(r.packageName); } catch (RemoteException c) { // pm is in same process, this will never happen. } } } }if (!app.isolated) { //无法记录孤立进程的crash时间点,由于他们并没有一个固定身份. mProcessCrashTimes.put(app.info.processName, app.uid, now); mProcessCrashTimesPersistent.put(app.info.processName, app.uid, now); } //当app存在crash的handler,那么交给其处理 if (app.crashHandler != null) mService.mHandler.post(app.crashHandler); return true; }

9.1 ASS.handleAppCrashLocked ActivityStackSupervisor.java
void handleAppCrashLocked(ProcessRecord app) { 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); //调用ActivityStack【见小节9.1.1】 stack.handleAppCrashLocked(app); } } }

9.1.1 AS.handleAppCrashLocked ActivityStack.java
void handleAppCrashLocked(ProcessRecord app) { for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { final ArrayList activities = mTaskHistory.get(taskNdx).mActivities; for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { final ActivityRecord r = activities.get(activityNdx); if (r.app == app) { Slog.w(TAG, "Force finishing activity " + r.intent.getComponent().flattenToShortString()); // Force the destroy to skip right to removal. r.app = null; mWindowManager.prepareAppTransition(TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */); //结束当前activity finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false, "handleAppCrashedLocked"); } } } }

这里的mTaskHistory数据类型为ArrayList,记录着所有先前的后台activities。遍历所有activities,找到位于该ProcessRecord的所有ActivityRecord,并结束该Acitivity
9.2 AMS.removeProcessLocked ActivityManagerService.java
@GuardedBy("this") boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart, boolean allowRestart, String reason) { final String name = app.processName; final int uid = app.uid; if (DEBUG_PROCESSES) Slog.d(TAG_PROCESSES, "Force removing proc " + app.toShortString() + " (" + name + "/" + uid + ")"); ProcessRecord old = mProcessNames.get(name, uid); if (old != app) { // This process is no longer active, so nothing to do. Slog.w(TAG, "Ignoring remove of inactive process: " + app); return false; } //从mProcessNames移除该进程 removeProcessNameLocked(name, uid); if (mHeavyWeightProcess == app) { mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG, mHeavyWeightProcess.userId, 0)); mHeavyWeightProcess = null; } boolean needRestart = false; if ((app.pid > 0 && app.pid != MY_PID) || (app.pid == 0 && app.pendingStart)) { int pid = app.pid; if (pid > 0) { synchronized (mPidsSelfLocked) { mPidsSelfLocked.remove(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); getPackageManagerInternalLocked().removeIsolatedUid(app.uid); } } boolean willRestart = false; //对于非孤立的persistent进程设置成可重启flags if (app.persistent && !app.isolated) { if (!callerWillRestart) { willRestart = true; } else { needRestart = true; } } // 杀进程【9.2.1】 app.kill(reason, true); //移除进程并清空该进程相关联的activity/service等组件 【9.2.2】 handleAppDiedLocked(app, willRestart, allowRestart); if (willRestart) { //此处willRestart=false,不进入该分支 removeLruProcessLocked(app); addAppLocked(app.info, null, false, null /* ABI override */); } } else { mRemovedProcesses.add(app); }return needRestart; }

  • mProcessNames数据类型为ProcessMap,这是以进程名为key,记录着所有的ProcessRecord信息
  • mPidsSelfLocked数据类型为SparseArray,这是以pidkey,记录着所有的ProcessRecord信息。该对象的同步保护是通过自身锁,而非全局ActivityManager锁。
9.2.1 app.kill ProcessRecord.java]
void kill(String reason, boolean noisy) { //通过am 杀进程 if (!killedByAm) {// 如果不想让am kill 当前进程,可以在这地方跳过 if (!mService.mAmsExt.shouldKilledByAm(this.processName, reason)) { return; }Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "kill"); if (mService != null && (noisy || info.uid == mService.mCurOomAdjUid)) { mService.reportUidInfoMessageLocked(TAG, "Killing " + toShortString() + " (adj " + setAdj + "): " + reason, info.uid); } if (pid > 0) { EventLog.writeEvent(EventLogTags.AM_KILL, userId, pid, processName, setAdj, reason); // pid > 0 杀进程以及所在的进程组 Process.killProcessQuiet(pid); ActivityManagerService.killProcessGroup(uid, pid); } else { pendingStart = false; } if (!persistent) { killed = true; killedByAm = true; } Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } }

此处reason为“crash”.
9.2.2 handleAppDiedLocked ActivityManagerService.java
// 通过AM 移除当前存在的进程,不存在,则清除当前进程包含的所有内容 @GuardedBy("this") private final void handleAppDiedLocked(ProcessRecord app, boolean restarting, boolean allowRestart) { int pid = app.pid; final boolean clearLaunchStartTime = !restarting && app.removed && app.foregroundActivities; //清除应用中service/receiver/ContentProvider信息 boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1, false /*replacingPid*/); if (!kept && !restarting) { // 根据LRU 算法移除 app 进程 removeLruProcessLocked(app); if (pid > 0) { //从list 移除对应的pid ProcessList.remove(pid); } }if (mProfileProc == app) { clearProfilerLocked(); }//清除应用中activity相关信息 boolean hasVisibleActivities = mStackSupervisor.handleAppDiedLocked(app); 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()) { // 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(); }// TODO (b/67683350) // When an app process is removed, activities from the process may be relaunched. In the // case of forceStopPackageLocked the activities are finished before any window is drawn, // and the launch time is not cleared. This will be incorrectly used to calculate launch // time for the next launched activity launched in the same windowing mode. if (clearLaunchStartTime) { final LaunchTimeTracker.Entry entry = mStackSupervisor .getLaunchTimeTracker().getEntry(mStackSupervisor.getWindowingMode()); if (entry != null) { entry.mLaunchStartTime = 0; } } }

9.3 ASS.resumeFocusedStackTopActivityLocked ActivityStackSupervisor.java
boolean resumeFocusedStackTopActivityLocked() { return resumeFocusedStackTopActivityLocked(null, null, null); }boolean resumeFocusedStackTopActivityLocked( ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {if (!readyToResume()) { return false; }if (targetStack != null && isFocusedStack(targetStack)) { //【见小节9.3.1】 return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions); }final ActivityRecord r = mFocusedStack.topRunningActivityLocked(); if (r == null || !r.isState(RESUMED)) { mFocusedStack.resumeTopActivityUncheckedLocked(null, null); } else if (r.isState(RESUMED)) { // Kick off any lingering app transitions form the MoveTaskToFront operation. mFocusedStack.executeAppTransition(targetOptions); }return false; }

9.3.1 AS.resumeTopActivityLocked
ActivityStack.java
//确保 top Activity 在resumed 状态 // 最好使用ActivityStackSupervisor#ActivityStackSupervisor#resumeFocusedStackTopActivityLockedActivityStackSupervisor#resumeFocusedStackTopActivityLocked 待替此方法 boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) { if (mStackSupervisor.inResumeTopActivity) { // Don't even start recursing. return false; }boolean result = false; try { // Protect against recursion. mStackSupervisor.inResumeTopActivity = true; result = resumeTopActivityInnerLocked(prev, options); // When resuming the top activity, it may be necessary to pause the top activity (for // example, returning to the lock screen. We suppress the normal pause logic in // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the // end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here // to ensure any necessary pause logic occurs. In the case where the Activity will be // shown regardless of the lock screen, the call to // {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped. final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */); if (next == null || !next.canTurnScreenOn()) { checkReadyForSleep(); } } finally { mStackSupervisor.inResumeTopActivity = false; }return result; }

9.4 finishTopCrashedActivitiesLocked ActivityStackSupervisor.java
//Finish the topmost activities in all stacks that belong to the crashed app TaskRecord finishTopCrashedActivitiesLocked(ProcessRecord app, String reason) { TaskRecord finishedTask = null; ActivityStack focusedStack = getFocusedStack(); for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx); // It is possible that request to finish activity might also remove its task and stack, // so we need to be careful with indexes in the loop and check child count every time. for (int stackNdx = 0; stackNdx < display.getChildCount(); ++stackNdx) { final ActivityStack stack = display.getChildAt(stackNdx); ////此处reason= "force-crash" 见小节9.4.1 final TaskRecord t = stack.finishTopCrashedActivityLocked(app, reason); if (stack == focusedStack || finishedTask == null) { finishedTask = t; } } } return finishedTask; }

9.4.1AS.finishTopCrashedActivityLocked
ActivityStack.java
/** * Finish the topmost activity that belongs to the crashed app. We may also finish the activity * that requested launch of the crashed one to prevent launch-crash loop. */ final TaskRecord finishTopCrashedActivityLocked(ProcessRecord app, String reason) { ActivityRecord r = topRunningActivityLocked(); TaskRecord finishedTask = null; if (r == null || r.app != app) { return null; } Slog.w(TAG, "Force finishing activity " + r.intent.getComponent().flattenToShortString()); finishedTask = r.getTask(); int taskNdx = mTaskHistory.indexOf(finishedTask); final TaskRecord task = finishedTask; int activityNdx = task.mActivities.indexOf(r); mWindowManager.prepareAppTransition(TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */); // 见小结 9.4.2 finishActivityLocked(r, Activity.RESULT_CANCELED, null, reason, false); finishedTask = task; // Also terminate any activities below it that aren't yet // stopped, to avoid a situation where one will get // re-start our crashing activity once it gets resumed again. --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.isState(RESUMED, PAUSING, PAUSED)) { if (!r.isActivityTypeHome() || mService.mHomeProcess != r.app) { Slog.w(TAG, "Force finishing activity " + r.intent.getComponent().flattenToShortString()); finishActivityLocked(r, Activity.RESULT_CANCELED, null, reason, false); } } } return finishedTask; }

9.4.2 AS.finishActivityLocked
ActivityStack.java
/** * See {@link #finishActivityLocked(ActivityRecord, int, Intent, String, boolean, boolean)} */ final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData, String reason, boolean oomAdj) { return finishActivityLocked(r, resultCode, resultData, reason, oomAdj, !PAUSE_IMMEDIATELY); }/** * @return Returns true if this activity has been removed from the history * list, or false if it is still in the list and will be removed later. */ final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData, String reason, boolean oomAdj, boolean pauseImmediately) { if (r.finishing) { Slog.w(TAG, "Duplicate finish request for " + r); return false; }mWindowManager.deferSurfaceLayout(); try { //设置finish状态的activity不可见 r.makeFinishingLocked(); final TaskRecord task = r.getTask(); EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY, r.userId, System.identityHashCode(r), task.taskId, r.shortComponentName, reason); final ArrayList activities = task.mActivities; final int index = activities.indexOf(r); if (index < (activities.size() - 1)) { task.setFrontOfTask(); if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) { // If the caller asked that this activity (and all above it) // be cleared when the task is reset, don't lose that information, // but propagate it up to the next activity. ActivityRecord next = activities.get(index+1); next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); } } //暂停key的分发事件 r.pauseKeyDispatchingLocked(); adjustFocusedActivityStack(r, "finishActivity"); finishActivityResultsLocked(r, resultCode, resultData); final boolean endTask = index <= 0 && !task.isClearingToReuseTask(); final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE; if (mResumedActivity == r) { if (DEBUG_VISIBILITY || DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare close transition: finishing " + r); if (endTask) { mService.mTaskChangeNotificationController.notifyTaskRemovalStarted( task.taskId); } mWindowManager.prepareAppTransition(transit, false); // Tell window manager to prepare for this one to be removed. r.setVisibility(false); if (mPausingActivity == null) { if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish needs to pause: " + r); if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING, "finish() => pause with userLeaving=false"); //回调activity的onPause方法 startPausingLocked(false, false, null, pauseImmediately); /// M: onBeforeActivitySwitch @{ ActivityRecord nextResumedActivity = mStackSupervisor.getFocusedStack().topRunningActivityLocked(); if (nextResumedActivity != null) { mService.mAmsExt.onBeforeActivitySwitch( mService.mLastResumedActivity, nextResumedActivity, true, nextResumedActivity.getActivityType()); } /// M: onBeforeActivitySwitch @} }if (endTask) { mService.getLockTaskController().clearLockedTask(task); } } else if (!r.isState(PAUSING)) { // If the activity is PAUSING, we will complete the finish once // it is done pausing; else we can just directly finish it here. if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish not pausing: " + r); if (r.visible) { prepareActivityHideTransitionAnimation(r, transit); }final int finishMode = (r.visible || r.nowVisible) ? FINISH_AFTER_VISIBLE : FINISH_AFTER_PAUSE; final boolean removedActivity = finishCurrentActivityLocked(r, finishMode, oomAdj, "finishActivityLocked") == null; // The following code is an optimization. When the last non-task overlay activity // is removed from the task, we remove the entire task from the stack. However, // since that is done after the scheduled destroy callback from the activity, that // call to change the visibility of the task overlay activities would be out of // sync with the activitiy visibility being set for this finishing activity above. // In this case, we can set the visibility of all the task overlay activities when // we detect the last one is finishing to keep them in sync. if (task.onlyHasTaskOverlayActivities(true /* excludeFinishing */)) { for (ActivityRecord taskOverlay : task.mActivities) { if (!taskOverlay.mTaskOverlay) { continue; } prepareActivityHideTransitionAnimation(taskOverlay, transit); } } return removedActivity; } else { if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + r); }return false; } finally { mWindowManager.continueSurfaceLayout(); } }

十、UIHandler 通过mUiHandler发送message,且消息的msg.waht=SHOW_ERROR_MSG,接下来进入UiHandler来看看handleMessage的处理过程。
ActivityManagerService.java
final class UiHandler extends Handler { public void handleMessage(Message msg) { switch (msg.what) { case SHOW_ERROR_MSG: { HashMap data = https://www.it610.com/article/(HashMap) msg.obj; synchronized (ActivityManagerService.this) { ProcessRecord proc = (ProcessRecord)data.get("app"); AppErrorResult res = (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语句块还有一个杀进程的动作。
十一 、 killProcess
Process.killProcess(Process.myPid()); System.exit(10);

通过finnally语句块保证能执行并彻底杀掉Crash进程。当Crash进程被杀后,并没有完全结束,还有Binder死亡通知的流程还没有处理完成
十二、小结 当进程抛出未捕获异常时,则系统会处理该异常并进入Crash处理流程。

深入理解|深入理解 Android 9.0 Crash 机制(二)
文章图片
Crash处理流程
其中最为核心的工作图中红色部分AMS.handleAppCrashLocked的主要功能:
  1. 当同一进程1分钟之内连续两次Crash,则执行的情况下:
对于非persistent进程: -ASS.handleAppCrashLocked, 直接结束该应用所有activity
  • AMS.removeProcessLocked,杀死该进程以及同一个进程组下的所有进
    -ASS.resumeTopActivitiesLocked,恢复栈顶第一个非finishing状态的activity
对于persistent进程,则只执行 ASS.resumeTopActivitiesLocked,恢复栈顶第一个非finishing状态的activity
2.否则,当进程没连续频繁crash
  • ASS.finishTopRunningActivityLocked,执行结束栈顶正在运行activity
    另外,AMS.handleAppCrashLocked,该方法内部主要调用链,如下:
AMS.handleAppCrashLocked ASS.handleAppCrashLocked AS.handleAppCrashLocked AS.finishCurrentActivityLocked AMS.removeProcessLocked ProcessRecord.kill AMS.handleAppDiedLocked ASS.handleAppDiedLocked AMS.cleanUpApplicationRecordLocked AS.handleAppDiedLocked AS.removeHistoryRecordsForAppLockedASS.resumeTopActivitiesLocked AS.resumeTopActivityLocked AS.resumeTopActivityInnerLocked ASS.finishTopRunningActivityLocked AS.finishTopRunningActivityLocked AS.finishActivityLocked

深入理解|深入理解 Android 9.0 Crash 机制(二)
文章图片
友情推荐:
Android 干货分享
至此,本篇已结束,如有不对的地方,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!
深入理解|深入理解 Android 9.0 Crash 机制(二)
文章图片

    推荐阅读