深入理解|深入理解 Android 9.0 Crash 机制(二)
阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android
本篇文章主要介绍 Android
开发中的部分知识点,通过阅读本篇文章,您将收获以下内容:
九、 AppErrors.handleAppCrashLocked()本篇文章续接 深入理解 Android 9.0 Crash 机制(一),Crash 之前详细步骤请看上篇文章。
十、UIHandler
十一、 killProcess
十二、小结
九、 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();
- [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
,这是以pid
为key
,记录着所有的ProcessRecord
信息。该对象的同步保护是通过自身锁,而非全局ActivityManager
锁。
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
处理流程。文章图片
Crash处理流程
其中最为核心的工作图中红色部分
AMS.handleAppCrashLocked
的主要功能:- 当同一进程1分钟之内连续两次
Crash
,则执行的情况下:
persistent
进程:
-ASS.handleAppCrashLocked,
直接结束该应用所有activity
-
AMS.removeProcessLocked,
杀死该进程以及同一个进程组下的所有进
-ASS.resumeTopActivitiesLocked
,恢复栈顶第一个非finishing
状态的activity
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 干货分享
至此,本篇已结束,如有不对的地方,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!
文章图片
推荐阅读
- android第三方框架(五)ButterKnife
- 深入理解Go之generate
- 考研英语阅读终极解决方案——阅读理解如何巧拿高分
- 由浅入深理解AOP
- Android中的AES加密-下
- 逻辑回归的理解与python示例
- 带有Hilt的Android上的依赖注入
- 【1057快报】深入机关,走下田间,交通普法,共创文明
- android|android studio中ndk的使用
- 生发知识,带你深入了解