【Android 源码分析】Activity生命周期之onStop-1

忽然有一天,我想要做一件事:去代码中去验证那些曾经被"灌输"的理论。

-- 服装学院的IT男
本篇已收录于Activity短暂的一生系列

欢迎一起学习讨论Android应用开发或者WMS

V:WJB6995

Q:707409815

正文

生命周期系列:

之前看过一遍流程的Events日志

复制代码
// SystemService端创建TargetActivity  (writeWmCreateActivity)
03-27 14:41:06.428 27889 28629 I wm_create_activity: [0,253598020,21,com.google.android.dialer/.extensions.GoogleDialtactsActivity,android.intent.action.MAIN,NULL,NULL,270532608]

// SystemService端触发SourceActivity的Pause (writeWmPauseActivity)
03-27 14:41:06.431 27889 28629 I wm_pause_activity: [0,51114540,com.android.launcher3/.uioverrides.QuickstepLauncher,userLeaving=true,pauseBackTasks]

// SourceActivity应用端将执行onPause (writeWmOnPausedCalled)
03-27 14:41:06.448 28606 28606 I wm_on_paused_called: [51114540,com.android.launcher3.uioverrides.QuickstepLauncher,performPause]

// SystemService端把SourceActivity添加进需要stop的集合 (writeWmAddToStopping)
03-27 14:41:06.459 27889 28630 I wm_add_to_stopping: [0,51114540,com.android.launcher3/.uioverrides.QuickstepLauncher,makeInvisible]

// SystemService端要真正触发TargetActivity启动 (writeWmRestartActivity)
03-27 14:41:06.487 27889 28630 I wm_restart_activity: [0,253598020,21,com.google.android.dialer/.extensions.GoogleDialtactsActivity]

// TargetActivity端将执行onCreate  (writeWmOnCreateCalled)
03-27 14:41:06.769  3401  3401 I wm_on_create_called: [253598020,com.google.android.dialer.extensions.GoogleDialtactsActivity,performCreate]

// TargetActivity端将执行onStart (writeWmOnStartCalled)
03-27 14:41:06.900  3401  3401 I wm_on_start_called: [253598020,com.google.android.dialer.extensions.GoogleDialtactsActivity,handleStartActivity]

// TargetActivity端将执行Resume (writeWmOnResumeCalled)
03-27 14:41:06.911  3401  3401 I wm_on_resume_called: [253598020,com.google.android.dialer.extensions.GoogleDialtactsActivity,RESUME_ACTIVITY]

// SystemService端触发SourceActivity的stop (writeWmStopActivity)
03-27 14:41:07.097 27889 30491 I wm_stop_activity: [0,51114540,com.android.launcher3/.uioverrides.QuickstepLauncher]

// SourceActivity应用端将执行onStop (writeWmStopActivity)
03-27 14:41:07.119 28606 28606 I wm_on_stop_called: [51114540,com.android.launcher3.uioverrides.QuickstepLauncher,STOP_ACTIVITY_ITEM]

其中可以看到很早就打印了 "wm_add_to_stopping",但是 SourceActivity 真正执行 onPause ("wm_on_stop_called")却是在最后。

所以按照顺序,先看看 "wm_add_to_stopping"相关的逻辑。

整个流程分为3步:

    1. addToStopping 流程,将应用添加进需要stop的列表 -- system_service进程处理
    1. stopIfPossible 流程,也就是开始执行stop -- system_service进程处理
    1. 应用端处理stop流程 -- 应用进程处理

前面个都是system_service进程处理的,第三步是在 SourceActivity 的应用进程处理。

本篇为 onStop第一篇,介绍 system_service 进程是如何把 SourceActivity 添加进stop集合。

第一步:addToStopping 流程

1 调用链概览

通过Events日志可知"wm_add_to_stopping"的执行在真正启动 TargetActivity 之前。 在 SourceActivity 的 pause 流程之后。

"wm_add_to_stopping" 日志打印的方法在 ActivityRecord::addToStopping 中,在这个方法加上堆栈得到以下内容

复制代码
03-28 14:39:03.326 23968 26756 I wm_add_to_stopping: [0,264636779,com.android.launcher3/.uioverrides.QuickstepLauncher,makeInvisible]
03-28 14:39:03.327 23968 26756 E biubiubiu: ActivityRecord  addToStopping: ActivityRecord{fc6096b u0 com.android.launcher3/.uioverrides.QuickstepLauncher} t7}
03-28 14:39:03.327 23968 26756 E biubiubiu: java.lang.Exception
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.ActivityRecord.addToStopping(ActivityRecord.java:6225)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.ActivityRecord.makeInvisible(ActivityRecord.java:5811)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.EnsureActivitiesVisibleHelper.setActivityVisibilityState(EnsureActivitiesVisibleHelper.java:243)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.EnsureActivitiesVisibleHelper.process(EnsureActivitiesVisibleHelper.java:155)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.TaskFragment.updateActivityVisibilities(TaskFragment.java:1118)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.Task.lambda$ensureActivitiesVisible$19(Task.java:4918)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.Task$$ExternalSyntheticLambda24.accept(Unknown Source:10)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.Task.forAllLeafTasks(Task.java:3183)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.Task.forAllLeafTasks(Task.java:3171)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.Task.ensureActivitiesVisible(Task.java:4917)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.DisplayContent.lambda$ensureActivitiesVisible$44(DisplayContent.java:6143)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.DisplayContent$$ExternalSyntheticLambda38.accept(Unknown Source:10)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.Task.forAllRootTasks(Task.java:3195)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.WindowContainer.forAllRootTasks(WindowContainer.java:2033)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.WindowContainer.forAllRootTasks(WindowContainer.java:2033)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.WindowContainer.forAllRootTasks(WindowContainer.java:2033)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.WindowContainer.forAllRootTasks(WindowContainer.java:2033)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.WindowContainer.forAllRootTasks(WindowContainer.java:2033)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.WindowContainer.forAllRootTasks(WindowContainer.java:2033)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.WindowContainer.forAllRootTasks(WindowContainer.java:2026)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.DisplayContent.ensureActivitiesVisible(DisplayContent.java:6142)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.RootWindowContainer.ensureActivitiesVisible(RootWindowContainer.java:1873)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.RootWindowContainer.ensureActivitiesVisible(RootWindowContainer.java:1854)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.TaskFragment.completePause(TaskFragment.java:1802)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.ActivityRecord.activityPaused(ActivityRecord.java:6063)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.ActivityClientController.activityPaused(ActivityClientController.java:182)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at android.app.IActivityClientController$Stub.onTransact(IActivityClientController.java:574)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at com.android.server.wm.ActivityClientController.onTransact(ActivityClientController.java:125)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at android.os.Binder.execTransactInternal(Binder.java:1280)
03-28 14:39:03.327 23968 26756 E biubiubiu: 	at android.os.Binder.execTransact(Binder.java:1244)

根据这段堆栈很明显可以看初是 SourceActivity 执行的 activityPaused 流程,再根据之前的Events日志顺序,也知道是在 SourceActivity 执行完 pause 流程后触发的。

也就是说 activityPaused 流程再触发 TargetActivity 启动前,还执行了 addToStopping 流程,将 SourceActivity 放进来需要 stop 的列表中。

关于 【Activity启动流程-2】流程之前整理的调用链如下:

复制代码
ActivityClientController::activityPaused
    ActivityRecord::activityPaused
        TaskFragment::completePause
            RootWindowContainer::resumeFocusedTasksTopActivities       --分支1 ,再次执行 resumeFocusedTasksTopActivities
                RootWindowContainer::resumeFocusedTasksTopActivities
                    Task::resumeTopActivityUncheckedLocked
                        Task::resumeTopActivityInnerLocked
                            TaskFragment::resumeTopActivity
                                ActivityTaskSupervisor::startSpecificActivity                           --触发 startSpecificActivity 判断应用是否创建
            RootWindowContainer::ensureActivitiesVisible              --分支2
                RootWindowContainer::ensureActivitiesVisible
                    DisplayContent::ensureActivitiesVisible 
                        WindowContainer::forAllRootTasks  --忽略固定逻辑
                            Task::ensureActivitiesVisible
                                Task::forAllLeafTasks --忽略固定逻辑
                                    TaskFragment::updateActivityVisibilities
                                        EnsureActivitiesVisibleHelper::process
                                            EnsureActivitiesVisibleHelper::setActivityVisibilityState
                                                EnsureActivitiesVisibleHelper::makeVisibleAndRestartIfNeeded
                                                    ActivityTaskSupervisor::startSpecificActivity       --触发 startSpecificActivity 判断应用是否创建

这2个分支在【Activity启动流程】都分析过了,但是现在关注的是生命周期相关, 分之一和生命周期相关的流程已经分析过了,现在需要看看分支2和生命周期相关的逻辑。

复制代码
# TaskFragment

    void completePause(boolean resumeNext, ActivityRecord resuming) {

        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "completePause");
        // 拿到之前的Activity,也就是需要 pause的
        ActivityRecord prev = mPausingActivity;
        ProtoLog.v(WM_DEBUG_STATES, "Complete pause: %s", prev);
        if (prev != null) {
            ......
            // 设置窗口状态为PAUSED
            prev.setState(PAUSED, "completePausedLocked");
            if (prev.finishing) {
                ...... 如果已经finish,上面还在设置 pause,那正常应该是还没finish
            } else if (prev.hasProcess()) {
                // 打印状态日志
                ProtoLog.v(WM_DEBUG_STATES, "Enqueue pending stop if needed: %s "
                        + "wasStopping=%b visibleRequested=%b",  prev,  wasStopping,prev.mVisibleRequested);
            }else {
                ......
            }
            if (resumeNext) {
                ......
                // 重点* 第1分支
                Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "resumeFocusedTasksTopActivities");
                mRootWindowContainer.resumeFocusedTasksTopActivities(topRootTask, prev,null /* targetOptions */);
                Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
                ......
            }
            ......
            // 重点* 第2分支
            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "ensureActivitiesVisible");
            mRootWindowContainer.ensureActivitiesVisible(resuming, 0, !PRESERVE_WINDOWS);
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
            ......
        }
        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
    }

我在代码上加了几个 Trace 稍后再看,当前分析 onStop 流程所以只看第2分支触发的 ensureActivitiesVisible 流程,这个流程就是界面上有啥风吹草动,SystemService 端需要确保手机屏幕上Activity正确的显示。

根据上面的堆栈和整理出的调用链 RootWindowContainer::ensureActivitiesVisible 最终会执行到 EnsureActivitiesVisibleHelper::process 来处理当前 Task 下 Activity 的可见性。

EnsureActivitiesVisibleHelper的相关处理后面单独放一个章节详细解释,是ensureActivitiesVisible 流程非常重要的一环,目前可以自行了解或以黑盒概念理解

直接看 EnsureActivitiesVisibleHelper::setActivityVisibilityState 对 SourceActivity 的 stop 逻辑是如何处理的。

复制代码
# EnsureActivitiesVisibleHelper

    // 当前Task栈顶是否有Activity
    private boolean mAboveTop;

    // 设置Activity可见性
    private void setActivityVisibilityState(ActivityRecord r, ActivityRecord starting,
            final boolean resumeTopActivity) {
        ......

        // SourceActivity 所在的Task 被遮挡了,所以mBehindFullyOccludedContainer为true
        r.updateVisibilityIgnoringKeyguard(mBehindFullyOccludedContainer);

        // 自然是返回不可见
        final boolean reallyVisible = r.shouldBeVisibleUnchecked();
        ......
        
        if (reallyVisible) {
            // 忽略可见处理
        } else {
            if (DEBUG_VISIBILITY) {
                Slog.v(TAG_VISIBILITY, "Make invisible? " + r
                        + " finishing=" + r.finishing + " state=" + r.getState()
                        + " containerShouldBeVisible=" + mContainerShouldBeVisible
                        + " behindFullyOccludedContainer=" + mBehindFullyOccludedContainer
                        + " mLaunchTaskBehind=" + r.mLaunchTaskBehind);
            }
            // 不可见的处理 --使Activity不可见
            r.makeInvisible();
        }
        ......// launcher处理
    }

所以执行 ActivityRecord::makeInvisible 方法开始设置 SourceActivity 不可见。

2 设置Activity不可见 -- ActivityRecord::makeInvisible

makeInvisible 方法触发的调用链:

复制代码
ActivityRecord::makeInvisible
    ActivityRecord::setVisibility  -- setVisibility通用流程
        ActivityRecord::setVisibility
            ActivityRecord::setVisibleRequested
    ActivityRecord::addToStopping
        ActivityTaskSupervisor.mStoppingActivities::add --添加当前Activity到集合
        ActivityTaskSupervisor::scheduleIdle  -- 发送IDLE_NOW_MSG

        --------------处理消息-------------------
        ActivityTaskSupervisor$ActivityTaskSupervisorHandler::handleMessage
            ActivityTaskSupervisor$ActivityTaskSupervisorHandler::handleMessageInner
                ActivityTaskSupervisor$ActivityTaskSupervisorHandler::activityIdleFromMessage
                    ActivityTaskSupervisor::activityIdleInternal
                        ActivityTaskSupervisor::processStoppingAndFinishingActivities -- 热启动第一次执行到这时因条件不满足不会执行后续逻辑

看一下代码执行流程。

复制代码
# ActivityRecord

    void makeInvisible() {
        // mVisibleRequested 为false表示当前 Activity 已经在处理可见性逻辑了,不需要执行后面的逻辑, 
        if (!mVisibleRequested) {
            if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Already invisible: " + this);
            return;
        }

        // Now for any activities that aren't visible to the user, make sure they no longer are
        // keeping the screen frozen.
        // 对于不可见的Activity,需要开始真正的处理了
        if (DEBUG_VISIBILITY) {
            Slog.v(TAG_VISIBILITY, "Making invisible: " + this + ", state=" + getState());
        }
        try {
            final boolean canEnterPictureInPicture = checkEnterPictureInPictureState(
                    "makeInvisible", true /* beforeStopping */);
            // Defer telling the client it is hidden if it can enter Pip and isn't current paused,
            // stopped or stopping. This gives it a chance to enter Pip in onPause().
            // 画中画相关
            final boolean deferHidingClient = canEnterPictureInPicture
                    && !isState(STARTED, STOPPING, STOPPED, PAUSED);
            setDeferHidingClient(deferHidingClient);
            // 重点* 1. 设置为不可见 ,会将 mVisibleRequested 设置为false
            setVisibility(false);
            switch (getState()) {
                case STOPPING:
                case STOPPED:
                    // Reset the flag indicating that an app can enter picture-in-picture once the
                    // activity is hidden
                    supportsEnterPipOnTaskSwitch = false;
                    break;
                case RESUMED:
                case INITIALIZING:
                case PAUSING:
                case PAUSED:
                case STARTED:
                    // 重点* 2. 加入到Stop列表
                    addToStopping(true /* scheduleIdle */,
                            canEnterPictureInPicture /* idleDelayed */, "makeInvisible");
                    break;

                default:
                    break;
            }
        } catch (Exception e) {
            // Just skip on any failure; we'll make it visible when it next restarts.
            Slog.w(TAG, "Exception thrown making hidden: " + intent.getComponent(), e);
        }
    }
    1. 调用 setVisibility 方法设置为不可见
    1. 根据 state 做了一些处理,STOPPING 和 STOPPED 的情况下就设置了一个画中画的标志位,其他的几个状态会执行 addToStopping

方法前面的 mVisibleRequested 唯一赋值的地方在 ActivityRecord::setVisibleRequested 方法中,值为可见性,所以这个变量表示: 当前Activity被设置的可见性的值。

makeInvisible 方法是要将 Activity 设置为不可见,所以方法开始的时候如果 mVisibleRequested 是 false, 说明已经在做这件事了, 就不需要执行后面的逻辑了。

然后中间有一段画中画的逻辑处理,这段当前不需要关注。

再下面就是getState() 的返回值处理,当前执行到这里的是 SourceActivity 的 activityPaused 流程,所以这里的 getState() 返回的是 PAUSED ,这个可以通过上面的log确认。

2.1 setVisibility 方法

看一眼 setVisibility方法主要做了什么

复制代码
# ActivityRecord

    void setVisibility(boolean visible, boolean deferHidingClient) {
        ......
        ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
                "setAppVisibility(%s, visible=%b): %s visible=%b mVisibleRequested=%b Callers=%s",
                token, visible, appTransition, isVisible(), mVisibleRequested,
                Debug.getCallers(6));
        ......
        // 处理 DisplayContent 下的2个集合
        displayContent.mOpeningApps.remove(this);
        displayContent.mClosingApps.remove(this);
        ......
        // 1. 给 mVisibleRequested 赋值
        setVisibleRequested(visible);
        ......
            // 2. 处理 DisplayContent 下的2个集合
            if (visible) {
                displayContent.mOpeningApps.add(this);
                mEnteringAnimation = true;
            } else if (mVisible) {
                displayContent.mClosingApps.add(this);
                mEnteringAnimation = false;
            }
        ......
        // 3. 提交可见性更新
        commitVisibility(visible, true /* performLayout */);
        updateReportedVisibilityLocked();
    }
    1. 执行 setVisibleRequested 方法,内部会对 mVisibleRequested 变量赋值
    1. 处理 DisplayContent类维护的2个列表, 分别对应打开和关闭的应用(这个很重要)
    1. 执行 commitVisibility 方法,这里会最终可见性

继续看主流程 addToStopping 方法。

addToStopping 流程非常重要

3. ActivityRecord::addToStopping 方法

复制代码
# ActivityRecord

    final ActivityTaskSupervisor mTaskSupervisor;

    void addToStopping(boolean scheduleIdle, boolean idleDelayed, String reason) {
        if (!mTaskSupervisor.mStoppingActivities.contains(this)) {
            // 打印 event日志
            EventLogTags.writeWmAddToStopping(mUserId, System.identityHashCode(this),
                    shortComponentName, reason);
            // 重点* 1. 唯一将Activity添加到 mStoppingActivities 集合中的代码
            mTaskSupervisor.mStoppingActivities.add(this);
        }

        final Task rootTask = getRootTask();
        ......
        if (scheduleIdle || forceIdle) {
            // 打印Proto日志
            ProtoLog.v(WM_DEBUG_STATES,
                    "Scheduling idle now: forceIdle=%b immediate=%b", forceIdle, !idleDelayed);

            if (!idleDelayed) {
                // 重点* 2. 一般都是立即执行,所以是走这(可见根据上面log的immediate值确认)
                mTaskSupervisor.scheduleIdle();
            } ......
        } ......
    }

这个方法做了2件事

    1. 将当前这个Activity 添加到 ActivityTaskSupervisor 下的 mStoppingActivities 集合
    1. 执行 ActivityTaskSupervisor::scheduleIdle 内部会发送 "IDLE_NOW_MSG" 消息,进而触发后续 stop 逻辑

这个方法正常是执行 scheduleIdle 逻辑的, 另外有 Events 和Proto 2个日志的打印,如果发现有问题可以仔细看看相关变量的打印。

ActivityTaskSupervisor::scheduleIdle 方法如下:

复制代码
# ActivityTaskSupervisor

    final void scheduleIdle() {
        if (!mHandler.hasMessages(IDLE_NOW_MSG)) {
            // 发送消息,打堆栈
            if (DEBUG_IDLE) Slog.d(TAG_IDLE, "scheduleIdle: Callers=" + Debug.getCallers(4));
            mHandler.sendEmptyMessage(IDLE_NOW_MSG);
        }
    }

这个方法主要就是发送了"IDLE_NOW_MSG" 消息,并且打印了debug的堆栈。

冷启动的话 ActivityTaskSupervisor::scheduleIdle 的调用链就上面分析的一个,但是应用内启动Activity 根据log打印的堆栈发现会有3个调用链,这边也整理一下3个调用链,感兴趣的可以自己跟一下

复制代码
Callers=com.android.server.wm.ActivityRecord.addToStopping:6239
 com.android.server.wm.ActivityRecord.makeInvisible:5810
  com.android.server.wm.EnsureActivitiesVisibleHelper.setActivityVisibilityState:240
   com.android.server.wm.EnsureActivitiesVisibleHelper.process:153 

Callers=com.android.server.wm.ActivityTaskSupervisor.scheduleProcessStoppingAndFinishingActivitiesIfNeeded:2175
 com.android.server.wm.ActivityRecord.onAnimationFinished:7473
  com.android.server.wm.WindowContainer$$ExternalSyntheticLambda4.onAnimationFinished:2
   com.android.server.wm.SurfaceAnimator.lambda$getFinishedCallback$0$com-android-server-wm-SurfaceAnimator:133 

Callers=com.android.server.wm.ActivityTaskSupervisor.scheduleProcessStoppingAndFinishingActivitiesIfNeeded:2175
 com.android.server.wm.ActivityRecord.onWindowsVisible:6532
  com.android.server.wm.ActivityRecord.updateReportedVisibilityLocked:6633
   com.android.server.wm.WindowManagerService$4.onAppTransitionFinishedLocked:1154 

4 "IDLE_NOW_MSG"的处理 ActivityTaskSupervisor -- activityIdleFromMessage

消息的执行也在 ActivityTaskSupervisor 类。

复制代码
# ActivityTaskSupervisor
    private final class ActivityTaskSupervisorHandler extends Handler {
                @Override
        public void handleMessage(Message msg) {
            synchronized (mService.mGlobalLock) {
                // 处理消息
                if (handleMessageInner(msg)) {
                    return;
                }
            }
            ......
        }

        private boolean handleMessageInner(Message msg) {
            ......
            case IDLE_NOW_MSG: {
                if (DEBUG_IDLE) Slog.d(TAG_IDLE, "handleMessage: IDLE_NOW_MSG: r=" + msg.obj);
                // 打印
                activityIdleFromMessage((ActivityRecord) msg.obj, false /* fromTimeout */);
            } break;
            ......
        }
    }

处理消息的时候也有log打印,"msg.obj" 为null。

继续看处理的代码

复制代码
# ActivityTaskSupervisor

        private void activityIdleFromMessage(ActivityRecord idleActivity, boolean fromTimeout) {
            activityIdleInternal(idleActivity, fromTimeout,
                    fromTimeout /* processPausingActivities */, null /* config */);
        }
        void activityIdleInternal(ActivityRecord r, boolean fromTimeout,
            boolean processPausingActivities, Configuration config) {
            // 重点* 1 log
            if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + r);
            // 重点* 2. ActivityRecord 不为null才执行内部逻辑
            if (r != null) {
                // 重点* 3. log
                if (DEBUG_IDLE) Slog.d(TAG_IDLE, "activityIdleInternal: Callers="
                        + Debug.getCallers(4));
                ......
            }
            ......
            // Atomically retrieve all of the other things to do. 原子检索所有其他要做的事情
            // 重点* 4. 看方法名是处理 停止和finish的Activity辑在这里
            processStoppingAndFinishingActivities(r, processPausingActivities, "idle");
            if (DEBUG_IDLE) {
                // 重点* 5. log 
                Slogf.i(TAG, "activityIdleInternal(): r=%s, mStartingUsers=%s", r, mStartingUsers);
            }
            ......
        }

这里有5个重点,其中1,3,5都是log,很少会将log标记为重点,当前这么做是因为这个方法会执行两次,需要通过这3个log来区分

现在是分析第一次执行,根据前面的分析参数 r 是null,所以执行 processStoppingAndFinishingActivities 方法。

log中搜索"Activity idle: "可以有以下2次打印

复制代码
Line 5664: 04-01 20:50:30.411  8585  8751 V ActivityTaskManager: Activity idle: null
Line 19079: 04-01 20:50:31.171  8585  9527 V ActivityTaskManager: Activity idle: ActivityRecord{95d53d7 u0 com.google.android.dialer/.extensions.GoogleDialtactsActivity} t26}

2次打印的行数和时间有很大的差距,说明不是一个时机执行的,当前分析的是第一次执行,是由 SourceActivity 执行 activityPaused 的时候会触发 addToStopping 流程。这一次参数 r 为null。

第二次打印的 r 为 TargetActivity 具体执行流程下面会分析。

4.1 processStoppingAndFinishingActivities 逻辑(其实啥也没干)

复制代码
# ActivityTaskSupervisor

    /**
     * Processes the activities to be stopped or destroyed. This should be called when the resumed
     * 处理要停止或销毁的Activity。这应该在resumed时调用
     * activities are idle or drawn.
     */
    private void processStoppingAndFinishingActivities(ActivityRecord launchedActivity,
            boolean processPausingActivities, String reason) {
                // 准备要执行 Stop 的Activity 集合 
                ArrayList<ActivityRecord> readyToStopActivities = null;
                // 重点 * 1. 遍历mStoppingActivities
                for (int i = mStoppingActivities.size() - 1; i >= 0; --i) {
                    // 获取到ActivityRecord (当前分析场景就1个)
                    final ActivityRecord s = mStoppingActivities.get(i);
                    final boolean animating = s.isAnimating(TRANSITION | PARENTS,
                            ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_RECENTS)
                            || s.inTransition();
                    // 日志
                    ProtoLog.v(WM_DEBUG_STATES, "Stopping %s: nowVisible=%b animating=%b "
                            + "finishing=%s", s, s.nowVisible, animating, s.finishing);
                    // 条件满足才执行
                    if (!animating || mService.mShuttingDown) {
                        ......
                        // 打印 准备stop的log
                        ProtoLog.v(WM_DEBUG_STATES, "Ready to stop: %s", s);
                        if (readyToStopActivities == null) {
                            readyToStopActivities = new ArrayList<>();
                        }
                        // 重点 * 2. 添加进集合
                        readyToStopActivities.add(s);
                        // 从集合中移除
                        mStoppingActivities.remove(i);
                    }
                }
                // 重点 * 3. 遍历readyToStopActivities
                final int numReadyStops = readyToStopActivities == null ? 0 : readyToStopActivities.size();
                for (int i = 0; i < numReadyStops; i++) {
                    final ActivityRecord r = readyToStopActivities.get(i);
                    // 检查该ActivityRecord对象是否在历史记录中。  
                    if (r.isInHistory()) {
                        // 如果该ActivityRecord对象正在结束(可能是用户或系统触发的结束操作)。
                        if (r.finishing) {
                            // TODO(b/137329632): Wait for idle of the right activity, not just any.
                            r.destroyIfPossible(reason);
                        } else {
                            // 重点* 4. 如果ActivityRecord对象不在结束状态,则尝试停止它
                            r.stopIfPossible();
                        }
                    }
                }
                ......
            }

这个方法的逻辑还是很重要的,不过当前这一次执行进来,因为条件不满足,其实相当于啥也没干。

    1. 这里遍历的集合,在 ActivityRecord::addToStopping 方法中看到对其赋值
    1. 满足条件的会被添加进 readyToStopActivities 集合, 进入if的条件刚好log也有打印

    V WindowManager: Stopping ActivityRecord{f40797d u0 com.android.launcher3/.uioverrides.QuickstepLauncher} t20}: nowVisible=true animating=true finishing=false mShuttingDown=false

animating 和 mShuttingDown 都不满足条件,所以不会进入。自如也不会有下面的"Ready to stop:"的打印,因为这里没进入执行 readyToStopActivities 集合没有元素,所以重点3也不会执行。

但是第二次执行 ActivityTaskSupervisor::activityIdleInternal 方法的时候的日志会有后续的打印,也就是说会执行到 ActivityRecord::stopIfPossible ,第二次的log如下

复制代码
04-01 20:50:31.182  8585  9527 V WindowManager: Stopping ActivityRecord{f40797d u0 com.android.launcher3/.uioverrides.QuickstepLauncher} t20}: nowVisible=false animating=false finishing=false  mShuttingDown=false
04-01 20:50:31.182  8585  9527 V WindowManager: Ready to stop: ActivityRecord{f40797d u0 com.android.launcher3/.uioverrides.QuickstepLauncher} t20}

第二次相关的逻辑有个印象几个,后面会再分析

5 小结

在正确冷启动流程的开始 SourceActivity 执行 activityPaused 的时候会触发 addToStopping 流程,这个流程会执行到 ActivityTaskSupervisor:: processStoppingAndFinishingActivities 方法,但是由于条件不满足,在这个方法中不会有什么实质性的处理。(后续还有会流程第二次触发该方法)

因此 addToStopping 流程最重要的事就是将 SourceActivity 添加到了 ActivityTaskSupervisor 类下的 mStoppingActivities 集合中。等后面条件满足再触发 ActivityTaskSupervisor:: processStoppingAndFinishingActivities 方法时就会执行 ActivityRecord::stopIfPossible 流程了。

"wm_add_to_stopping" 日志的线索跟到这里就结束了,后面的流程还有2个线索

    1. 第二个和 stop 有关的events 日志为 "wm_stop_activity" 并且已知在 "wm_on_resume_called"后打印
    1. ActivityTaskSupervisor::activityIdleInternal 的第二次执行,并且第二次执行到 ActivityTaskSupervisor::processStoppingAndFinishingActivities 方法会触发后续逻辑创建 Stop 的事务。
相关推荐
Digitally39 分钟前
如何将文件从 iPhone 传输到 Android(新指南)
android·ios·iphone
whysqwhw2 小时前
OkHttp深度架构缺陷分析与演进规划
android
用户7093722538512 小时前
Android14 SystemUI NotificationShadeWindowView 加载显示过程
android
木叶丸2 小时前
跨平台方案该如何选择?
android·前端·ios
顾林海3 小时前
Android ClassLoader加载机制详解
android·面试·源码
用户2018792831673 小时前
🎨 童话:Android画布王国的奇妙冒险
android
whysqwhw3 小时前
OkHttp框架的全面深入架构分析
android
你过来啊你3 小时前
Android App冷启动流程详解
android
泓博4 小时前
KMP(Kotlin Multiplatform)改造(Android/iOS)老项目
android·ios·kotlin
移动开发者1号4 小时前
使用Baseline Profile提升Android应用启动速度的终极指南
android·kotlin