美文网首页Android开发Android开发Android技术知识
深入理解 Android 9.0 Crash 机制(二)

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

作者: 程序员Android1 | 来源:发表于2019-03-30 14:03 被阅读10次

    极力推荐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 所有的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<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 */);
                        //结束当前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<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.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
    
    长按识别二维码,领福利

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

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

    相关文章

      网友评论

        本文标题:深入理解 Android 9.0 Crash 机制(二)

        本文链接:https://www.haomeiwen.com/subject/fckjbqtx.html