极力推荐Android 开发大总结文章:欢迎收藏
Android 开发技术文章大总结

本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容:

九、 AppErrors.handleAppCrashLocked()
十、UIHandler
十一、 killProcess
十二、小结

本篇文章续接 深入理解 Android 9.0 Crash 机制(一),Crash 之前详细步骤请看上篇文章。

九、 AppErrors.handleAppCrashLocked()

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 所有的ServiceServiceRecord sr = app.services.valueAt(i);// Service 一会自动起来 重置count 为1,否则+1if (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加入到mBadProcessesmBadProcesses.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<ActivityRecord> 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<ActivityRecord> 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 */);//结束当前activityfinishCurrentActivityLocked(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进程设置成可重启flagsif (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 appTaskRecord 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.1final 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.2finishActivityLocked(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<ActivityRecord> 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<String, Object> data = (HashMap<String, Object>) 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处理流程。

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.handleAppCrashLockedASS.handleAppCrashLockedAS.handleAppCrashLockedAS.finishCurrentActivityLockedAMS.removeProcessLockedProcessRecord.killAMS.handleAppDiedLockedASS.handleAppDiedLockedAMS.cleanUpApplicationRecordLockedAS.handleAppDiedLockedAS.removeHistoryRecordsForAppLockedASS.resumeTopActivitiesLockedAS.resumeTopActivityLockedAS.resumeTopActivityInnerLockedASS.finishTopRunningActivityLockedAS.finishTopRunningActivityLockedAS.finishActivityLocked

长按识别二维码,领福利

至此,本篇已结束,如有不对的地方,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!

如有侵权,请联系小编,小编对此深感抱歉,届时小编会删除文章,立即停止侵权行为,请您多多包涵。

小礼物走一走,来简书关注我

深入理解 Android 9.0 Crash 机制(二)相关推荐

  1. 深入理解Android音视频同步机制(二)ExoPlayer的avsync逻辑

    深入理解Android音视频同步机制(一)概述 深入理解Android音视频同步机制(二)ExoPlayer的avsync逻辑 深入理解Android音视频同步机制(三)NuPlayer的avsync ...

  2. Android 10.0 PackageManagerService(二)权限扫描-[Android取经之路]

    摘要:PackageManagerService在systemReady()后,进行了/system/etc/permissions中的各种xml进行扫描,进行相应的权限存储,供以后使用 阅读本文大约 ...

  3. Android 6.0 PM机制系列(四) APK安装需要空间分析

    前言 在Android 9.0 PM机制系列(四) APK安装需要空间分析文章中,我们重点分析了Android9.0需要的最小APK安装存储空间大小.结论就是:只要系统空间小于Math.min(get ...

  4. Android Touch事件传递机制 二:单纯的(伪生命周期) 这个清楚一点

    转载于:http://blog.csdn.net/yuanzeyao/article/details/38025165 在前一篇文章中,我主要讲解了Android源码中的Touch事件的传递过程,现在 ...

  5. Android Touch事件传递机制 二:单纯的(伪生命周期)

    转载于:http://blog.csdn.net/yuanzeyao/article/details/38025165 在前一篇文章中,我主要讲解了Android源码中的Touch事件的传递过程,现在 ...

  6. Android 8.0 VDEX机制简介

    背景 Android 8.0在odex的基础上又引入了vdex机制,目的是为了降低dex2oat时间. 因为当系统ota后,用户自己安装的应用是不会发生任何变化的,但framework代码已经发生了变 ...

  7. android 6.0 log,android 6.0 logcat机制(二)logcat从logd中获取log保存到文件中

    一.设置保存log文件的路径 在手机刚开机的时候,会有类似如下命令执行 /system/bin/logcat -r 5120 -v threadtime -v usec -v printable -n ...

  8. android 6.0 logcat机制(二)logcat从logd中获取log保存到文件中

    这篇博客分析的是logcat是如何获取logd中的log,然后写入文件. 一.设置保存log文件的路径 在手机刚开机的时候,会有类似如下命令执行 /system/bin/logcat -r 5120 ...

  9. 安卓 java内存碎片_理解Android Java垃圾回收机制

    Jvm(Java虚拟机)内存模型 从Jvm内存模型中入手对于理解GC会有很大的帮助,不过这里只需要了解一个大概,说多了反而混淆视线. Jvm(Java虚拟机)主要管理两种类型内存:堆和非堆. 堆是运行 ...

最新文章

  1. c++异常Try catch
  2. IOS应用管理学习,进阶,涉及字典转模型,工厂方法,面向对象思想,页面布局等
  3. 求最大公约数——欧几里得算法(JAVA)
  4. python字典的常用方法_python操作字典类型的常用方法(推荐)
  5. 浅谈百度云计算网络的构建之路
  6. 论文赏析[EMNLP18]针对自顶向下和中序移进归约成分句法分析的Dynamic Oracles
  7. ASP.NET开发学习视频教程大全(共800集)
  8. 软件项目需求调研报告模板下载_强烈推荐:一个软件,即可搞定所有方案报价工作...
  9. 强大好看的dz论坛社区源码手机端
  10. 工业通讯 | OEM嵌入式通讯模块与西门子PLC S7-1200通讯测试指南
  11. 软件项目管理第十章笔记---项目采购管理
  12. 数字PCR和实时PCR的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  13. 免费常用IP归属地查询API
  14. 解耦技巧——依赖注入!
  15. 基于 Java Spring Security 的关注微信公众号即登录的设计与实现 ya
  16. 数据库身份证号用什么类型_【文末送书】MySQL数据库?看这一篇干货文章就够了!...
  17. autoGPT搭建详细教程-通俗易懂
  18. Scala中下划线“_“的应用场景
  19. 七天玩转Redis | Day7、Redis常见面试题及课程总结
  20. 初识Flink,简要介绍Flink

热门文章

  1. 31 《象与骑象人:幸福的假设》 -豆瓣评分8.4
  2. 基于MT5的短线反向交易策略
  3. OpenCV 实现图片的水平投影与垂直投影,并进行行分割
  4. 怎么学习电脑板编程c语言,电脑编程c语言学习
  5. Python爬虫核心知识-第二章:2.2 爬虫urllib.parse模块
  6. windows二维码工具3.0
  7. 论计算机取证工具软件及其检测(转)
  8. vlc多媒体播放器VLC Media Player 3.0.7.1中文版
  9. mysql bulkupdate_django_bulk_update源码分析
  10. Intellij Idea整合JProfiler插件