Android V app 冷启动 (1) Activity生命周期

812 阅读23分钟

分析案例

竖屏下,从 Launcher 启动一个横屏 app。

app 很简单,就是从 Android Studio 创建一个 project,然后在 AndroidManifest.xml 中,把 MainActivity 的方向声明为横屏,如下

<activity
    android:name=".MainActivity"
    android:screenOrientation="landscape">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

第一阶段启动

第一阶段启动,从 Launcher 点击 app 图标开始

// QuickStepLauncher.java

@Override
public View.OnClickListener getItemOnClickListener() {
    return this::onItemClicked;
}

protected void onItemClicked(View view) {
    if (!mSplitToWorkspaceController.handleSecondAppSelectionForSplit(view)) {
        // 调用到 ItemClickHandler#onClick()
        QuickstepLauncher.super.getItemOnClickListener().onClick(view);
    }
}
// ItemClickHandler.java
private static void onClick(View v) {
    // ...
    
    // 通过 View 的 Context, 强转 Launcher
    Launcher launcher = Launcher.getLauncher(v.getContext());
    if (!launcher.getWorkspace().isFinishedSwitchingState()) return;

    Object tag = v.getTag();
    if (tag instanceof WorkspaceItemInfo) { // 点击 workspace 区域图标
        onClickAppShortcut(v, (WorkspaceItemInfo) tag, launcher);
    } // ...
}

public static void onClickAppShortcut(View v, WorkspaceItemInfo shortcut, Launcher launcher) {
    // ...

    startAppShortcutOrInfoActivity(v, shortcut, launcher);
}

private static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher) {

    Intent intent;
    if (item instanceof ItemInfoWithIcon
            && (((ItemInfoWithIcon) item).runtimeStatusFlags
            & ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE) != 0) {

    } else {
        // WorkspaceItemInfo 获取启动 app 的 Intent
        intent = item.getIntent();
    }
    
    // ...
    
    if (v != null && launcher.supportsAdaptiveIconAnimation(v)
            && !item.shouldUseBackgroundAnimation()) {
        // 预加载 view 的 icon,保存到 FloatingIconView#sIconLoadResult
        // Preload the icon to reduce latency b/w swapping the floating view with the original.
        FloatingIconView.fetchIcon(launcher, v, item, true /* isOpening */);
    }
    
    // 由 Launcher 执行启动
    // 子类 QuickStepLauncher 有复写,但是最终由基类 ActivityContext 实现核心逻辑
    launcher.startActivitySafely(v, intent, item);
}
// ActivityContext.java

default RunnableList startActivitySafely(
        View v, Intent intent, @Nullable ItemInfo item) {
    
    // 强转 Context
    Context context = (Context) this;
    
    // ..
    
    // 重点:创建启动 Activity 时附带的参数
    // Launcher 的子类 QuickstepLauncher 复写了 getActivityLaunchOptions()
    ActivityOptionsWrapper options = v != null ? getActivityLaunchOptions(v, item)
            : makeDefaultActivityOptions(item != null && item.animationType == DEFAULT_NO_ICON
                    ? SPLASH_SCREEN_STYLE_SOLID_COLOR : -1 /* SPLASH_SCREEN_STYLE_UNDEFINED */);
    UserHandle user = item == null ? null : item.user;
    Bundle optsBundle = options.toBundle();
    
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    if (v != null) {
        // intent 保存了 view bounds
        intent.setSourceBounds(Utilities.getViewBounds(v));
    }
    
    
    try {
    
        // item.itemt.Type 为 ITEM_TYPE_APPLICATION
        boolean isShortcut = (item instanceof WorkspaceItemInfo)
                && (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT
                || item.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT)
                && !((WorkspaceItemInfo) item).isPromise();
        if (isShortcut) {
            
        } else if (user == null || user.equals(Process.myUserHandle())) {
            // 由 Context 启动 activity
            context.startActivity(intent, optsBundle);
        } else {
            
        }
        
        // ...
        
        return options.onEndCallback;
    } catch (NullPointerException | ActivityNotFoundException | SecurityException e) {
        // ...
    }
    return null;
}

从 Launcher 启动 app 的原理,就是通过 Context#startActivity() 启动指定 Activity。

很多人可能关心传入的 Bundle 参数到底包含哪些数据,这里仅仅展示下,不做分析,因为目前还用不到。

// QuickStepLauncher.java

public ActivityOptionsWrapper getActivityLaunchOptions(View v, @Nullable ItemInfo item) {
    // 重点:创建 ActivityOptionsWrapper
    ActivityOptionsWrapper activityOptions =
            mAppTransitionManager.hasControlRemoteAppTransitionPermission()
                    ? mAppTransitionManager.getActivityLaunchOptions(v)
                    : super.getActivityLaunchOptions(v, item);
    
    if (mLastTouchUpTime > 0) {
        activityOptions.options.setSourceInfo(ActivityOptions.SourceInfo.TYPE_LAUNCHER,
                mLastTouchUpTime);
    
    
    if (item != null && (item.animationType == DEFAULT_NO_ICON
            || item.animationType == VIEW_BACKGROUND)) {

    } else {
        // 启动窗口使用 icon
        activityOptions.options.setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
    }
    
    // 保存 display id
    activityOptions.options.setLaunchDisplayId(
            (v != null && v.getDisplay() != null) ? v.getDisplay().getDisplayId()
                    : Display.DEFAULT_DISPLAY);
                    
    // 保存 cookie
    addLaunchCookie(item, activityOptions.options);
    return activityOptions;
}
// QuickstepTransitionManager.java

public ActivityOptionsWrapper getActivityLaunchOptions(View v) {
    boolean fromRecents = isLaunchingFromRecents(v, null /* targets */);
    RunnableList onEndCallback = new RunnableList();

    // Handle the case where an already visible task is launched which results in no transition
    TaskRestartedDuringLaunchListener restartedListener =
            new TaskRestartedDuringLaunchListener();
    restartedListener.register(onEndCallback::executeAllAndDestroy);
    onEndCallback.add(restartedListener::unregister);

    // 远程动画的真正执行者
    mAppLaunchRunner = new AppLaunchAnimationRunner(v, onEndCallback);
    ItemInfo tag = (ItemInfo) v.getTag();
    if (tag != null && tag.shouldUseBackgroundAnimation()) {
       
    }
    
    // RemoteAnimationRunnerCompat 是为了兼容新旧两种动画而设计的类
    // 它把远程动画交给 mAppLaunchRunner 去执行
    RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(
            mHandler, mAppLaunchRunner, true /* startAtFrontOfQueue */);

    // Note that this duration is a guess as we do not know if the animation will be a
    // recents launch or not for sure until we know the opening app targets.
    long duration = fromRecents
            ? RECENTS_LAUNCH_DURATION
            : APP_LAUNCH_DURATION;

    long statusBarTransitionDelay = duration - STATUS_BAR_TRANSITION_DURATION
            - STATUS_BAR_TRANSITION_PRE_DELAY;
    ActivityOptions options = ActivityOptions.makeRemoteAnimation(
            new RemoteAnimationAdapter(runner, duration, statusBarTransitionDelay),
            new RemoteTransition(runner.toRemoteTransition(),
                    mLauncher.getIApplicationThread(), "QuickstepLaunch"));
    return new ActivityOptionsWrapper(options, onEndCallback);
}

ATMS

// ActivityTaskManagerService.java

    public final int startActivity(IApplicationThread caller, String callingPackage,
            String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
            Bundle bOptions) {
        // 增加了最后一个参数 userId
        return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }
    
    public int startActivityAsUser(IApplicationThread caller, String callingPackage,
            String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
            Bundle bOptions, int userId) {
        // 增加了最后一个参数 validateIncomingUser,值为 true
        return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
                true /*validateIncomingUser*/);
    }
    
    private int startActivityAsUser(IApplicationThread caller, String callingPackage,
            @Nullable String callingFeatureId, Intent intent, String resolvedType,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {

        // app 端传过来的参数是 Bundle 类型,并且是序列化的,因此无法打印
        // 在服务端,需要把它转换为 ActivityOptions 才能打印 app 端传入的数据
        // 这里更进一步,把 ActivityOptions 包装成 SafeActivityOptions,为的是检测调用方的权限
        final SafeActivityOptions opts = SafeActivityOptions.fromBundle(bOptions);

        // ...
        
        // 把启动参数包装成 ActivityStart#mRequest ,并通过 ActivityStarter 来启动 activity
        return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
                .setCaller(caller) // 指向 launcher
                .setCallingPackage(callingPackage) // com.android.launcher
                .setCallingFeatureId(callingFeatureId) // null
                .setResolvedType(resolvedType) // 这是 mime type,目前是 null
                .setResultTo(resultTo) // 指向 launcher
                .setResultWho(resultWho) // null 
                // 注意,这个请求码是 -1,也就是说 launcher 不需要知道启动结果
                .setRequestCode(requestCode) 
                .setStartFlags(startFlags) // 0
                .setProfilerInfo(profilerInfo) // null
                .setActivityOptions(opts) // 这个是启动 Activity 传入的数据,不为 null
                .setUserId(userId)
                .execute();

    }    

ATMS 把启动 Activity 的参数保存到了 ActivityStart#mRequest,然后交给 ActivityStarter 继续执行启动 Activity 流程。

ActivityStarter

// ActivityStarter.java

    /**
     * Resolve necessary information according the request parameters provided earlier, and execute
     * the request which begin the journey of starting an activity.
     * @return The starter result.
     */
    int execute() {
        try {
            // ...
            
            // 1.解析 Activity 信息,并保存到 mRequest.activityInfo
            if (mRequest.activityInfo == null) {
                mRequest.resolveActivity(mSupervisor);
            }

            // ...

            int res;
            synchronized (mService.mGlobalLock) {
                // ...

                try {
                    // 2.执行activity启动请求
                    res = executeRequest(mRequest);
                } finally {
                    mRequest.logMessage.append(" result code=").append(res);
                    // 这里输出的就是著名的 START u0 的 log
                    Slog.i(TAG, mRequest.logMessage.toString());
                    mRequest.logMessage.setLength(0);
                }

                // ...

                return getExternalResult(res);
            }
        } finally {
            onExecutionComplete();
        }
    }

根据注释所说,这一步主要就是解析一些必要信息,然后执行请求。

executeRequest()

// ActivityStarter.java

/**
 * Executing activity start request and starts the journey of starting an activity. Here
 * begins with performing several preliminary checks. The normally activity launch flow will
 * go through {@link #startActivityUnchecked} to {@link #startActivityInner}.
 */
private int executeRequest(Request request) {

    // 省略启动前检查的代码

    // ...

    // 构造 START u0 的 log
    if (err == ActivityManager.START_SUCCESS) {
        request.logMessage.append("START u").append(userId).append(" {")
                .append(intent.toShortString(true, true, true, false))
                .append("} with ").append(launchModeToString(launchMode))
                .append(" from uid ").append(callingUid);
        if (callingUid != realCallingUid
                && realCallingUid != Request.DEFAULT_REAL_CALLING_UID) {
            request.logMessage.append(" (realCallingUid=").append(realCallingUid).append(")");
        }
    }   

    // ...


    // 创建 ActivityRecord
    final ActivityRecord r = new ActivityRecord.Builder(mService)
            .setCaller(callerApp) // 指向 launcher 进程
            .setLaunchedFromPid(callingPid)
            .setLaunchedFromUid(callingUid)
            .setLaunchedFromPackage(callingPackage) // com.android.launcher
            .setLaunchedFromFeature(callingFeatureId) // null
            .setIntent(intent)
            .setResolvedType(resolvedType) // null
            .setActivityInfo(aInfo)
            .setConfiguration(mService.getGlobalConfiguration()) // 使用 global config
            .setResultTo(resultRecord) // null
            .setResultWho(resultWho) // null
            .setRequestCode(requestCode) // -1
            .setComponentSpecified(request.componentSpecified) // false
            .setRootVoiceInteraction(voiceSession != null) // false
            .setActivityOptions(checkedOptions) // 这个就是启动 Activity 传入的 Bundle 参数
            .setSourceRecord(sourceRecord) // launcher
            .build();

    // mLastStartActivityRecord 保存最近一次启动的activity
    mLastStartActivityRecord = r;

    // ...

    // 以 ActivityRecord 为参数,继续执行启动
    mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
            request.voiceInteractor, startFlags, checkedOptions,
            inTask, inTaskFragment, balCode, intentGrants, realCallingUid);

    // ...

    return mLastStartActivityResult;
}

如注释所说,这一步做了启动前的检查,然后创建 ActivityRecord,最后利用 ActivityRecord 来执行下一步的启动。

在这一步中,我还展示了 START u0 的 log 是如何构造的,这里展示下实际的 log

ActivityTaskManager: START u0 
{act=com.android.intent.MAIN, 
cat=[com.android.category.LAUNCHER], 
flg=0x10200000, cmp=com.example.helloworld/.MainActivity ....} ... 
result code = 0

大括号内是 Intent 的信息,flg 的值中包含 FLAG_ACTIVITY_NEW_TASK,所以从桌面冷启动 App,是需要新建一个 Task 的。

startActivityUnchecked()

// ActivityStarter.java

/**
 * Start an activity while most of preliminary checks has been done and caller has been
 * confirmed that holds necessary permissions to do so.
 * Here also ensures that the starting activity is removed if the start wasn't successful.
 */
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        int startFlags, ActivityOptions options, Task inTask,
        TaskFragment inTaskFragment, @BalCode int balCode,
        NeededUriGrants intentGrants, int realCallingUid) {
    int result = START_CANCELED;
    final Task startedActivityRootTask;

    final TransitionController transitionController = r.mTransitionController;
    // 1.创建 OPEN transition,并使 transition 进入收集状态
    Transition newTransition = transitionController.isShellTransitionsEnabled()
            ? transitionController.createAndStartCollecting(TRANSIT_OPEN) : null;
    
    // 从 launcher 启动 app 时,会携带一个 RemoteTranstion 数据,与桌面的远程动画相关
    RemoteTransition remoteTransition = r.takeRemoteTransition();
    
    try {
        mService.deferWindowLayout();
        
        // 1.1 transition 收集正在启动的 ActivityRecord
        transitionController.collect(r);
        
        try {
        
            // 注意,这里有一个第一阶段的启动 trace
            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
            
            // 2. 继续启动 activity
            result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, options, inTask, inTaskFragment, balCode,
                    intentGrants, realCallingUid);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
            
            // 3.处理启动结果
            startedActivityRootTask = handleStartResult(r, options, result, newTransition,
                    remoteTransition);
        }
    } finally {
        mService.continueWindowLayout();
    }

    // 注意这段代码中关于 START_TASK_TO_FRONT 和  START_DELIVERED_TO_TOP 结果的处理,与PIP等功能有关
    postStartActivityProcessing(r, result, startedActivityRootTask);
    
    return result;
}

这一步主要做了三件事

  1. 创建一个 OPEN Transition ,并收集 ActivityRecord。
  2. 执行下一步启动。
  3. 处理启动结果。如果启动成功,OPEN transition 会收集 ActivityRecord 的存在性改变,还会向 WMShell 请求 OPEN transition。

注意,本文不分析 transition 动画,只分析 Activity 生命周期如何执行的。

startActivityInner()

// ActivityStarter.java

/**
 * Start an activity and determine if the activity should be adding to the top of an existing
 * task or delivered new intent to an existing activity. Also manipulating the activity task
 * onto requested or valid root-task/display.
 *
 * Note: This method should only be called from {@link #startActivityUnchecked}.
 */
int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        int startFlags, ActivityOptions options, Task inTask,
        TaskFragment inTaskFragment, @BalCode int balCode,
        NeededUriGrants intentGrants, int realCallingUid) {
    // 保存并解析一些初始状态,例如, mStartActivity 保存要启动的 Activity,mDoResume 解析为 true
    setInitialState(r, options, inTask, inTaskFragment, startFlags, sourceRecord,
            voiceSession, voiceInteractor, balCode, realCallingUid);
    
    // ...
    
    // app 冷启动,是需要新建 Task,所以这里是找不到可以直接使用的 Task
    final boolean includeLaunchedFromBubble =
            Flags.onlyReuseBubbledTaskWhenLaunchedFromBubble()
                    ? sourceActivityLaunchedFromBubble : true;
    final Task reusedTask = resolveReusableTask(includeLaunchedFromBubble);
    // ...
    final Task targetTask = reusedTask != null ? reusedTask : computeTargetTask();
    // true
    final boolean newTask = targetTask == null;
    // null
    mTargetTask = targetTask;
    // ...
    // null
    final ActivityRecord targetTaskTop = newTask
            ? null : targetTask.getTopNonFinishingActivity();
    if (targetTaskTop != null) {
        // ...
    } else {
        // 需要把 ActivityRecord 添加到 Task
        mAddingToTask = true;
    }
    
    // ...
    
    if (mTargetRootTask == null) {
        // 1. 创建 root task ,并且作为 top child 保存到 TaskDisplayArea 下
        mTargetRootTask = getOrCreateRootTask(mStartActivity, mLaunchFlags, targetTask,
                mOptions);
    }
    
    if (newTask) {
        // null
        final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
                ? mSourceRecord.getTask() : null;
        // 2. root task 作为 leaf task,把 ActivityRecord 作为 top child 保存
        setNewTask(taskToAffiliate);
    } else if (mAddingToTask) {
        // ...
    }
    
    // ...
    
    final Task startedTask = mStartActivity.getTask();
    if (newTask) {
        // 创建 task 的 event log : wm_create_task
        EventLogTags.writeWmCreateTask(mStartActivity.mUserId, startedTask.mTaskId,
                startedTask.getRootTaskId(), startedTask.getDisplayId());
    }
    
    // 启动 Activity 的 event log : wm_create_activity
    mStartActivity.logStartActivity(EventLogTags.WM_CREATE_ACTIVITY, startedTask);
    
    // ...
    
    // isTaskSwitch 为 true
    final boolean isTaskSwitch = startedTask != prevTopTask;
    // 3. 创建启动窗口
    mTargetRootTask.startActivityLocked(mStartActivity, topRootTask, newTask, isTaskSwitch,
            mOptions, sourceRecord);
    
    if (mDoResume) {
        final ActivityRecord topTaskActivity = startedTask.topRunningActivityLocked();
        if (!mTargetRootTask.isTopActivityFocusable()
                || (topTaskActivity != null && topTaskActivity.isTaskOverlay()
                && mStartActivity != topTaskActivity)) {
            // ...
        } else {
            // mTargetRootTask 目前已经是 top focused task
            if (!mAvoidMoveToFront && mTargetRootTask.isTopActivityFocusable()
                    && !mRootWindowContainer.isTopDisplayFocusedRootTask(mTargetRootTask)) {
                // ... 
            }
            // 4. ActivityRecord 的窗口层级已经构建成功,现在由 RWC 来执行下一步启动
            // mTransientLaunch 来自于 mOptions 的解析 KEY_TRANSIENT_LAUNCH,这里值为 false
            // 如果它为 true,那么表示不用等到暂停后台 Tasks 之后,就可以立即 start activity
            mRootWindowContainer.resumeFocusedTasksTopActivities(
                    mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);
        }
    }
    
    
    // ...
    return START_SUCCESS;
}

首先介绍下窗口层级树,如下

graph TD
RootWindowContainer --> DisplayContent
DisplayContent --> DislayArea1
DisplayContent --> DislayArea
DisplayContent --> DislayArea2
DislayArea --> TaskDisplayArea
TaskDisplayArea --> Task
Task --> ActivityRecord
ActivityRecord --> WindowState

其中,RootWindowContainer 是层级树的根,DisplayContent 代表一个屏幕,DisplayArea 管理 DisplayContent 下某些层级的区域,TaskDisplayArea 是用来管理 Task,Task 用来保存代表 Activity 的 ActivityRecord,ActivityRecord 保存代表窗口的 WindowState。

这一步主要就是为了构建窗口层级,过程如下

  1. 创建 root Task,并以 top child 保存到 TaskDisplayArea 下。什么是 root Task ? 它的 parent 不是 Task,那么它就是 root task。
  2. root Task 作为 leaf Task,把 target ActivityRecord 作为 top child 进行保存。什么是 leaf Task ? 其实 Task 下面也可以保存子 Task,子 Task 下面如果没有 Task,那么子 Task 就是 leaf Task。
  3. 创建启动窗口。就是 App 开发经常说的 splash screen。
  4. 窗口层级构建完成后,通过层级树的根 RootWindowContainer 来执行下一步的 Activity 启动。

经过这一步之后,窗口层级树如下

graph TD
RootWindowContainer --> DisplayContent
DisplayContent --> DislayArea1
DisplayContent --> DislayArea
DisplayContent --> DislayArea2
DislayArea --> TaskDisplayArea
TaskDisplayArea --> Task
Task --> ActivityRecord
ActivityRecord --> WindowState
TaskDisplayArea --> targetTask
targetTask --> taretActivityRecord

其中,targetTask 是新建的 Task,targetActivityRecord 就是要启动的 Activity。

RootWindowContainer

// RootWindowContainer.java

// targetRootTask 就是要启动 activity 的 root task
// target 就是要启动的 activity
// targetOptions 是 start activity 的参数
// deferPause 为 false
boolean resumeFocusedTasksTopActivities(
        Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions,
        boolean deferPause) {
    if (!mTaskSupervisor.readyToResume()) {
        return false;
    }
    boolean result = false;
    
    // targetRootTask 是作为 top child 保存在 TDA 下,因此它现在就是 top root task
    if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea()
            || getTopDisplayFocusedRootTask() == targetRootTask)) {
        // 由 toot task resume top activity
        result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions,
                deferPause);
    }

    // 处理 activity 启动失败的情况
    // 例如,从桌面启动 activity 失败,至少系统得再把桌面拉起来
    for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
        // ...
    }
    return result;
}

RootWindowContainer 交给 root task 来 resume top activity,这个 top activity 就是要启动的 Activity。

root Task#resumeTopActivityUncheckedLocked()

// Task.java


/**
 * Ensure that the top activity in the root task is resumed.
 *
 * @param prev The previously resumed activity, for when in the process
 * of pausing; can be null to call from elsewhere.
 * @param options Activity options.
 * @param deferPause When {@code true}, this will not pause back tasks.
 *
 */
// 参数 prev 此时就是要启动的 activity,但是从命名以及注释来看,它的意思耐人寻味
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options,
        boolean deferPause) {

    // ...

    boolean someActivityResumed = false;
    try {
        // Protect against recursion.
        mInResumeTopActivity = true;

        if (isLeafTask()) { // leaf Task
            if (isFocusableAndVisible()) { // top activity 可以获焦,并且 task 处于 top,需要可见
                // root task 作为 leaf Task 来 resume top activity
                someActivityResumed = resumeTopActivityInnerLocked(prev, options, deferPause);
            }
        } else {
            // ... 这里处理不是 leaf task 的情况,不外乎就是遍历 children,然后递归调用当前方法
        }

        // ...
    } finally {
        mInResumeTopActivity = false;
    }
    return someActivityResumed;
}

root task 交给 leaf task 来 resume top activity,对于本案例来说,root task 就是 leaf task。

leaf Task#resumeTopActivityInnerLocked()

// Task.java

// prev 是要启动的 activity
// options 是启动 activity 的参数
// deferPause 为 false
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options,
        boolean deferPause) {
    if (!mAtmService.isBooting() && !mAtmService.isBooted()) {
        // Not ready yet!
        return false;
    }
    
    //获取 Task 的 top-focusable-non-finishing-activty
    final ActivityRecord topActivity = topRunningActivity(true /* focusableOnly */);

    if (topActivity == null) {
        // ...
    }

    final boolean[] resumed = new boolean[1];

    final TaskFragment topFragment = topActivity.getTaskFragment();
    // 由 top activity 的 TaskFragment 来启动 top activity
    resumed[0] = topFragment.resumeTopActivity(prev, options, deferPause);
    
    // 看看其他 TaskFragment 是否能 resume top activity
    forAllLeafTaskFragments(f -> {
        // ...
    }, true);
    return resumed[0];
}

leaf task 交给 activity 的 TaskFragment 来 resume top activity。

Task 本身就是继承自 TaskFragment,对于本案例来说,leaf task 下是没有子 TaskFragment 的,因此 activity 的 TaskFragment 就是 leaf task ,也是 root task。

TaskFragment#resumeTopActivity()

// TaskFragment.java

// prev 就是要启动的 activity
// deferPause 为 false
final boolean resumeTopActivity(ActivityRecord prev, ActivityOptions options,
        boolean deferPause) {
    // 获取 top-focusable-non-finishing-activity,其实就是要启动的 activity
    ActivityRecord next = topRunningActivity(true /* focusableOnly */);
    
    // ...

    // 如果当前有 Actvity 正在暂停,那么什么也不做
    // If we are currently pausing an activity, then don't do anything until that is done.
    final boolean allPausedComplete = mRootWindowContainer.allPausedActivitiesComplete();
    if (!allPausedComplete) {
        ProtoLog.v(WM_DEBUG_STATES,
                "resumeTopActivity: Skip resume: some activity pausing.");
        return false;
    }

    final TaskDisplayArea taskDisplayArea = getDisplayArea();

    // Task 才刚刚创建,mResumedActivity 和 mLastPausedActivity 都为 null
    if (mResumedActivity == next && next.isState(RESUMED)
            && taskDisplayArea.allResumedActivitiesComplete()) {
        // ....
        return false;
    }
    if (mLastPausedActivity == next && shouldSleepOrShutDownActivities()) {
        // ...
        return false;
    }

    // ...

    // 1.暂停后台 Task
    // 此时 deferPause 为 false,表示不能推迟暂停后台 tasks
    // 只要有一个后台 Task 正在暂停,那么返回 true
    boolean pausing = !deferPause && taskDisplayArea.pauseBackTasks(next);

    if (mResumedActivity != null) {
        // ...
    }

    if (pausing) {
        ProtoLog.v(WM_DEBUG_STATES, "resumeTopActivity: Skip resume: need to"
                + " start pausing");
                
        if (next.attachedToProcess()) { // 此时还没有进程
            // ...
        } else if (!next.isProcessRunning()) {
            // Since the start-process is asynchronous, if we already know the process of next
            // activity isn't running, we can start the process earlier to save the time to wait
            // for the current activity to be paused.
            final boolean isTop = this == taskDisplayArea.getFocusedRootTask();
            // 2. 由于有后台 Task 正在暂停,因此不能立即 start activity,但是可以先拉起进程
            mAtmService.startProcessAsync(next, false /* knownToBeDead */, isTop,
                    isTop ? HostingRecord.HOSTING_TYPE_NEXT_TOP_ACTIVITY
                            : HostingRecord.HOSTING_TYPE_NEXT_ACTIVITY);
        }
        
        // 注意,这里就结束了
        return true;
    } else if (mResumedActivity == next && next.isState(RESUMED)
            && taskDisplayArea.allResumedActivitiesComplete()) {
        // ...
    }
    
    // ...
}

本案例分析的是 app 冷启动,TaskFragment 先暂停了后台 Tasks,然后拉起 app 进程。

暂停后台 Tasks

所有的 Task 都由 TaskDisplayArea 管理,因此暂停后台 Tasks 的任务,当然是交给 TaskDisplayArea 来处理

对于本文分析的案例,此时需要暂停的后台 Tasks 只有 Launcher Task。

// TaskDisplayArea.java

boolean pauseBackTasks(ActivityRecord resuming) {
    final int[] someActivityPaused = {0};
    
    // 由 leaf task 来暂停 activity
    forAllLeafTasks(leafTask -> {
        if (leafTask.pauseActivityIfNeeded(resuming, "pauseBackTasks")) {
            someActivityPaused[0]++;
        }
    }, true /* traverseTopToBottom */);
    
    return someActivityPaused[0] > 0;
}
// Task.java

boolean pauseActivityIfNeeded(@Nullable ActivityRecord resuming, @NonNull String reason) {
    if (!isLeafTask()) {
        return false;
    }

    final int[] someActivityPaused = {0};

    if (!isLeafTaskFragment()) {
        
    }

    forAllLeafTaskFragments((taskFrag) -> {
        // 获取 resumed activity
        final ActivityRecord resumedActivity = taskFrag.getResumedActivity();
        
        // 暂停后台 Task 的两个条件
        if (resumedActivity != null && !taskFrag.canBeResumed(resuming)) {
        
            // 由 TaskFragment 来处理暂停
            if (taskFrag.startPausing(false /* uiSleeping*/, resuming, reason)) {
                someActivityPaused[0]++;
            }
        }
    }, true /* traverseTopToBottom */);

    return someActivityPaused[0] > 0;
}

TaskDisplayArea 把任务交给所有的 leaf task,leaf task 把任务交给所有的 leaf TaskFragment。

只有 TaskFragment 有 resumed activity,并且要启动的 activity 不属于这个 TaskFragment,这样就可以执行暂停 Task 的任务。

// TaskFragment.java

final boolean startPausing(boolean uiSleeping, ActivityRecord resuming, String reason) {
    return startPausing(mTaskSupervisor.mUserLeaving, uiSleeping, resuming, reason);
}

// userLeaving 为 true
// uiSleeping 为 false
// resuming 就是要启动的 activity
// reason 为 pauseBackTasks
boolean startPausing(boolean userLeaving, boolean uiSleeping, ActivityRecord resuming,
        String reason) {
    if (!hasDirectChildActivities()) {
        return false;
    }

    ProtoLog.d(WM_DEBUG_STATES, "startPausing: taskFrag =%s " + "mResumedActivity=%s", this,
            mResumedActivity);

    if (mPausingActivity != null) {
        
    }
    
    ActivityRecord prev = mResumedActivity;

    if (prev == null) {
        
    }

    if (prev == resuming) {
        
    }

    ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSING: %s", prev);
    
    // 标记正在暂停的 activity
    // 这个就是当前的 resumed activity
    mPausingActivity = prev;
    
    // TODO: 此时就标记已经暂停的 activity,是不是有点不妥?
    mLastPausedActivity = prev;
    
    if (!prev.finishing && prev.isNoHistory()
            && !mTaskSupervisor.mNoHistoryActivities.contains(prev)) {
        
    }
    
    // 1. 切换 PAUSING 状态,并且 TaskFragment 还会清空 mResumedActivity
    prev.setState(PAUSING, "startPausingLocked");
    
    // ...

    boolean pauseImmediately = false;
    boolean shouldAutoPip = false;
    if (resuming != null) {
        // ...
        
        if (prev.supportsEnterPipOnTaskSwitch && userLeaving
                && resumingOccludesParent && lastResumedCanPip
                && prev.pictureInPictureArgs.isAutoEnterEnabled()) {
            // ...
        } else if (!lastResumedCanPip) {
            // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous
            // activity to be paused.
            // FLAG_RESUME_WHILE_PAUSING 表示不用等到 app 反馈暂停完成,服务端就可以立即完成暂停
            // FLAG_RESUME_WHILE_PAUSING 来自于 AndroidMainfest 的 Activity 属性
            pauseImmediately = (resuming.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;
        } else {
            
        }
    }

    if (prev.attachedToProcess()) {
        if (shouldAutoPip && ActivityTaskManagerService.isPip2ExperimentEnabled()) {
            // ...
        } else if (shouldAutoPip) {
            // ...
        } else {
            // 2.通知 app 端暂停 activity
            schedulePauseActivity(prev, userLeaving, pauseImmediately,
                    false /* autoEnteringPip */, reason);
        }
    } else {
        // ...
    }

    // ...

    // If already entered PIP mode, no need to keep pausing.
    if (mPausingActivity != null) {
        if (!uiSleeping) {
            // 暂停事件分发
            prev.pauseKeyDispatchingLocked();
        } else {
            // ...
        }

        // FLAG_RESUME_WHILE_PAUSING 就是在这里起作用的,服务端立即 complete pause,
        // 而不用等到 app 反馈暂停完成。
        // 本案例不走这里
        if (pauseImmediately) {
            // If the caller said they don't want to wait for the pause, then complete
            // the pause now.
            completePause(false, resuming);
            return false;

        } else {
            // app 反馈暂停完成也有超时时间限制
            prev.schedulePauseTimeout();
            
            // All activities will be stopped when sleeping, don't need to wait for pause.
            if (!uiSleeping) {
                // 3.强制设置 transition ready 为 false
                // Unset readiness since we now need to wait until this pause is complete.
                mTransitionController.setReady(this, false /* ready */);
            }
            return true;
        }

    } else {
        // ...
    }
}

这里就是暂停后台 Task 的真正的逻辑

  1. 把 resumed activity 标记为 pausing activity,并切换状态为 PAUSING。与此同时,TaskFragment 会清理 resumed activity。
  2. 通知 app 端去 pause activity。
  3. 强制设置 transition ready 为 false,因为 pause activity 的生命周期流程还没有走完。

小结

第一阶段启动,主要做了如下事情

  1. 创建 ActivityRecord 和 Task,并构建窗口层级。
  2. 创建 OPEN Transition,收集了存在性改变的 ActivityRecord 和 Task。
  3. 暂停后台 Tasks,即通知 app 端去 pause Activity。
  4. 拉起 app 进程。
  5. 向 WMShell 发起 transition request。

第二阶段启动

app 端 pause activity 后,会通知服务端,服务端会再尝试启动 Activity,我称之为第二阶段启动

// ActivityClientController.java

    public void activityPaused(IBinder token) {
        final long origId = Binder.clearCallingIdentity();
        synchronized (mGlobalLock) {
            // 注意,这里有 activity paused 的 trace
            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityPaused");
            
            final ActivityRecord r = ActivityRecord.forTokenLocked(token);
            if (r != null) {
                // ActvityRecord 处理 activity paused
                r.activityPaused(false);
            }
            
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
        Binder.restoreCallingIdentity(origId);
    }
// ActivityRecord.java

    void activityPaused(boolean timeout) {
        ProtoLog.v(WM_DEBUG_STATES, "Activity paused: token=%s, timeout=%b", token,
                timeout);

        final TaskFragment taskFragment = getTaskFragment();
        if (taskFragment != null) {
            removePauseTimeout();

            final ActivityRecord pausingActivity = taskFragment.getPausingActivity();
            if (pausingActivity == this) {
                ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSED: %s %s", this,
                        (timeout ? "(due to timeout)" : " (pause complete)"));
                        
                mAtmService.deferWindowLayout();
                
                try {
                    // taskFragment 执行 complete pause
                    // 第一个参数 resumeNext 为 true,表示需要 resume top activity
                    taskFragment.completePause(true /* resumeNext */, null /* resumingActivity */);
                } finally {
                    // 由于有可见性更新,因此 continue layout 会发起窗口刷新
                    mAtmService.continueWindowLayout();
                }
                
                return;
            } else {
                // ...
            }
        }

        // ...
    }
// TaskFragment.java

// resumeNext 为 true
// resuming 为 null
void completePause(boolean resumeNext, ActivityRecord resuming) {

    ActivityRecord prev = mPausingActivity;
    ProtoLog.v(WM_DEBUG_STATES, "Complete pause: %s", prev);

    // 1. 完成 activity pause 流程
    if (prev != null) {
        prev.setWillCloseOrEnterPip(false);
        // 当前状态为 PAUSING
        final boolean wasStopping = prev.isState(STOPPING);
        
        // 状态切换到 PAUSED
        prev.setState(PAUSED, "completePausedLocked");
        
        mPausingActivity = null;
        
        if (prev.finishing) {
            
        } else if (prev.attachedToProcess()) {
            ProtoLog.v(WM_DEBUG_STATES, "Enqueue pending stop if needed: %s "
                            + "wasStopping=%b visibleRequested=%b",  prev,  wasStopping,
                    prev.isVisibleRequested());
            if (wasStopping) {
                
            } else if (!prev.isVisibleRequested() || shouldSleepOrShutDownActivities()) {
                
            }
        } else {
            
        }

        if (prev != null) {
            prev.stopFreezingScreen(true /* unfreezeNow */, true /* force */);
        }
    }

    // 2. 由 RWC 继续启动 activity
    if (resumeNext) {
        final Task topRootTask = mRootWindowContainer.getTopDisplayFocusedRootTask();
        if (topRootTask != null && !topRootTask.shouldSleepOrShutDownActivities()) {
            // 由 RWC resume top activity of top root task
            mRootWindowContainer.resumeFocusedTasksTopActivities(topRootTask, prev,
                    null /* targetOptions */);
        } else {
            
        }
    }

    if (prev != null) {
        // 注意,activity 暂停完成后,才恢复事件分发
        prev.resumeKeyDispatchingLocked();
    }

    // 3. 更新所有 activity 可见性
    // resuming 为 null
    mRootWindowContainer.ensureActivitiesVisible(resuming);

    // ...
}

activity pause 流程,最终是由其 TaskFragment 处理

  1. 把 mPausingActivity 的状态切换到 PAUSED,并清理 mPausingActivity。
  2. 由 RootWindowContainer resume top activity of top root task,也就是继续启动 activity。
  3. 更新所有 Activity 的可见性。这里涉及到 stop activity 生命周期流程。

RootWindowContainer 启动 activity

RootWindowContainer 启动 activity 的方法,在前面已经分析过,最终是由 TaskFragment 来启动 activity。

// TaskFragment.java

    // 参数 prev 此时代表已经完成暂停的 Activity
    // options 为 null
    // deferPause 为 false
    final boolean resumeTopActivity(ActivityRecord prev, ActivityOptions options,
            boolean deferPause) {
        // 获取 top-focusable-non-finishing activity,就是要启动的 activity
        ActivityRecord next = topRunningActivity(true /* focusableOnly */);
        
        // ...

        // 此时后台 Tasks 都已经暂停完成
        final boolean allPausedComplete = mRootWindowContainer.allPausedActivitiesComplete();
        // 如果还有 Task 正在暂停,是不能启动 activity 的
        if (!allPausedComplete) {
            ProtoLog.v(WM_DEBUG_STATES,
                    "resumeTopActivity: Skip resume: some activity pausing.");
            return false;
        }

        final TaskDisplayArea taskDisplayArea = getDisplayArea();
        
        // 此时 mResumedActivity 为 null
        if (mResumedActivity == next && next.isState(RESUMED)
                && taskDisplayArea.allResumedActivitiesComplete()) {
            // ....
            return false;
        }

        // 此时 mLastPausedActivity 为 null
        if (mLastPausedActivity == next && shouldSleepOrShutDownActivities()) {
            // ...
            return false;
        }

        // ...

        // 暂停后台 Task
        // 此时已经没有需要暂停的后台 Task 了,因此这里返回 false
        boolean pausing = !deferPause && taskDisplayArea.pauseBackTasks(next);
        
        // mResumedActivity 为 null
        if (mResumedActivity != null) {
            // ...
        }
        
       
        if (pausing) {
            // ...
        } 
        // mResumedActivity 为 null
        else if (mResumedActivity == next && next.isState(RESUMED)
                && taskDisplayArea.allResumedActivitiesComplete()) {
            //  ....
            return true;
        }

        // ...

        // next 代表要启动的 activity
        // next.nowVisible 代表是 Acivity 的窗口是否可见,现在是不可见的
        if (prev != null && prev != next && next.nowVisible) {
            // ...
        }

        // ...

        boolean anim = true;
        final DisplayContent dc = taskDisplayArea.mDisplayContent;
        if (prev != null) {
            if (prev.finishing) {
                // ...
            } else {
                if (DEBUG_TRANSITION) {
                    Slog.v(TAG_TRANSITION, "Prepare open transition: prev=" + prev);
                }
                
                if (mTaskSupervisor.mNoAnimActivities.contains(next)) {
 
                } else {
                    // app transition 已经废弃
                    dc.prepareAppTransition(TRANSIT_OPEN,
                            next.mLaunchTaskBehind ? TRANSIT_FLAG_OPEN_BEHIND : 0);
                }
            }
        } else {
            // ...
        }

        if (anim) {
            // transition 会保存 app 制定的动画的 options
            next.applyOptionsAnimation();
        } else {
            
        }

        mTaskSupervisor.mNoAnimActivities.clear();

        if (next.attachedToProcess()) { // 此时,app 进程还在创建中
            // ...
        } else {
            // Whoops, need to restart this activity!
            if (!next.hasBeenLaunched) {
                next.hasBeenLaunched = true;
            } else {
                
            }
            
            ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Restarting %s", next);
            
            // 根据进程状态启动 activity
            mTaskSupervisor.startSpecificActivity(next, true, true);
        }

        return true;
    }

此时,根据 ActivityRecord 是否绑定到进程,来决定如何启动 activity。但是须知,拉起 app 进程其实是“非常慢”的一个过程,它基本上都是在 activity paused 之后才完成的。

// ActivityTaskSupervisor.java

void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
    // Is this activity's application already running?
    // 进程还没有起来呢
    final WindowProcessController wpc =
            mService.getProcessController(r.processName, r.info.applicationInfo.uid);

    boolean knownToBeDead = false;
    if (wpc != null && wpc.hasThread()) {
        // ...
    }

    r.notifyUnknownVisibilityLaunchedForKeyguardTransition();

    final boolean isTop = andResume && r.isTopRunningActivity();
    // 继续拉起进程
    mService.startProcessAsync(r, knownToBeDead, isTop,
            isTop ? HostingRecord.HOSTING_TYPE_TOP_ACTIVITY
                    : HostingRecord.HOSTING_TYPE_ACTIVITY);
}

很不幸,由于 app 进程还在启动中,第二阶段启动,让然无法真正启动 Activity。

更新 ActivityRecord 可见性

RootWindowContainer 会把更新 ActivityRecord 可见性的任务交给 Task,Task 交给 EnsureActivitiesVisibleHelper

// EnsureActivitiesVisibleHelper.java

// starting 为 null
// notifyClients 为 true
void process(@Nullable ActivityRecord starting, boolean notifyClients) {
    reset(starting, notifyClients);

    if (DEBUG_VISIBILITY) {
        Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible behind " + mTopRunningActivity);
    }
    if (mTopRunningActivity != null && mTaskFragment.asTask() != null) {
        mTaskFragment.asTask().checkTranslucentActivityWaiting(mTopRunningActivity);
    }

    // We should not resume activities that being launched behind because these
    // activities are actually behind other fullscreen activities, but still required
    // to be visible (such as performing Recents animation).
    final boolean resumeTopActivity = mTopRunningActivity != null
            && !mTopRunningActivity.mLaunchTaskBehind
            && mTaskFragment.canBeResumed(starting)
            && (starting == null || !starting.isDescendantOf(mTaskFragment));

    ArrayList<TaskFragment> adjacentTaskFragments = null;
    for (int i = mTaskFragment.mChildren.size() - 1; i >= 0; --i) {
        final WindowContainer child = mTaskFragment.mChildren.get(i);
        final TaskFragment childTaskFragment = child.asTaskFragment();
        if (childTaskFragment != null
                && childTaskFragment.getTopNonFinishingActivity() != null) {
            // ..
        } else if (child.asActivityRecord() != null) {
            // 设置 activity 可见性
            setActivityVisibilityState(child.asActivityRecord(), starting, resumeTopActivity);
        }
    }
}

EnsureActivitiesVisibleHelper 会针对 ActivityRecord ,设置可见性

// EnsureActivitiesVisibleHelper.java

private void setActivityVisibilityState(ActivityRecord r, ActivityRecord starting,
        final boolean resumeTopActivity) {
    // ...

    if (reallyVisible) { // 一般来说,只有 top task 的 top activity 才需要可见
        if (r.finishing) {
            return;
        }
        if (DEBUG_VISIBILITY) {
            Slog.v(TAG_VISIBILITY, "Make visible? " + r
                    + " finishing=" + r.finishing + " state=" + r.getState());
        }
        
        // 当前要启动的 ActivityRecord 还处于 INITIALING 界面,因此这里不会更新可见性
        if (r != mStarting && mNotifyClients) {
            r.ensureActivityConfiguration(true /* ignoreVisibility */);
        }

        if (!r.attachedToProcess()) { // ActivityRecord 没有绑定到进程的情况
            // 1. ActivityRecord设置可见,并且尝试启动 activity
            makeVisibleAndRestartIfNeeded(mStarting, resumeTopActivity && isTop, r);
        } else if (r.isVisibleRequested()) { // ActivityRecord 已经请求可见
            
        } else { // ActivityRecord 绑定到进程,并且请求可见为 false
            r.makeVisibleIfNeeded(mStarting, mNotifyClients);
        }
    } else { // 一般来说,top task 之下的 task 的 activity 都不可见
        if (DEBUG_VISIBILITY) {
            Slog.v(TAG_VISIBILITY, "Make invisible? " + r
                    + " finishing=" + r.finishing + " state=" + r.getState()
                    + " containerShouldBeVisible=" + mContainerShouldBeVisible
                    + " behindFullyOccludedContainer=" + mBehindFullyOccludedContainer
                    + " mLaunchTaskBehind=" + r.mLaunchTaskBehind);
        }
        // 2. 设置不可见
        r.makeInvisible();
    }

    // ...
}

对于本案例来说,app task 现在已经是top task,而 Launcher task 是在其下。

那么,app task 的 ActivityRecord 的可见性,要被更新为 true,而 Launcher ActivityRecord 的可见性,要被更新为 false。

来看下 Launcher ActivityRecord 可见性更新为 false 的流程

// ActivityRecord.java

void makeInvisible() {
    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.
    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. 设置可见性为 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. 进入 stopping 生命周期流程
                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);
    }
}

本文只分析生命周期,因此第一步可见性更新就不分析了,看下第二步的进去 stop activity 流程

// ActivityRecord.java

// scheduleIdle 为 true
// idleDelayed 为 false
// reason 为 makeInvisible
void addToStopping(boolean scheduleIdle, boolean idleDelayed, String reason) {

    // 1. 加入到 mTaskSupervisor.mStoppingActivities 列表中
    if (!mTaskSupervisor.mStoppingActivities.contains(this)) {
        EventLogTags.writeWmAddToStopping(mUserId, System.identityHashCode(this),
                shortComponentName, reason);
        mTaskSupervisor.mStoppingActivities.add(this);
    }

    final Task rootTask = getRootTask();
    boolean forceIdle = mTaskSupervisor.mStoppingActivities.size() > MAX_STOPPING_TO_FORCE
            || (isRootOfTask() && rootTask.getChildCount() <= 1);
    
    // scheduleIdle 此时为 true
    if (scheduleIdle || forceIdle) {
        ProtoLog.v(WM_DEBUG_STATES,
                "Scheduling idle now: forceIdle=%b immediate=%b", forceIdle, !idleDelayed);
        
        // idleDelayed 此时为 false
        if (!idleDelayed) {
            // 2.调度 idle
            // 会执行 ActivityTaskSupervisor#activityIdleInterna()
            mTaskSupervisor.scheduleIdle();
        } else {
            // ...
        }
    } else {
        // ...
    }
}
// ActivityTaskSupervisor.java

void activityIdleInternal(ActivityRecord r, boolean fromTimeout,
        boolean processPausingActivities, Configuration config) {
    if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + r);

    if (r != null) {
        // ...
    }

    // app task 还没有 resume activity 呢,那么 activity 肯定不是出于 idle 状态
    if (mRootWindowContainer.allResumedActivitiesIdle()) {
        // ...
    }

    // 处理 stopping 或者 finishing activity
    processStoppingAndFinishingActivities(r, processPausingActivities, "idle");

    if (DEBUG_IDLE) {
        Slogf.i(TAG, "activityIdleInternal(): r=%s, mStartingUsers=%s", r, mStartingUsers);
    }

    // ...
}
// ActivityRecord.java

void processStoppingAndFinishingActivities(ActivityRecord launchedActivity,
        boolean processPausingActivities, String reason) {

    boolean displaySwapping = false;
    // 处理 stopping activity
    ArrayList<ActivityRecord> readyToStopActivities = null;
    for (int i = 0; i < mStoppingActivities.size(); i++) {
        final ActivityRecord s = mStoppingActivities.get(i);
        
        
        // 是否处于 transition 动画
        final boolean animating = s.isInTransition()
                && s.getTask() != null && !s.getTask().isForceHidden();
                
        displaySwapping |= s.isDisplaySleepingAndSwapping();
        
        ProtoLog.v(WM_DEBUG_STATES, "Stopping %s: nowVisible=%b animating=%b "
                + "finishing=%s", s, s.nowVisible, animating, s.finishing);
                
        // 不处于 transition 动画,才可以把 ActivityRecord 从 mStoppingActivities 移除
        // 并保存到 readyToStopActivities
        if ((!animating && !displaySwapping) || mService.mShuttingDown
                || s.getRootTask().isForceHiddenForPinnedTask()) {
            if (!processPausingActivities && s.isState(PAUSING)) {

            }

            ProtoLog.v(WM_DEBUG_STATES, "Ready to stop: %s", s);
            
            if (readyToStopActivities == null) {
                readyToStopActivities = new ArrayList<>();
            }
            readyToStopActivities.add(s);

            mStoppingActivities.remove(i);
            i--;
        }
    }


    if (displaySwapping) {
       
    }

    // 让 readyToStopActivities 中的 Actvity 进入 stop 流程
    final int numReadyStops = readyToStopActivities == null ? 0 : readyToStopActivities.size();
    for (int i = 0; i < numReadyStops; i++) {
        final ActivityRecord r = readyToStopActivities.get(i);
        if (r.isInHistory()) {
            if (r.finishing) {
                
            } else {
                // 通知 app stop activity
                r.stopIfPossible();
            }
        }
    }

    // 省略处理 finishing activity 代码 ...
}

这里只是暂时 Launcher ActivityRecord 保存到 mTaskSupervisor.mStoppingActivities,而由于 Launcher ActivityRecord 此时处于 Transition 动画中,因此,无法执行 stop activity 流程。

从这里也可以推理出,当 Transition 动画结束时,才会执行 Launcher activity 的 stop 生命周期流程。

小结

第二阶段启动,始于 app 端通知服务端 activity paused 完成。但是,由于 app 进程还在启动中,因此仍然无法完成 activity 的启动。

但是,对于 Transition 动画来说,第二阶段启动还包含 ActivityRecord 可见性更新,其中 app ActivityRecord 可见性被更新为 true,Launcher ActivityRecord 的可见性被更新为 false。

第三阶段启动

当 app 进程起来后,它与服务端交互时,也会让服务端去启动 app 进程相关联的,并还未完成启动的 Activity。

由于 app 进程的启动,是一个异步过程,因此,我称之为第三阶段启动。

// ActivityThread.java

public static void main(String[] args) {
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
    // ...
    Looper.prepareMainLooper();
    // ...
    // 创建 ActivityThread,并调用它的 attach() 
    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq);
    // ...
    
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

private void attach(boolean system, long startSeq) {
    // ..

    if (!system) {
        final IActivityManager mgr = ActivityManager.getService();
        try {
            // 1. attach app
            // mAppThread 是一个 binder 回调,在服务端代表 app 进程
            mgr.attachApplication(mAppThread, startSeq);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }

        // ...
    } else {
        // ...
    }

    // ...
}    

ActivityThreaad#main() 最终就是向服务端注册一个 Binder 回调,这就是所谓的 attach app。

attach app

现在来看下服务端的 attach app 流程

// ActivityManagerService.java

public final void attachApplication(IApplicationThread thread, long startSeq) {
    if (thread == null) {
        throw new SecurityException("Invalid application interface");
    }
    synchronized (this) {
        int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid, callingUid, startSeq);
        Binder.restoreCallingIdentity(origId);
    }
}

private void attachApplicationLocked(@NonNull IApplicationThread thread,
        int pid, int callingUid, long startSeq) {
    // ...

    if (pid != MY_PID && pid >= 0) {
        synchronized (mPidsSelfLocked) {
            // 进程创建的时候,会保存到 mPidsSelfLocked
            app = mPidsSelfLocked.get(pid);
        }
        if (app != null && (app.getStartUid() != callingUid || app.getStartSeq() != startSeq)) {
            // ...
        }
    } else {
        // ...
    }

    // ...

    EventLogTags.writeAmProcBound(app.userId, pid, app.processName);

    // ...

    try {
        // ...

        if (app.getIsolatedEntryPoint() != null) {
            // ....
        } else if (instr2 != null) {
            // ...
        } else {
            // 1. 通知 app 进行 bind application
            thread.bindApplication(processName, appInfo,
                    app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,
                    providerList, null, profilerInfo, null, null, null, testMode,
                    mBinderTransactionTrackingEnabled, enableTrackAllocation,
                    isRestrictedBackupMode || !normalMode, app.isPersistent(),
                    new 
                     // 来自 wps 的配置
                    Configuration(app.getWindowProcessController().getConfiguration()),
                    app.getCompat(), getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked(),
                    buildSerial, autofillOptions, contentCaptureOptions,
                    app.getDisabledCompatChanges(), serializedSystemFontMap,
                    app.getStartElapsedTime(), app.getStartUptime());
        }
        
        // ...

        synchronized (mProcLock) {
            // 2. 进程与 app 端绑定
            // 进程实例 ProcessRecord 保存 app 端传入的回调 IApplicationThread 对象
            app.makeActive(thread, mProcessStats);
            checkTime(startTime, "attachApplicationLocked: immediately after bindApplication");
        }
        
        // ... 

        // mConstants.mEnableWaitForFinishAttachApplication 默认为 false
        // 如果为 true,表示需要等待 app 完成 bind application 之后,才执行 finish attach application 操作
        if (!mConstants.mEnableWaitForFinishAttachApplication) {
            // 3. finish attach app
            // 四大组件中如果有等待进程启动的,此时就可以启动组件
            finishAttachApplicationInner(startSeq, callingUid, pid);
        } else {
            // ...
        }
    } catch (Exception e) {
        // ...
    }
}

服务端 attach app

  1. 通知 app 端 bind application,其实就是把数据发送给 app 端。
  2. 进程与 app 端绑定。
  3. finish attach app,主要是针对四大组件的启动。

finish attach app

// ActivityManagerService.java

private void finishAttachApplicationInner(long startSeq, int uid, int pid) {
    final ProcessRecord app;
    synchronized (mPidsSelfLocked) {
        // 获取进程实例 ProcessRecord
        app = mPidsSelfLocked.get(pid);
    }
    // ...
    synchronized (this) {
        // ...

        // See if the top visible activity is waiting to run in this process...
        if (normalMode) {
            try {
                didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
            } catch (Exception e) {
                // ...
            }
        }
        // ...
    }
}
// ActivityTaskManagerService.java

public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
    synchronized (mGlobalLockWithoutBoost) {
        // attach app 的 trace
        if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "attachApplication:" + wpc.mName);
        }
        try {
            return mRootWindowContainer.attachApplication(wpc);
        } finally {
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
    }
}

finish attach app 把启动 activity 的任务交给了 RootWindowContainer

// RootWindowContainer.java

boolean attachApplication(WindowProcessController app) throws RemoteException {
    // 拉起app进程调用的 startProcessAsync() 中,会把要启动的 activity 保存到 mService.mStartingProcessActivities
    final ArrayList<ActivityRecord> activities = mService.mStartingProcessActivities;
    RemoteException remoteException = null;
    boolean hasActivityStarted = false;
    for (int i = activities.size() - 1; i >= 0; i--) {
        final ActivityRecord r = activities.get(i);
        
        // 省略检测是否要启动 activity 的代码 ...
        
        try {
            final boolean canResume = r.isFocusable() && r == tf.topRunningActivity();
            
            // 真正启动 activity 来了
            if (mTaskSupervisor.realStartActivityLocked(r, app, canResume,
                    true /* checkConfig */)) {
                hasActivityStarted = true;
            }
        } catch (RemoteException e) {
            Slog.w(TAG, "Exception in new process when starting " + r, e);
            remoteException = e;
        }
    }
    if (remoteException != null) {
        throw remoteException;
    }
    return hasActivityStarted;
}
// ActivityTaskSupervisor.java

boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
        boolean andResume, boolean checkConfig) throws RemoteException {

    // 如果有 activity 还没有暂停完成,那么不能启动新 activity
    if (!mRootWindowContainer.allPausedActivitiesComplete()) {
        ProtoLog.v(WM_DEBUG_STATES,
                "realStartActivityLocked: Skipping start of r=%s some activities pausing...",
                r);
        return false;
    }

    final Task task = r.getTask();
    if (andResume) {
    
        // 当前 task 没有 resumed activity,不需要 pause
        if (task.pauseActivityIfNeeded(r, "realStart")) {
            
        }
        final TaskFragment taskFragment = r.getTaskFragment();
        if (taskFragment != null && taskFragment.getResumedActivity() != null) {
  
        }
    }

    final Task rootTask = task.getRootTask();
    
    beginDeferResume();
    proc.pauseConfigurationDispatch();// 推迟配置分发

    try {
        // ...
        
        // ActivityRecord 先与进程绑定,再启动柜
        r.setProcess(proc);

        // ...
        
        // checkConfig 此时为 true
        if (checkConfig) {
            // 更新 activity 可见性,以及确保 activity 能正确处理配置
            // 可见性更新,在前面执行过
            // 至于配置,ActivityRecord 还处于 INITIALING 状态,无需考虑
            mRootWindowContainer.ensureVisibilityAndConfig(r, r.mDisplayContent,
                    true /* deferResume */);
        }

        // 前面已经更新过可见性
        if (mKeyguardController.checkKeyguardVisibility(r) && r.allowMoveToFront()) {
            // We only set the visibility to true if the activity is not being launched in
            // background, and is allowed to be visible based on keyguard state. This avoids
            // setting this into motion in window manager that is later cancelled due to later
            // calls to ensure visible activities that set visibility back to false.
            r.setVisibility(true);
        }

        // ...
        
        // 这个 binder 会发送给 app 端,app 端会利用它与服务端沟通 activity 状态
        final IActivityClientController activityClientController =
                proc.hasEverLaunchedActivity() ? null : mService.mActivityClientController;
        r.launchCount++;

        if (DEBUG_ALL) Slog.v(TAG, "Launching: " + r);

        // ...

        try {
            // ...
            
            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
                    "Launching: " + r + " savedState=" + r.getSavedState()
                            + " with results=" + results + " newIntents=" + newIntents
                            + " andResume=" + andResume);
                            
            // 真正启动 activity 的 event log : wm_restart_activity
            EventLogTags.writeWmRestartActivity(r.mUserId, System.identityHashCode(r),
                    task.mTaskId, r.shortComponentName);
            
            // ...

            // 有 WPC 的 full config 和 ActivityRecord 的 merged override config 
            // 共同组成发送给 app 的配置
            final Configuration procConfig = proc.prepareConfigurationForLaunchingActivity();
            final Configuration overrideConfig = r.getMergedOverrideConfiguration();
            r.setLastReportedConfiguration(procConfig, overrideConfig);
            
            // 这里会把 task bounds 也发送给 app 端
            final ActivityWindowInfo activityWindowInfo = r.getActivityWindowInfo();
            r.setLastReportedActivityWindowInfo(activityWindowInfo);

            // ...

            // Create activity launch transaction.
            final boolean isTransitionForward = r.isTransitionForward();
            final IBinder fragmentToken = r.getTaskFragment().getFragmentToken();
            final int deviceId = getDeviceIdForDisplayId(r.getDisplayId());
            
            // 创建 Launch activity callback
            final LaunchActivityItem launchActivityItem = LaunchActivityItem.obtain(r.token,
                    r.intent, System.identityHashCode(r), r.info,
                    procConfig, overrideConfig, deviceId,
                    r.getFilteredReferrer(r.launchedFromPackage), task.voiceInteractor,
                    proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(),
                    results, newIntents, r.takeSceneTransitionInfo(), isTransitionForward,
                    proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
                    r.shareableActivityToken, r.getLaunchedFromBubble(), fragmentToken,
                    r.initialCallerInfoAccessToken, activityWindowInfo);

            // Set desired final state.
            final ActivityLifecycleItem lifecycleItem;
            if (andResume) {
                // 创建 resume 生命周期请求
                lifecycleItem = ResumeActivityItem.obtain(r.token, isTransitionForward,
                        r.shouldSendCompatFakeFocus());
            } else if (r.isVisibleRequested()) {
                
            } else {
                
            }

            // ...
            
            // 通知 app 端启动 activity,并把生命周期执行到 resume
            mService.getLifecycleManager().scheduleTransactionAndLifecycleItems(
                    proc.getThread(), launchActivityItem, lifecycleItem,
                    // Immediately dispatch the transaction, so that if it fails, the server can
                    // restart the process and retry now.
                    true /* shouldDispatchImmediately */);

            // ...

        } catch (RemoteException e) {
            
        }
    } finally {
        endDeferResume();
        proc.resumeConfigurationDispatch();
    }

    r.launchFailed = false;

    // TODO(lifecycler): Resume or pause requests are done as part of launch transaction,
    // so updating the state should be done accordingly.
    if (andResume && readyToResume()) {
        // 服务端执行一小部分的 resumed activity 流程
        // 剩下的流程,是在 app 端通知 activity resumed 后执行
        r.setState(RESUMED, "realStartActivityLocked");
        r.completeResumeLocked();
    } else if (r.isVisibleRequested()) {
        
    } else {
        
    }
    
    // ...

    return true;
}

ActivityTaskSupervisor#realStartActivityLocked() 正如函数名一样,真正用来启动 Activity, 其实就是通知 app 端启动 activity,并把生命周期执行到 resume。