Android Framework(三)Activity启动流程

news2024/9/22 1:18:06

文章目录

  • 大纲
    • 总体流程
  • 第一阶段:点击图标启动应用
    • 流程概览
    • SourceActivity端处理
    • system_service处理
      • 启动请求参数的构建
      • activityInfo的解析
      • 创建ActivityRecord
    • 窗口层级树的处理
      • 获取Task--getOrCreateRootTask
      • ActivityRecord挂载到Task--setNewTask
      • 移动Task到容器顶部--moveToFront
    • 显示Activity--resumeFocusedTasksTopActivities
      • pause 流程--pauseBackTasks
      • PauseActivityItem
    • 阶段一总结
    • system_service 处理的完整堆栈
  • 第二阶段--completePause
      • ActivityRecord::activityPaused
      • 第一步--resumeFocusedTasksTopActivities
      • 关键方法--startSpecificActivity
      • 第二步--ensureActivitiesVisible 流程
      • 阶段二总结
  • 第三阶段:触发目标应用进程创建
      • 应用进程创建
      • system_service端处理
      • 阶段三总结
  • 第四阶段:真正启动Activity
    • 创建Activity
    • 阶段四小结

大纲

在这里插入图片描述
对于Activity的启动流程来说,可以分为3个模块:

1、SourceActivity:执行 startActivity 方法的 Activity ,也就是发起请求的Activity ,当前是 Launcher 的 Activity 。

2、TargetActivity:被启动的 Activity 当前就是“电话”应用在清单文件配置的MainActivity。

3、AMS: 不仅仅是指 AMS 这一个类,而是指在这个过程中 system_service 进程参与处理的相关类。

这3个模块也对应3个进程,当前案例来说分别为:Launcher 进程,电话进程,system_service 进程。

图中AMS 对 Launcher 多了一个返回箭头的原因是 Launcher 肯定是需要执行 pause 的,但执行 pause 的时机 Launcher 自身无法控制,只能由 AMS 控制。

总体流程

在这里插入图片描述
这里有4个阶段,以4个颜色表示。同时还涉及到3个进程。

第一阶段:
1、由 Launcher 进程发起启动 Activity 的请求
2、AMS 处理,创建对应的 ActivityRecord 和 Task ,并挂载到窗口层级树中
3、AMS 触发 Launcher 的 pause 流程
4、AMS 触发"电话"应用进程的创建

第二阶段:
1、Launcher 执行完 pause
2、pause 流程完成后触发 AMS 启动 TargetActivity

第三阶段:
1、创建应用进程
2、应用进程创建好后会向 AMS 进行绑定,并触发 AMS 启动 TargetActivity

第四阶段:
1、AMS 触发 realStartActivityLocked 方法试图应用启动 Activity
2、如果还有 Activity 没有执行完 pause 逻辑,则 realStartActivityLocked 会 return
3、如果应用 Activity 都执行完了 pause ,则触发 TargetActivity 的启动,并将生命周期会执行到 onResume

注意:其中第2,3阶段几乎是同时开始的,并且 ASM 通知 Launcher 执行 pause 和通过 Zygote 创建进程是异步操作,不知道各自执行的顺序。
但是看的出来最终都是会执行到 realStartActivityLocked 方法来试图启动 TargetActivity ,为什么说是“试图启动”启动呢?
一共就有2种可能:

  • completePause 先执行完
  • 进程先创建完

假设第一种情况:

  • Launcher 先执行完 completePause 来到 ActivityTaskSupervisor::startSpecificActivity 方法,这个时候进程还没创建完毕,则不会执行 ActivityTaskSupervisor::realStartActivityLocked ,而是会再触发进程创建,当然之前已经触发过来,这次触发不会真的再创建进行了。

  • 然后会由阶段三的流程创建好进程走到 ActivityTaskSupervisor::realStartActivityLocked ,在这个方法里会判断是不是执行完 pause 了,那当前这个情况肯定是满足的,
    所以会触发启动 TargetActivity 。

假设第二种情况:

  • 阶段三创建进程先执行完,走到 ActivityTaskSupervisor::realStartActivityLocked 方法,但是发现 pause 还没执行玩,所以就 return 了。
  • 然后等 completePause 流程来到 ActivityTaskSupervisor::startSpecificActivity 方法时,这次发现进程已经创建好了,则一次执行后续逻辑触发启动 TargetActivity 。

也就是说不管阶段二,三谁先执行完都会试图启动 TargetActivity ,而成功启动必须有2个条件:

  • 进程创建完毕
  • launcher执行完pause

第一阶段:点击图标启动应用

流程概览

堆栈:

ItemClickHandler::onClick
    ItemClickHandler::onClickAppShortcut
        ItemClickHandler::startAppShortcutOrInfoActivity
            QuickstepLauncher::startActivitySafely
                Launcher::startActivitySafely
                    AppLauncher::startActivitySafely
                        BaseQuickstepLauncher::getActivityLaunchOptions    -- 构建 Option 参数
                        Activity::startActivity  -- 共用启动Activity流程
                            Activity::startActivity
                                Activity::startActivity
                                    Activity::startActivityForResult
                                        Instrumentation::execStartActivity
                                            ActivityTaskManagerService::startActivity -- 跨进程

画成时序图:
在这里插入图片描述
其实我们正常通过 startActivity 传递 Intent 启动 Activity 的流程也是一样的,最终都会调到 Instrumentation::execStartActivity 然后开始跨进程与 AMS 通信。
只不过这边多了一些 Launcher 自己的处理,这边只需要对 BaseQuickstepLauncher::getActivityLaunchOptions 有个印象即可,这个方法会构建 ActivityOptions 对象,包含了一起启动参数,比如:远端动画的 RemoteAnimationAdapter 。
前面的流程就不看了,执行从 Activity::startActivityForResult 开始看代码流程。

SourceActivity端处理

SourceActivity 发起启动 Activity 的逻辑相对简单,无论哪种参数的 Activity::startActivity 方法,最终都是调到 Activity::startActivityForResult 方法。
然后在 Instrumentation 最后的处理,最后跨进程传递到 system_service 进程中。

# Activity.java
    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            ......
        }
        ......
    }
# Instrumentation.java
    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        ......
            // 当前应用进程处理结束,开始传递给 ActivityTaskManagerService
            int result = ActivityTaskManager.getService().startActivity(whoThread,
                who.getOpPackageName(), who.getAttributionTag(), intent,
                intent.resolveTypeIfNeeded(who.getContentResolver()), token,
                target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
            // 对跨进程启动的结果做check
            checkStartActivityResult(result, intent);
        ......
    }

Instrumentation::checkStartActivityResult 这个方法有一些常见的报错,比如常见的未在 AndroidManifest.xml 注册 Activity 的报错就在这。

# Instrumentation

    public static void checkStartActivityResult(int res, Object intent) {
        if (!ActivityManager.isStartResultFatalError(res)) {
            return;
        }

        switch (res) {
            case ActivityManager.START_INTENT_NOT_RESOLVED:
            case ActivityManager.START_CLASS_NOT_FOUND:  // 未在AndroidManifest.xml注册
                if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
                    throw new ActivityNotFoundException(
                            "Unable to find explicit activity class "
                            + ((Intent)intent).getComponent().toShortString()
                            + "; have you declared this activity in your AndroidManifest.xml"
                            + ", or does your intent not match its declared <intent-filter>?");
                throw new ActivityNotFoundException(
                        "No Activity found to handle " + intent);
            case ActivityManager.START_PERMISSION_DENIED:
                throw new SecurityException("Not allowed to start activity "
                        + intent);
            case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
                throw new AndroidRuntimeException(
                        "FORWARD_RESULT_FLAG used while also requesting a result");
            case ActivityManager.START_NOT_ACTIVITY:
                throw new IllegalArgumentException(
                        "PendingIntent is not an activity");
            case ActivityManager.START_NOT_VOICE_COMPATIBLE:
                throw new SecurityException(
                        "Starting under voice control not allowed for: " + intent);
            case ActivityManager.START_VOICE_NOT_ACTIVE_SESSION:
                throw new IllegalStateException(
                        "Session calling startVoiceActivity does not match active session");
            case ActivityManager.START_VOICE_HIDDEN_SESSION:
                throw new IllegalStateException(
                        "Cannot start voice activity on a hidden session");
            case ActivityManager.START_ASSISTANT_NOT_ACTIVE_SESSION:
                throw new IllegalStateException(
                        "Session calling startAssistantActivity does not match active session");
            case ActivityManager.START_ASSISTANT_HIDDEN_SESSION:
                throw new IllegalStateException(
                        "Cannot start assistant activity on a hidden session");
            case ActivityManager.START_CANCELED:
                throw new AndroidRuntimeException("Activity could not be started for "
                        + intent);
            default:
                throw new AndroidRuntimeException("Unknown error code "
                        + res + " when starting " + intent);
        }
    }

system_service处理

对于 system_service 来说,它收到了启动 Activity 的请求,那么它要做的就是启动 TargetActivity 。
要实现这个目的,我整理了大概要做以下几件事:
1、解析请求参数
想要启动 Activity 最起码得知道具体是哪个 Activity 吧,当然还有其他很多参数,比如是谁发起的请求,requestCode等等,这些参数都是应用端带过来的。system_service 的第一件事肯定是解析这些参数,这些参数将被解析存放在一个叫 Request 对象中。
2、处理窗口层级树相关逻辑
虽然是启动 Activity ,但是肯定涉及到窗口操作,所以这一步也是必须的。
3、触发 SourceActivity 执行pause 逻辑,需要显示新的 TargetActivity ,那之前的 SourceActivity 肯定要执行 pause 逻辑的。
4、触发创建进程
当前场景是冷启动,那启动 TargetActivity 前必须要保证其所在的进程已经存在
在 Instrumentation::execStartActivity 里就开始触发跨进程通信了,剩下的逻辑就在 system_service 进程中执行了。

这部分缩略版的的调用链如下:

ActivityTaskManagerService::startActivity
    ActivityTaskManagerService::startActivityAsUser
        ActivityTaskManagerService::startActivityAsUser
            ActivityStartController::obtainStarter
                ActivityStarter::execute
                    ActivityStarter$Request::resolveActivity           -- 解析启动请求参数
                    ActivityStarter::executeRequest                    -- 3.3 创建ActivityRecord
                        ActivityStarter::startActivityUnchecked
                            ActivityStarter::startActivityInner        -- 3.4 关键函数startActivityInner
                                ActivityStarter::getOrCreateRootTask   -- 3.4.1 创建或者拿到Task                
                                ActivityStarter::setNewTask            -- 3.4.2 将Task与activityRecord 绑定
                                Task::moveToFront                       --3.4.3 移动Task到栈顶
                                RootWindowContainer::resumeFocusedTasksTopActivities    --3.4.4 显示Activity
                                    Task::resumeTopActivityUncheckedLocked
                                        Task::resumeTopActivityInnerLocked
                                            TaskFragment::resumeTopActivity      --  显示顶层Activity
                                                TaskDisplayArea::pauseBackTasks                   -- pause LauncherActivity 
                                                ActivityTaskManagerService::startProcessAsync     -- 创建“电话”进程

时序图:
在这里插入图片描述
流程来到 ActivityTaskManagerService::startActivity ,经过2次简单的跳转会执行 ActivityTaskManagerService::startActivityAsUser 方法。
这个方法比较重要,在这里会构建一个 ActivityStartController ,根据类名可以知道这个类是控制 Activity 启动。

启动请求参数的构建

# ActivityTaskManagerService

    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) {
            ......
            // 返回的是ActivityStartController
            return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setCallingFeatureId(callingFeatureId)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(bOptions)
                .setUserId(userId)
                .execute();
    }

    ActivityStartController getActivityStartController() {
        return mActivityStartController;
    }

ActivityStartController::obtainStarter 返回的是 ActivityStarter 对象。
而 ActivityStarter 这个类名看着就是处理启动 Activity 的一个类,它做的是就是解析调用者传递的参数,构建出一个 Request 然后开始执行后续的启动 Activity 逻辑。

# ActivityStartController
    // 返回ActivityStarter
    ActivityStarter obtainStarter(Intent intent, String reason) {
        return mFactory.obtain().setIntent(intent).setReason(reason);
    }

所以在 ActivityTaskManagerService::startActivityAsUser 方法中的 build 模式,其实是对 ActivityStarter 对象做构建,最终调用其 execute 方法。
在内容最终执行了 ActivityStarter::executeRequest 方法,下面只以 setCallingPackage 这一个方法看一下是怎么把参数设置到 Request 中的。

# ActivityStarter
    // 启动Activity的请求
    Request mRequest = new Request();
    // 设置调用者包名
    ActivityStarter setCallingPackage(String callingPackage) {
        mRequest.callingPackage = callingPackage;
        return this;
    }
    // 设置ActivityInfo
    ActivityStarter setActivityInfo(ActivityInfo info) {
        mRequest.activityInfo = info;
        return this;
    }
    int execute() {
        ......
        // 如果 mRequest 中没有 Activity 相关信息
        if (mRequest.activityInfo == null) {
            // 解析请求数据
            mRequest.resolveActivity(mSupervisor);
        }
        ......
        // 执行启动Activity请求
        res = executeRequest(mRequest);
        ......
    }

build 模式会把参数设置到 mRequest 中,但是并没有看到调用 ActivityStarter::setActivityInfo 所以在执行 ActivityStarter::execute 的时候 “mRequest.activityInfo”是 null 。
所以这里又分2步:

  1. 解析获取activityInfo
  2. 执行后续启动逻辑
ActivityStarter$Request

    ResolveInfo resolveInfo;
    ActivityInfo activityInfo;

    void resolveActivity(ActivityTaskSupervisor supervisor) {
        ......
            // 解析resolveInfo
            resolveInfo = supervisor.resolveIntent(intent, resolvedType, userId,
                0 /* matchFlags */,
                computeResolveFilterUid(callingUid, realCallingUid, filterCallingUid),
                realCallingPid);
            ......
            // 解析resolveInfo
            activityInfo = supervisor.resolveActivity(intent, resolveInfo, startFlags,
                    profilerInfo);
            ......
    }

activityInfo的解析

ActivityStarter$Request

    ResolveInfo resolveInfo;
    ActivityInfo activityInfo;

    void resolveActivity(ActivityTaskSupervisor supervisor) {
        ......
            // 解析resolveInfo
            resolveInfo = supervisor.resolveIntent(intent, resolvedType, userId,
                0 /* matchFlags */,
                computeResolveFilterUid(callingUid, realCallingUid, filterCallingUid),
                realCallingPid);
            ......
            // 解析resolveInfo
            activityInfo = supervisor.resolveActivity(intent, resolveInfo, startFlags,
                    profilerInfo);
            ......
    }

TargetActivity 所在的进程包名和 TargetActivity 的完整路径都在 activityInfo 中,这个解析方法也是一个核心点。

创建ActivityRecord

ActivityStarter::executeRequest 是一个需要注意的方法,因为内部会创建 ActivityRecord 对象,而这个 ActivityRecord 对象持有 token ,这个 token 就是以后分析其他逻辑一直会出现的 token 。也可以说是 system_service 中一个 Activity 的唯一标识。

应用进程中的 Activity 在 AMS 的代表就是 ActivityRecord 。

# ActivityStarter

  private int executeRequest(Request request) {
        ......
        // 包名在这
        ActivityInfo aInfo = request.activityInfo;
        ResolveInfo rInfo = request.resolveInfo;
        ......
        if (err == ActivityManager.START_SUCCESS) {
            // 重点* 1. 打印创建 ActivityRecord 日志
            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(")");
            }
        }
        ......
        // 重点* 2. 构造出一个ActivityRecord
        final ActivityRecord r = new ActivityRecord.Builder(mService)
                .setCaller(callerApp)
                .setLaunchedFromPid(callingPid)
                .setLaunchedFromUid(callingUid)
                .setLaunchedFromPackage(callingPackage)
                .setLaunchedFromFeature(callingFeatureId)
                .setIntent(intent)
                .setResolvedType(resolvedType)
                .setActivityInfo(aInfo)
                .setConfiguration(mService.getGlobalConfiguration())
                .setResultTo(resultRecord)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setComponentSpecified(request.componentSpecified)
                .setRootVoiceInteraction(voiceSession != null)
                .setActivityOptions(checkedOptions)
                .setSourceRecord(sourceRecord)
                .build();
        ......
        // 重点* 3. 继续执行startActivityUnchecked
        mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
                request.voiceInteractor, startFlags, true /* doResume */, checkedOptions,
                inTask, inTaskFragment, restrictedBgActivity, intentGrants);
        ......
  }

3个注意点:
1、虽然是个日志,但是也很关键,一般分析日志看启动了哪个 Activity 就搜“START u” ,打印的地方就在这。另外发现 U 版本上这一块还做了改变。
2、构建出一个 ActivityRecord 对象
3、继续执行主流程

主要看ActivityRecord 是怎么创建的:

# ActivityRecord
    private ActivityRecord(ActivityTaskManagerService _service, ......) {
            // 调用父类,创建 Token
            super(_service.mWindowManager, new Token(), TYPE_APPLICATION, true,
                null /* displayContent */, false /* ownerCanManageAppTokens */);
            ......
            packageName = info.applicationInfo.packageName;
            .....
        }

这里的重点其实就是创建了一个匿名 Token 然后传递到了父类的构建方法, ActivityRecord 的父类是 WindowToken。

# WindowToken

    protected WindowToken(WindowManagerService service, IBinder _token, int type,
            boolean persistOnEmpty, DisplayContent dc, boolean ownerCanManageAppTokens) {
        this(service, _token, type, persistOnEmpty, dc, ownerCanManageAppTokens,
                false /* roundedCornerOverlay */, false /* fromClientToken */, null /* options */);
    }

    protected WindowToken(WindowManagerService service, IBinder _token, int type,
            boolean persistOnEmpty, DisplayContent dc, boolean ownerCanManageAppTokens,
            boolean roundedCornerOverlay, boolean fromClientToken, @Nullable Bundle options) {
        super(service);
        // token 赋值
        token = _token;
        windowType = type;
        mOptions = options;
        ......
        if (dc != null) {
            // 挂载到窗口树,
            dc.addWindowToken(token, this);
        }
    }

将 ActivityRecord 创建的匿名 保存在了 token 对象,这个 token 就是 Activity 在 system_service 里唯一标识符。

普通的 WindowToken 在这里会挂载的窗口层级树,但是 DisplayContent::addWindowToken 方法内部对 ActivityRecord 做了判断。也就是说 ActivityRecord 刚创建好后是不会挂载到窗口树上的,当前流程后面是要介绍 ActivityRecord 是怎么挂载到层级树上的。

ActivityRecord 创建好后继续走主流程,根据前面的分析下一步是执行 ActivityStarter::startActivityUnchecked 不过这个方法也没做啥,主要是调用了 ActivityStarter::startActivityInner ,这个方法是流程的关键点。

窗口层级树的处理

ActivityStarter::startActivityInner 是 Activity 启动流程最重要的函数之一,这里涉及到【窗口层级树】相关知识,上一小节说了 ActivityRecord 创建好后并不会和 WindowToken 一样挂载到层级树中,而是需要单独处理,本小节就是看这一块是如何处理的。
先看看正常在 Launcher 界面时和启动“电话”后的层级树对比。

在这里插入图片描述
这里首先多了3个东西:
1、Task
2、上一步创建的 ActivityRecord
3、WindowState

另外这个 Task 还移动到了DefaultTaskDisplayArea的最顶部,这里涉及到的操作如下:
1、创建Task
2、ActivityRecord 挂在到这个 Task 下
3、将这个 Task 移动到最上面

至于最下面的那个 546fce2 为什么是 WindowState 对象,又是怎么挂在到 ActivityRecord 上的,这个属于窗口显示第一步,后边再说。

继续主流程代码:

# ActivityStarter

    // The task that the last activity was started into. We currently reset the actual start
    // activity's task and as a result may not have a reference to the task in all cases
    private Task mTargetTask;

    int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, Task inTask,
            TaskFragment inTaskFragment, boolean restrictedBgActivity,
            NeededUriGrants intentGrants) {
            ......
            // computeTargetTask内部会根据具体条件返回Task(比如标志位FLAG_ACTIVITY_NEW_TASK 就需要重新创建Task   )
            // 这里reusedTask为 null,因为是新启动的应用,所以computeTargetTask也找不到task,最终也为null
            
            final Task targetTask = reusedTask != null ? reusedTask : computeTargetTask();
            // 那么newTask为true, 表示需要新建一个task
            final boolean newTask = targetTask == null;
            // 同样为null
            mTargetTask = targetTask;
            ......
            if (mTargetRootTask == null) {
                // 重点* 1. 创建Task   23
                mTargetRootTask = getOrCreateRootTask(mStartActivity, mLaunchFlags, targetTask,
                        mOptions);
            }
            if (newTask) {
                // taskToAffiliate 为null
                final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
                        ? mSourceRecord.getTask() : null;
                // 重点* 2. 将需要启动的ActivityRecord与 新创建的Task 进行绑定
                setNewTask(taskToAffiliate);
            } else if (mAddingToTask) {
                addOrReparentStartingActivity(targetTask, "adding to task");
            }

            if (!mAvoidMoveToFront && mDoResume) {
                // 重点* 3. 移动到栈顶 
                mTargetRootTask.getRootTask().moveToFront("reuseOrNewTask", targetTask);
                ......
            }
            ......
            if (mDoResume) {
                ......
                // 重点*4. task 处理完后,需要将task顶部的Activity显示(resume) 
                // mTransientLaunch 一般为默认值 false
                mRootWindowContainer.resumeFocusedTasksTopActivities(
                        mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);
            }
            ......
        }
  1. 创建 Task
    • 我们知道 ActivityRecord 需要挂载到一个 Task 下,虽然这里调用的方法名是 getOrCreateRootTask(获取或者创建Task),但是当前场景肯定是创建一个,热启动是获取。
    • 另外 Task 创建的时候就会挂载到层级树中,也就是会挂载到DefaultTaskDisplayArea 下
  2. 将 ActivityRecord 挂载到创建的 Task 下
    • 上一小节没做的事,在这里就完成了挂载
  3. 移动 Task 到栈顶
    • 因为这个新启动的 Activity 需要显示,所以需要将它所在的 Task 移到容器顶部。 不过当前场景建好就已经是栈顶了,其实这一步没做什么,这点后面代码会分析
  4. 显示顶部的 Activity
    • 窗口层级的处理好了,就可以处理显示逻辑了,这里后续的逻辑会触发 Activity 的启动

获取Task–getOrCreateRootTask

调用链

ActivityStarter::getOrCreateRootTask
    RootWindowContainer::getOrCreateRootTask
        RootWindowContainer::getOrCreateRootTask
            TaskDisplayArea::getOrCreateRootTask
                TaskDisplayArea::getOrCreateRootTask
                    Task::Build     ---创建Task

代码:

# ActivityStarter
    private Task getOrCreateRootTask(ActivityRecord r, int launchFlags, Task task,
            ActivityOptions aOptions) {
        final boolean onTop =
                (aOptions == null || !aOptions.getAvoidMoveToFront()) && !mLaunchTaskBehind;
        final Task sourceTask = mSourceRecord != null ? mSourceRecord.getTask() : null;
        return mRootWindowContainer.getOrCreateRootTask(r, aOptions, task, sourceTask, onTop,
                mLaunchParams, launchFlags);
    }

1、onTop 表示是否要移到到当前栈顶,那肯定是要的,新启动的 Activity 当前要在最上面,这里 aOptions 为 null ,所以为 true
2、sourceTask 表示从哪里启动的,当前 Launcher 所在的 Task 就是 sourceTask

然后开始获取一个 Task 如果没有就新建一个。

# RootWindowContainer
    Task getOrCreateRootTask(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
            @Nullable Task candidateTask, boolean onTop) {
        return getOrCreateRootTask(r, options, candidateTask, null /* sourceTask */, onTop,
                null /* launchParams */, 0 /* launchFlags */);
    }
    Task getOrCreateRootTask(@Nullable ActivityRecord r,
            @Nullable ActivityOptions options, @Nullable Task candidateTask,
            @Nullable Task sourceTask, boolean onTop,
            @Nullable LaunchParamsController.LaunchParams launchParams, int launchFlags) {
            ......
            final int activityType = resolveActivityType(r, options, candidateTask);
            if (taskDisplayArea != null) {
                if (canLaunchOnDisplay(r, taskDisplayArea.getDisplayId())) {
                    // 重点*1. 传递到TaskDisplayArea
                    return taskDisplayArea.getOrCreateRootTask(r, options, candidateTask,
                            sourceTask, launchParams, launchFlags, activityType, onTop);
                } else {
                    taskDisplayArea = null;
                }
            }
            ......
    }

经过同名方法调用后,逻辑进入到 TaskDisplayArea::getOrCreateRootTask 。

# TaskDisplayArea
    Task getOrCreateRootTask(int windowingMode, int activityType, boolean onTop,
            @Nullable Task candidateTask, @Nullable Task sourceTask,
            @Nullable ActivityOptions options, int launchFlags) {
            if(....) {
                // 拿到之前创建的Task
                return candidateTask.getRootTask();
            }
            ......// 第一次显示所以是新建Task
            return new Task.Builder(mAtmService)
                .setWindowingMode(windowingMode)
                .setActivityType(activityType)
                .setOnTop(onTop)
                .setParent(this)  // 主要这个this被设置为Parent。所以直接挂载到了DefaultTaskDisplayArea下
                .setSourceTask(sourceTask)
                .setActivityOptions(options)
                .setLaunchFlags(launchFlags)
                .build();
    }

看方法名是获取或创建 Task ,当前流程是新启动的 Activity 所以需要创建 Task 。如果是以默认启动方式打开应用内的另一个 Activity ,就走的是上面的 “return candidateTask.getRootTask();”

接下来就是真正触发Task的创建:

# Task
    # Task.Builder
        Task build() {
            if (mParent != null && mParent instanceof TaskDisplayArea) {
                validateRootTask((TaskDisplayArea) mParent);
            }

            ......
            // 重点* 1. 创建task
            final Task task = buildInner();
            task.mHasBeenVisible = mHasBeenVisible;

            // Set activity type before adding the root task to TaskDisplayArea, so home task can
            // be cached, see TaskDisplayArea#addRootTaskReferenceIfNeeded().
            if (mActivityType != ACTIVITY_TYPE_UNDEFINED) {
                task.setActivityType(mActivityType);
            }
            // 重点* 2. 入栈 这里的 mOnTop 为true
            if (mParent != null) {
                if (mParent instanceof Task) {
                    final Task parentTask = (Task) mParent;
                    parentTask.addChild(task, mOnTop ? POSITION_TOP : POSITION_BOTTOM,
                            (mActivityInfo.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
                } else {
                    mParent.addChild(task, mOnTop ? POSITION_TOP : POSITION_BOTTOM);
                }
            }

            // Set windowing mode after attached to display area or it abort silently.
            if (mWindowingMode != WINDOWING_MODE_UNDEFINED) {
                task.setWindowingMode(mWindowingMode, true /* creating */);
            }
            // 返回
            return task;
        }

        // 创建
        Task buildInner() {
            return new Task(mAtmService, mTaskId, mIntent, mAffinityIntent, mAffinity,
                    mRootAffinity, mRealActivity, mOrigActivity, mRootWasReset, mAutoRemoveRecents,
                    mAskedCompatMode, mUserId, mEffectiveUid, mLastDescription, mLastTimeMoved,
                    mNeverRelinquishIdentity, mLastTaskDescription, mLastSnapshotData,
                    mTaskAffiliation, mPrevAffiliateTaskId, mNextAffiliateTaskId, mCallingUid,
                    mCallingPackage, mCallingFeatureId, mResizeMode, mSupportsPictureInPicture,
                    mRealActivitySuspended, mUserSetupComplete, mMinWidth, mMinHeight,
                    mActivityInfo, mVoiceSession, mVoiceInteractor, mCreatedByOrganizer,
                    mLaunchCookie, mDeferTaskAppear, mRemoveWithTaskOrganizer);
        }

小结:
最后描述一下最后创建的2个重点部分:
1、看到通过 buildInner 创建了一个 Task,而 buildInner 也很简单粗暴,通过各个变量直接 new 出一个 Task 对象。
2、mParent 不为 null ,是因为在创建的时候 setParent(this),当前的这个 this 就是 getDefaultTaskDisplayArea 返回的。就是 37层的第二层应用 Activity 存在的"DefaultTaskDisplayArea"

在 RootWindowContainer::getOrCreateRootTask 体现。
在这里插入图片描述
注意 log 里的 #17 的这个 Task 与前面的层级结构树新增的 Task 是对应的上的。而且"this= DefaultTaskDisplayArea "说明也确实是往 DefaultTaskDisplayArea 里添加了。
另外 log 里 index 为3,结合最上面的前后对比,说明也的往顶部添加。

ActivityRecord挂载到Task–setNewTask

# ActivityStarer

    private void setNewTask(Task taskToAffiliate) {
        // 为true
        final boolean toTop = !mLaunchTaskBehind && !mAvoidMoveToFront;
        // 就是mTargetRootTask,也就是刚刚创建的Task
        final Task task = mTargetRootTask.reuseOrCreateTask(
                mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
                mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
                mVoiceInteractor, toTop, mStartActivity, mSourceRecord, mOptions);
        task.mTransitionController.collectExistenceChange(task);
        // ActivityRecord的挂载
        addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask");
        // 需要注意这里的日志打印
        ProtoLog.v(WM_DEBUG_TASKS, "Starting new activity %s in new task %s",
                mStartActivity, mStartActivity.getTask());

        // mLaunchTaskBehind 为false,所以taskToAffiliate 为null 
        if (taskToAffiliate != null) {
            mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
        }
    }

这里的 Task 和 mTargetRootTask 是同一个对象,然后进入 ActivityStarer::addOrReparentStartingActivity 。

# ActivityStarer

    private void addOrReparentStartingActivity(@NonNull Task task, String reason) {
        //  newParent = task 都是刚刚创建的Task
        TaskFragment newParent = task;
        ......
        if (mStartActivity.getTaskFragment() == null
                || mStartActivity.getTaskFragment() == newParent) {
            // 重点, 将 ActivityRecord挂在到新创建的Task中,并且是顶部
            newParent.addChild(mStartActivity, POSITION_TOP);
        } else {
            mStartActivity.reparent(newParent, newParent.getChildCount() /* top */, reason);
        }
    }

这里的逻辑涉及到的 Task 就是上一步创建的 Task ,而 mStartActivity 则是“电话”在之前逻辑创建的 ActivityRecord。

setNewTask的堆栈信息如下:
在这里插入图片描述
另外这段逻辑里有个 ProtoLog 打印,日志如下:
在这里插入图片描述
结合逻辑分析 + 堆栈信息 + ProtoLog ,可以确认 ActivityStarer::setNewTask 做的事情就是将 ActivityRecord 挂在到 Task 中,而且在顶部。

移动Task到容器顶部–moveToFront

这里提一下这个 moveToFront 方法,因为前面创建 Task 并添加到 DefaultTaskDisplayArea 时是往顶部添加,后面将 ActivityRecord 挂在到 Task 也是挂在到其顶部。所以这个函数其实没有什么实际操作。但是对于其他场景,这里也是一个重点方法。

Task::moveToFront
    Task::moveToFrontInner
        TaskDisplayArea::positionChildAt
            TaskDisplayArea::positionChildTaskAt
                ActivityTaskSupervisor::updateTopResumedActivityIfNeeded
                    ActivityRecord::onTopResumedActivityChanged      --触发TopResumedActivityChangeItem

首先确定一个问题:需要移动到顶部的是哪个 Task ? 这个 Task 所在的是在哪个哪个容器? 在 ActivityStarter::startActivityInner 的时候调用的是这段代码:

// targetTask 当前场景为null
mTargetRootTask.getRootTask().moveToFront("reuseOrNewTask", targetTask);

已知 mTargetRootTask 是新创建给“电话”用的 Task, 而 mTargetRootTask.getRootTask() 返回值当前场景是 mTargetRootTask 本身。

# Task

    void moveToFront(String reason, Task task) {
        if (!isAttached()) {
            return;
        }
        mTransitionController.recordTaskOrder(this);

        final TaskDisplayArea taskDisplayArea = getDisplayArea();

        if (!isActivityTypeHome() && returnsToHomeRootTask()) {
            // Make sure the root home task is behind this root task since that is where we
            // should return to when this root task is no longer visible.
            taskDisplayArea.moveHomeRootTaskToFront(reason + " returnToHome");
        }

        final Task lastFocusedTask = isRootTask() ? taskDisplayArea.getFocusedRootTask() : null;
        if (task == null) {
            // 当前场景为null,所以会赋值成新建的 Task ,也就是 mTargetRootTask 也就是电话的 Task
            task = this;
        }
        // 这里调用 getParent 就是 DefaultTaskDisplayArea 了。
        // 把当前的 Task 移动到 DefaultTaskDisplayArea 的最前面
        task.getParent().positionChildAt(POSITION_TOP, task, true /* includingParents */);
        taskDisplayArea.updateLastFocusedRootTask(lastFocusedTask, reason);
    }

再回答一下问题:移动的是新建的电话 Task ,它的父容器是 DefaultTaskDisplayArea ,所以是把这个 Task 移动到 DefaultTaskDisplayArea 的最前面。

mTargetRootTask.getRootTask 返回的是顶部的 Task, 当前 Task 上一层是 TaskDisplayArea 类型 (name为DefaultTaskDisplayArea)

而 mTargetRootTask.getParent 返回的父容器(不限制是 Task),则是 name 为 DefaultTaskDisplayArea 的 TaskDisplayArea。
getRootTask 和 getParent 的区别可以自行去源码中看看

到这里,AMS已经将需要的 ActivityRecord 和 Task 创建并且挂载到层级树中,接下来将是需要处理 TargetActivity 启动和显示逻辑了

显示Activity–resumeFocusedTasksTopActivities

首先看方法名目的需要显示一个栈顶的 Activity ,那说的不就是 TargetActivity 嘛,TargetActivity 的 ActivityRecord 已经创建并且移动到栈顶了。
前面该做的也都做好了,现在也确实是时候处理显示逻辑,这部分流程由 RootWindowContainer::resumeFocusedTasksTopActivities 执行,调用链如下:

RootWindowContainer::resumeFocusedTasksTopActivities
    Task::resumeTopActivityUncheckedLocked
        Task::resumeTopActivityInnerLocked
            TaskFragment::resumeTopActivity 
                TaskDisplayArea::pauseBackTasks  --   pause LauncherActivity 
                    WindowContainer::forAllLeafTask
                        TaskFragment::forAllLeafTaskFragments
                            TaskFragment::startPausing
                                TaskFragment::startPausing
                                    TaskFragment::schedulePauseActivity --构建 PauseActivityItem,这里是触发暂停launch
                ActivityTaskManagerService::startProcessAsync     -- 创建“电话”进程

重点方法在 TaskFragment::resumeTopActivity 开始处理,先简单看一下前面的调用是怎么样的。

# RootWindowContainer
    // 第四个参数为 false
    boolean resumeFocusedTasksTopActivities(
            Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions,
            boolean deferPause) {
                ......
                if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea()
                        || getTopDisplayFocusedRootTask() == targetRootTask)) {
                    
                    result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions,
                            deferPause);
                }
                ......
            }
# Task
    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options,
            boolean deferPause) {
                ......
                if (isLeafTask()) {
                    if (isFocusableAndVisible()) {
                        someActivityResumed = resumeTopActivityInnerLocked(prev, options, deferPause);
                    }
                }
                ......
            }

    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options,
            boolean deferPause) {
                ......
                // deferPause = false
                resumed[0] = topFragment.resumeTopActivity(prev, options, deferPause);
                ......
            }

TaskFragment::resumeTopActivity 方法是 FrameWork 中非常常见的一个方法,方法名和它的功能是一样的:显示顶层 Activity 。
抛开多窗口场景,设备上显示 Activity 的逻辑就是显示 DefaultTaskDisplayArea 下的顶层 Task 中的顶层 Activity ,代码流程有很多场景都可能会导致屏幕显示内容的修改,也就需要执行当前方法来确保屏幕上有一个正确的 Activity 显示。
以后会经常看到这个方法,当前还是只分析 Launcher 启动“电话”的场景来看看执行逻辑。

# TaskFragment

    final boolean resumeTopActivity(ActivityRecord prev, ActivityOptions options,
            boolean deferPause) {
                // 这里的next返回的是电话的 MainActivity,表示下一个需要显示的Activity
                ActivityRecord next = topRunningActivity(true /* focusableOnly */);
                ......
                // 如果跳过的这些逻辑都没执行return,则正在开始执行 resume 流程,打印关键日志。    
                // 前面流程如果返回也有日志的打印
                // 打印日志,需要显示哪个Activity
                if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);
                ......
                // 重点* 1. 这里会将 Launcher 的Activity pause 。参数是电话的 ActivityRecord
                // 注意 1:如果有 Activity 被 pauseBackTasks 方法触发了 pause,则返回 true,表示有 Activity 正在 pausing
                boolean pausing = !deferPause && taskDisplayArea.pauseBackTasks(next);
                ......
                if (pausing) {
                    ProtoLog.v(WM_DEBUG_STATES, "resumeTopActivity: Skip resume: need to"+ " start pausing");
                    if (next.attachedToProcess()) {
                        ......
                    } else if (!next.isProcessRunning()) {
                        // 重点*2. 进程没有运行,则触发异步创建进程。 当前逻辑肯定是执行这一条
                        final boolean isTop = this == taskDisplayArea.getFocusedRootTask();
                        mAtmService.startProcessAsync(next, false /* knownToBeDead */, isTop,
                            isTop ? HostingRecord.HOSTING_TYPE_NEXT_TOP_ACTIVITY
                                    : HostingRecord.HOSTING_TYPE_NEXT_ACTIVITY);
                    }
                    ......
                    // 注意2:这里会return
                    return true;
                } else if ......
                ......//后面还有重要逻辑,当前可忽略   
            }

上面说过这个函数非常复杂,在当前逻辑有2个主线:

  1. pause 当前 Activity 也就是 Launcher
  2. 异步创建“电话”的进程

在第一步将 Launcher 的 Activity 执行 pause ,这一步执行到最后也会触发"电话"应用 MainActivity 的启动。
第二步创建“电话”进程,进程创建完肯定也会执行"电话"应用 MainActivity 的启动,这么看来就有2个地方触发了。
这是因为是异步创建进程,不知道谁先执行完,但是可以明确的是,"电话"应用 MainActivity 必须有2个条件:

  1. 前一个Activity执行完pause
  2. 进程创建完成

所以无论2个分支哪一个先执行完,都需要等后一个执行完的来触发后续电话"应用 MainActivity 的启动。 这个方法还有2个需要注意的地方:

变量 pausing 表示当前是否正在执行 Activity 的 pause 流程。这个值受2个因素影响,先看 Launcher 的 pause 流程。

pause 流程–pauseBackTasks

需要显示新的 Activity 那之前的 Activity 肯定是要执行 pause ,参数 next 为“电话”的 ActivityRecord 。 这一步主要是触发 SourceActivity 的pause 逻辑。

# TaskDisplayArea

    // 可以看到“电话”ActivityRecord在这里就被称为resuming
    boolean pauseBackTasks(ActivityRecord resuming) {
        final int[] someActivityPaused = {0};
        forAllLeafTasks(leafTask -> {
            // Check if the direct child resumed activity in the leaf task needed to be paused if
            // the leaf task is not a leaf task fragment.
            if (!leafTask.isLeafTaskFragment()) {
                // 当前不会走这里
                ......
            }

            leafTask.forAllLeafTaskFragments((taskFrag) -> {
                final ActivityRecord resumedActivity = taskFrag.getResumedActivity();
                if (resumedActivity != null && !taskFrag.canBeResumed(resuming)) {
                    if (taskFrag.startPausing(false /* uiSleeping*/, resuming, "pauseBackTasks")) {
                        someActivityPaused[0]++;
                    }
                }
            }, true /* traverseTopToBottom */);
        }, true /* traverseTopToBottom */);
        return someActivityPaused[0] > 0;
    }

forAllLeafTasks 和 forAllLeafTaskFragments 在WMS/AMS 常见方法调用提取有解释,那么当前这段方法其实就是让 DefaultTaskDisplayArea 下的每个叶子 LeafTaskFragments 执行 startPausing 。

# TaskFragment

    boolean startPausing(boolean userLeaving, boolean uiSleeping, ActivityRecord resuming,
            String reason) {
        ......
        // 日志输出当前 TaskFragment 和 mResumedActivity 的关系。后面会贴上日志证明
        // 注意这里的是需要 pause 的,不是需要 resume 的
        ProtoLog.d(WM_DEBUG_STATES, "startPausing: taskFrag =%s " + "mResumedActivity=%s", this,
                mResumedActivity);
        ......
        // 后面的prev就是launcher的ActivityRecord了
        ActivityRecord prev = mResumedActivity;
        ......
        // 输出日志
        ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSING: %s", prev);
        mPausingActivity = prev;
        ......
        // 设置window状态为PAUSING
        prev.setState(PAUSING, "startPausingLocked");
        prev.getTask().touchActiveTime();
        ......
        if (prev.attachedToProcess()) {
            // launcher的进程肯定是满足启动条件的
            if (shouldAutoPip) {
                // 当前场景与画中画模式无关,不走这
                boolean didAutoPip = mAtmService.enterPictureInPictureMode(
                        prev, prev.pictureInPictureArgs);
                ProtoLog.d(WM_DEBUG_STATES, "Auto-PIP allowed, entering PIP mode "
                        + "directly: %s, didAutoPip: %b", prev, didAutoPip);
            } else {
                // 重点*1. 上面的PIP日志没输出,肯定走的是这
                schedulePauseActivity(prev, userLeaving, pauseImmediately,
                        false /* autoEnteringPip */, reason);
            }
        }
        ......
    }

    void schedulePauseActivity(ActivityRecord prev, boolean userLeaving,
            boolean pauseImmediately, boolean autoEnteringPip, String reason) {
        // 输出日志
        ProtoLog.v(WM_DEBUG_STATES, "Enqueueing pending pause: %s", prev);
        try {
            // 输出events 日志
            EventLogTags.writeWmPauseActivity(prev.mUserId, System.identityHashCode(prev),
                    prev.shortComponentName, "userLeaving=" + userLeaving, reason);
            // 重点* 构建并执行PauseActivityItem
            mAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
                    prev.token, PauseActivityItem.obtain(prev.finishing, userLeaving,
                            prev.configChangeFlags, pauseImmediately, autoEnteringPip));
        } catch (Exception e) {
            ......
        }
    }

最终在 TaskFragment::schedulePauseActivity 构建 PauseActivityItem 并执行了 Launcher 的 pause 事件。

这块相关的日志输入如图:

在这里插入图片描述

PauseActivityItem

触发 pause 流程就是通过 PauseActivityItem 这个触发的。

# PauseActivityItem

    @Override
    public void execute(ClientTransactionHandler client, ActivityClientRecord r,
            PendingTransactionActions pendingActions) {
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
        // 重点*1. 触发 handlePauseActivity 流程
        client.handlePauseActivity(r, mFinished, mUserLeaving, mConfigChanges, pendingActions,
                "PAUSE_ACTIVITY_ITEM");
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }

    @Override
    public int getTargetState() {
        return ON_PAUSE;
    }
    //  pauser执行后调用 postExecute
    @Override
    public void postExecute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        if (mDontReport) {
            return;
        }
        //  重点*2. 触发启动新的Activity
        ActivityClient.getInstance().activityPaused(token);
    }


这里先执行 execute 方法也就是 Launcher 的 pause 流程,这个不是主线,可以移步Activity生命周期之onPause。

然后执行 postExecute,这里会触发新 Activity 的启动,这个流程就是阶段二。

# ActivityClient

    public void activityPaused(IBinder token) {
        try {
            getActivityClientController().activityPaused(token);
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
    }

阶段一总结

本篇对整个 Activity 启动流程做了介绍,然后重点分析第一阶段的事情,这一阶段的二级框图如下:
在这里插入图片描述
1、在 Launcher 进程构建了启动参数放在了 ActivityOption 中,然后通过 Bundle 传递给 system_service 端

2、AMS 先解析参数,放在了 Request 这个类中保存

3、AMS 构建出一个 ActivityRecord ,这个类在 system_service 端就代表着 Activity ,同时也是一个窗口容器

4、再构建出一个 Task 挂载到窗口树上

5、将 ActivityRecord 挂载到 Task 中,这样 ActivityRecord 也就挂载到窗口层级树中了

6、触发 Launcher 执行 pause 逻辑,也就是阶段二

7、触发 TargetActivity 所在的进程创建,也就是阶段三

system_service 处理的完整堆栈

ActivityTaskManagerService::startActivity
    ActivityTaskManagerService::startActivityAsUser
        ActivityTaskManagerService::startActivityAsUser
            ActivityStartController::obtainStarter
                ActivityStarter::execute
                    ActivityStarter$Request::resolveActivity           -- 解析启动请求参数
                        ActivityTaskSupervisor::resolveIntent
                        ActivityTaskSupervisor::resolveActivity
                    ActivityStarter::executeRequest                    -- 3.3 创建ActivityRecord
                        ActivityStarter::startActivityUnchecked
                            ActivityStarter::startActivityInner        -- 3.4 关键函数startActivityInner
                                ActivityStarter::getOrCreateRootTask   -- 3.4.1 创建或者拿到Task
                                    RootWindowContainer::getOrCreateRootTask
                                        RootWindowContainer::getOrCreateRootTask
                                            TaskDisplayArea::getOrCreateRootTask
                                                TaskDisplayArea::getOrCreateRootTask
                                                    Task::Build     ---创建Task                    
                                ActivityStarter::setNewTask            -- 3.4.2Task与activityRecord 绑定
                                    ActivityStarer::addOrReparentStartingActivity
                                Task::moveToFront                       --3.4.3 移动Task到栈顶
                                    Task::moveToFrontInner
                                        TaskDisplayArea::positionChildAt
                                            TaskDisplayArea::positionChildTaskAt
                                                ActivityTaskSupervisor::updateTopResumedActivityIfNeeded
                                                    ActivityRecord::onTopResumedActivityChanged      --触发TopResumedActivityChangeItem
                                RootWindowContainer::resumeFocusedTasksTopActivities    --3.4.4 显示Activity
                                    Task::resumeTopActivityUncheckedLocked
                                        Task::resumeTopActivityInnerLocked
                                            TaskFragment::resumeTopActivity      -- 1. 显示顶层Activity
                                                TaskDisplayArea::pauseBackTasks  -- 1.2 pause LauncherActivity 
                                                    WindowContainer::forAllLeafTask
                                                        TaskFragment::forAllLeafTaskFragments
                                                            TaskFragment::startPausing
                                                                TaskFragment::startPausing
                                                                    TaskFragment::schedulePauseActivity --构建 PauseActivityItem,这里是触发暂停launch
                                                ActivityTaskManagerService::startProcessAsync     -- 1.3 创建“电话”进程

第二阶段–completePause

应用完成 Pause 会执行 ActivityClientController::activityPaused 来通知 system_service 当前分析主流程继续看 completePause 的后续逻辑,这部分调用链如下:

ActivityClientController::activityPaused
    ActivityRecord::activityPaused
        TaskFragment::completePause
            RootWindowContainer::resumeFocusedTasksTopActivities       -- 显示顶层Activity
                RootWindowContainer::resumeFocusedTasksTopActivities
                    Task::resumeTopActivityUncheckedLocked
                        Task::resumeTopActivityInnerLocked
                            TaskFragment::resumeTopActivity
                                ActivityTaskSupervisor::startSpecificActivity        -- 试图启动 Activity
            RootWindowContainer::ensureActivitiesVisible              -- 确保设备上 Activity 的可见性
                RootWindowContainer::ensureActivitiesVisible
                    DisplayContent::ensureActivitiesVisible 
                        WindowContainer::forAllRootTasks  --忽略固定逻辑
                            Task::ensureActivitiesVisible
                                Task::forAllLeafTasks --忽略固定逻辑
                                    TaskFragment::updateActivityVisibilities
                                        EnsureActivitiesVisibleHelper::process
                                            EnsureActivitiesVisibleHelper::setActivityVisibilityState
                                                EnsureActivitiesVisibleHelper::makeVisibleAndRestartIfNeeded
                                                    ActivityTaskSupervisor::startSpecificActivity       -- 试图启动 Activity

之前看了第一阶段的窗口图:
在这里插入图片描述
冷启动的目标肯定是希望最后显示的是 TargetActivity ,也就是下面这图的状态:
在这里插入图片描述
其实在 system_service 这边的 DefaultTaskDisplayArea 并没有变化,只是用户看到的 Activity 变成了 TargetActivity 。
要实现这个最终状态就是需要目标应用端创建 TargetActivity 。而要触发这一步骤是2个条件就是:

  • 其他Activity完成pause
  • TargetActivity进程在运行

所以现在看到的阶段二就一直在试图来启动 TargetActivity ,这一阶段的大概流程图如下:
在这里插入图片描述

可以看到对应代码 TaskFragment::completePause 后有2个流程都试图执行 ActivityTaskSupervisor::startSpecificActivity 来启动 TargetActivity。

  • 如果在 resumeFocusedTasksTopActivities 流程的时候进程启动了,则会走完触发 TargetActivity 的启动逻辑。如果进程还未启动,则会在 startSpecificActivity 方法里触发一下创建进程
  • resumeFocusedTasksTopActivities 流程执行完后会执行 ensureActivitiesVisible 流程来遍历整个手机系统的所有 Activity 处理他们的可见性,如果这个时候发现顶层 Activity 的ActivityRecord::attachedToProcess 返回false,则又会执行到 startSpecificActivity 。否则会根据具体情况处理一下其可见性。

理论知识建设完毕,下面来说跟代码,从 ActivityRecord::activityPaused 方法开始。

ActivityRecord::activityPaused

# ActivityRecord
    void activityPaused(boolean timeout) {
        ......
            if (pausingActivity == this) {
                // 打印日志
                ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSED: %s %s", this,
                        (timeout ? "(due to timeout)" : " (pause complete)"));
                mAtmService.deferWindowLayout();
                try {
                    // 注意2个产出
                    taskFragment.completePause(true /* resumeNext */, null /* resumingActivity */);
                } finally {
                    mAtmService.continueWindowLayout();
                }
                return;
            } else ......
        ......
    }

流程来到 TaskFragment::completePause ,注意传递过来的参数分别为 true 和 null 。

# TaskFragment
    @VisibleForTesting
    void completePause(boolean resumeNext, ActivityRecord resuming) {
        // 拿到之前的Activity,也就是需要 pause 的
        ActivityRecord prev = mPausingActivity;
        ProtoLog.v(WM_DEBUG_STATES, "Complete pause: %s", prev);
        if (prev != null) {
            ......
            // 设置 SourceActivity 对应的ActivityRecord 状态为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. 第1个分支
                mRootWindowContainer.resumeFocusedTasksTopActivities(topRootTask, prev,
                        null /* targetOptions */);
                ......
            } else {......}
            ......
            // 重点*2. 确保设置所有Activity正确的可见性,注意是3个参数的,且第一个参数为null
            mRootWindowContainer.ensureActivitiesVisible(resuming, 0, !PRESERVE_WINDOWS);
            ......
        }
    }

这里的 topRootTask 就是 SourceActivity “电话”的 Activity, prev 是 launcher 的 ActivityRecord , resuming 为null。 这里又分为2步走了。

第一步–resumeFocusedTasksTopActivities

执行过来的流程是上一个 Activity 完成了 pause ,那说明需要显示一个新的 Activity ,显示哪个呢?
自然是最前面的 Task 下的 最前面的 Activity ,下面看看代码中是如何实现这一步的。
直接的调用链之前看过了,所有直接看 TaskFragment::resumeTopActivity 方法,这个方法之前也看过,但是这次的逻辑肯定不一样了。

# TaskFragment

    final boolean resumeTopActivity(ActivityRecord prev, ActivityOptions options,
            boolean deferPause) {
                ......
                // 这一次没有要 pause 的Activity了,所以为false
                boolean pausing = !deferPause && taskDisplayArea.pauseBackTasks(next);
                ......
                if (pausing) {
                    ......
                    return true;
                }
                ......
                // ActivityRecord 下的 app 变量是否有值,并且进程已经执行
                if (next.attachedToProcess()) {
                    if (DEBUG_SWITCH) {
                        // 日志
                        Slog.v(TAG_SWITCH, "Resume running: " + next + " stopped=" + next.mAppStopped
                                    + " visibleRequested=" + next.isVisibleRequested());
                    }
                    ......
                } else {
                    ......
                    // 打印log
                    ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Restarting %s", next);
                    // 重点* 执行startSpecificActivity 
                    mTaskSupervisor.startSpecificActivity(next, true, true);
                    ......
                }
                return true;
            }

这一次执行 TaskFragment::resumeTopActivity 方法和之前还说有区别的,首先由于这一次没有要 pause 的 Activity 了,所以 pausing = false ,也就不会走 “if (pausing)” 内部逻辑。
走的是下面的 ActivityTaskSupervisor::startSpecificActivity 试图启动 TargetActivity ,至于最后是不是真的能启动,还是要看进程起来没。

这一步会打印日志:
WindowManager: resumeTopActivity: Restarting ActivityRecord{1cf0e8 u0 com.google.android.apps.messaging/.ui.ConversationListActivity t30}

关键方法–startSpecificActivity

这个方法已经提过多次了,简单说目的是想去让应用端启动 Activity ,但是如果可能应用端进程还没创建,就会触发进程创建。

# ActivityTaskSupervisor

    final ActivityTaskManagerService mService;

    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;
        // 重点* 1. 进程是否存在,且主线程已执行
        if (wpc != null && wpc.hasThread()) {
            try {
                // 进程存在 则执行 realStartActivityLocked 流程
                realStartActivityLocked(r, wpc, andResume, checkConfig);
                // 重点* 会返回
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity "
                        + r.intent.getComponent().flattenToShortString(), e);1111111111
            }
            ......
        }
        ......
        // 重点* 2. 触发启动进程
        mService.startProcessAsync(r, knownToBeDead, isTop,
                isTop ? HostingRecord.HOSTING_TYPE_TOP_ACTIVITY
                        : HostingRecord.HOSTING_TYPE_ACTIVITY);
    }

以当前分析的条件,肯定又是触发进程创建了,所以 ActivityTaskSupervisor::realStartActivityLocked 暂时就先不看了。

第二步–ensureActivitiesVisible 流程

前面看了 resumeFocusedTasksTopActivities 的流程,挺简单的,目前暂且假设因为进程没启动,所以没有触发 TargetActivity 的启动,现在继续看 ensureActivitiesVisible 流程。
这个方法的目的之前也说过了,就是确保一下手机上所有的 Activity 的正确可见性,也就是遍历所有 Task 下的所有 ActivityRecord 然后根据对应的条件处理想要的可见性。

# RootWindowContainer
    // starting = null  configChanges = 0  preserveWindows = false
    void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
            boolean preserveWindows) {
        ensureActivitiesVisible(starting, configChanges, preserveWindows, true /* notifyClients */);
    }

    void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
            boolean preserveWindows, boolean notifyClients) {
        // 已经正常处理可见性就不重复执行了
        if (mTaskSupervisor.inActivityVisibilityUpdate()
                || mTaskSupervisor.isRootVisibilityUpdateDeferred()) {
            // Don't do recursive work.
            return;
        }

        try {
            // 开始处理
            mTaskSupervisor.beginActivityVisibilityUpdate();
            // First the front root tasks. In case any are not fullscreen and are in front of home.
            // 遍历屏幕
            for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
                final DisplayContent display = getChildAt(displayNdx);
                display.ensureActivitiesVisible(starting, configChanges, preserveWindows,
                        notifyClients);
            }
        } finally {
            // 处理结束
            mTaskSupervisor.endActivityVisibilityUpdate();
        }
    }

遍历所有屏幕

# DisplayContent

    void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
            boolean preserveWindows, boolean notifyClients) {
        ......
        mInEnsureActivitiesVisible = true;
        mAtmService.mTaskSupervisor.beginActivityVisibilityUpdate();
        try {
            forAllRootTasks(rootTask -> {
                // 遍历所有根 Task 
                rootTask.ensureActivitiesVisible(starting, configChanges, preserveWindows,
                        notifyClients);
            });
            ......
        } finally {
            mAtmService.mTaskSupervisor.endActivityVisibilityUpdate();
            mInEnsureActivitiesVisible = false;
        }
    }

遍历所有根 Task ,使其执行 ensureActivitiesVisible 方法

# Task
    void ensureActivitiesVisible(@Nullable ActivityRecord starting, int configChanges,
            boolean preserveWindows, boolean notifyClients) {
        mTaskSupervisor.beginActivityVisibilityUpdate();
        try {
            // 遍历每个叶子Task
            forAllLeafTasks(task -> {
                task.updateActivityVisibilities(starting, configChanges, preserveWindows,
                        notifyClients);
            }, true /* traverseTopToBottom */);
            ......
        } finally {
            mTaskSupervisor.endActivityVisibilityUpdate();
        }
    }

遍历所有叶子 Task ,使其执行 updateActivityVisibilities 方法,这个方法定义在父类 TaskFragmet 中。

# TaskFragmet
    // 帮助类
    private final EnsureActivitiesVisibleHelper mEnsureActivitiesVisibleHelper =
            new EnsureActivitiesVisibleHelper(this);

    final void updateActivityVisibilities(@Nullable ActivityRecord starting, int configChanges,
            boolean preserveWindows, boolean notifyClients) {
        mTaskSupervisor.beginActivityVisibilityUpdate();
        try {
            // 重点处理
            mEnsureActivitiesVisibleHelper.process(
                    starting, configChanges, preserveWindows, notifyClients);
        } finally {
            mTaskSupervisor.endActivityVisibilityUpdate();
        }
    }

我们知道这一条线都是为了处理Activity可见的。 在这定义了一个专门的类来处理。 不过需要注意的是,这个方法会执行多次,因为他是遍历每一个符合条件的子容器,从上到下遍历。

阶段二总结

阶段二的逻辑其实比较简单,其实就是 SourceActivity 完成 pause 后,执行 ActivityRecord::activityPaused 流程,AMS 需要显示当前顶层 Activity 所以执行了 RootWindowContainer::resumeFocusedTasksTopActivities 方法,但是这一次是不是真的能显示顶层 Activity 还是要看其进程是否已经创建好了。
在操作了 Activity 的显示逻辑后,为了确保系统 Activity 正常的可见性,所以又执行了一次 ensureActivitiesVisible 流程。
流程相对简单,就是下面这个图:
在这里插入图片描述

第三阶段:触发目标应用进程创建

执行pause后会执行 ActivityTaskManagerService::startProcessAsync,最后也是通过 ActivityManagerService来触发启动进程的。 看看AMS这块执行进程创建的调用流程。

# ActivityTaskManagerService
    void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,
            String hostingType) {
        try {
            if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
                Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "dispatchingStartProcess:"
                        + activity.processName);
            }

            // 发送消息,启动进程,调用 ActivityManagerInternal::startProcess
            final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess,
                    mAmInternal, activity.processName, activity.info.applicationInfo, knownToBeDead,
                    isTop, hostingType, activity.intent.getComponent());
            mH.sendMessage(m);
        } finally {
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
    }

这里通过 Handler 来完成,ActivityManagerInternal::startProcess 的实现在 ActivityManagerService 的内部类 LocalService 中。

# ActivityManagerService$LocalService

        public void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead,
                boolean isTop, String hostingType, ComponentName hostingName) {
            try {
                if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "startProcess:"
                            + processName);
                }
                synchronized (ActivityManagerService.this) {
                    // 继续调用
                    startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
                            new HostingRecord(hostingType, hostingName, isTop),
                            ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, false /* allowWhileBooting */,
                            false /* isolated */);
                }
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            }
        }
        @GuardedBy("this")
        final ProcessRecord startProcessLocked(String processName,
                ApplicationInfo info, boolean knownToBeDead, int intentFlags,
                HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,
                boolean isolated) {
            return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
                    hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,
                    false /* isSdkSandbox */, 0 /* sdkSandboxClientAppUid */,
                    null /* sdkSandboxClientAppPackage */,
                    null /* ABI override */, null /* entryPoint */,
                    null /* entryPointArgs */, null /* crashHandler */);
        }

流程走到:ProcessList::startProcessLocked

# ProcessList
    boolean startProcessLocked(......) {
                ......
                mService.mProcStartHandler.post(() -> handleProcessStart(
                    app, entryPoint, gids, runtimeFlags, zygotePolicyFlags, mountExternal,
                    requiredAbi, instructionSet, invokeWith, startSeq));     
                ......   
        }
        private void handleProcessStart(......) {
            创建一个用于启动进程的 Runnable 对象
            final Runnable startRunnable = () -> {
                try {    // 调用 startProcess 方法启动进程,并获取启动结果 ProcessStartResult
                        final Process.ProcessStartResult startResult = startProcess(app.getHostingRecord(),
                            entryPoint, app, app.getStartUid(), gids, runtimeFlags, zygotePolicyFlags,
                            mountExternal, app.getSeInfo(), requiredAbi, instructionSet, invokeWith,
                            app.getStartTime());
                         // 在锁定 ActivityManagerService 后,处理进程启动结果
                        synchronized (mService) {
                            // 更新应用的状态,如设置PID,更新生命周期状态等
                            handleProcessStartedLocked(app, startResult, startSeq);
                        }
                } catch (RuntimeException e) {
                    ......异常处理
                }
            };
            ......
        }
    

通过 ProcessList::startProcess 来启动应用进程
启动玩之后 ProcessList::handleProcessStartedLocked 会更新应用的状态,如设置PID,更新生命周期状态等。

# ProcessList
    boolean startProcessLocked(......) {
                ......
                mService.mProcStartHandler.post(() -> handleProcessStart(
                    app, entryPoint, gids, runtimeFlags, zygotePolicyFlags, mountExternal,
                    requiredAbi, instructionSet, invokeWith, startSeq));     
                ......   
        }
        private void handleProcessStart(......) {
            创建一个用于启动进程的 Runnable 对象
            final Runnable startRunnable = () -> {
                try {    // 调用 startProcess 方法启动进程,并获取启动结果 ProcessStartResult
                        final Process.ProcessStartResult startResult = startProcess(app.getHostingRecord(),
                            entryPoint, app, app.getStartUid(), gids, runtimeFlags, zygotePolicyFlags,
                            mountExternal, app.getSeInfo(), requiredAbi, instructionSet, invokeWith,
                            app.getStartTime());
                         // 在锁定 ActivityManagerService 后,处理进程启动结果
                        synchronized (mService) {
                            // 更新应用的状态,如设置PID,更新生命周期状态等
                            handleProcessStartedLocked(app, startResult, startSeq);
                        }
                } catch (RuntimeException e) {
                    ......异常处理
                }
            };
            ......
        }
    

1、通过 ProcessList::startProcess 来启动应用进程
2、启动玩之后 ProcessList::handleProcessStartedLocked 会更新应用的状态,如设置PID,更新生命周期状态等

ProcessList::handleProcessStartedLocked 经过几次重载会调用下面的方法

# ProcessList
    ActivityManagerService mService = null;

    boolean handleProcessStartedLocked(ProcessRecord app, int pid, boolean usingWrapper,
                long expectedStartSeq, boolean procAttached) {
                ......
                StringBuilder buf = mStringBuilder;
                buf.append("Start proc ");
                buf.append(pid);
                buf.append(':');
                buf.append(app.processName);
                buf.append('/');
                UserHandle.formatUid(buf, app.getStartUid());
                if (app.getIsolatedEntryPoint() != null) {
                    buf.append(" [");
                    buf.append(app.getIsolatedEntryPoint());
                    buf.append("]");
                }
                buf.append(" for ");
                buf.append(app.getHostingRecord().getType());
                if (app.getHostingRecord().getName() != null) {
                    buf.append(" ");
                    buf.append(app.getHostingRecord().getName());
                }
                // 输出日志
                mService.reportUidInfoMessageLocked(TAG, buf.toString(), app.getStartUid());
                ......
        }

创建进程会打印一些关键日志:

07-26 19:19:05.477 8737 8782 I ActivityManager: Start proc 19643:com.example.myapplication/u0a198 for next-top-activity {com.example.myapplication/com.example.myapplication.MainActivity}

经常看日志看启动了哪个进程搜的日志就是在这里打印的。

这部分调用链如下:

ActivityTaskManagerService::startProcessAsync
    ActivityManagerService$LocalService::startProcess
        ActivityManagerService::startProcessLocked
            ProcessList::startProcessLocked
                ProcessList::handleProcessStart
                    ProcessList::startProcess                               -- 启动进程
                    ProcessList::handleProcessStartedLocked
                        ActivityManagerService::reportUidInfoMessageLocked  -- 打印日志

应用进程创建

进程创建完成后会执行 ActivityThread::main 方法,所以应用端进程创建结束的逻辑从这个方法开始分析。

# ActivityThread

    // ApplicationThread 是 AMS 作为 C 端时,与应用进程通信的方式
    final ApplicationThread mAppThread = new ApplicationThread();

    public static void main(String[] args) {
        ......
        // 主线程Looper
        Looper.prepareMainLooper();
        ......
        ActivityThread thread = new ActivityThread();
        // 下一步
        thread.attach(false, startSeq);
        // 主线程Looper
         Looper.loop();
    }
    private void attach(boolean system, long startSeq) {
        ......
            final IActivityManager mgr = ActivityManager.getService();
            try {
                //重点 *2. 将mAppThread告知AMS,用于AMS与应用进程通信
                mgr.attachApplication(mAppThread, startSeq);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        ......
    }

应用端的调用链比较简单:

ActivityThread::main
    Looper::prepareMainLooper
    ActivityThread::init
    ActivityThread::attach
        ActivityManagerService::attachApplication  -- 跨进程
    Looper::loop

应用进程(电话)创建完毕后,在 main 方法里会执行 attach 就是要将自己的信息告知AMS,毕竟 AMS 是管理模块。

system_service端处理

system_service 端 ActivityManagerService 知道有进程启动了,这个行为也可能会触发系统组显示逻辑的改变,所以比如也会做响应处理

ActivityManagerService::attachApplication
    ActivityManagerService::attachApplicationLocked
        ActivityThread::bindApplication
            ActivityTaskManagerService.LocalService::attachApplication  
                WindowContainer::forAllRootTasks  --- 省略forAllRootTasks等固定堆栈
                    Task::forAllRootTasks
                        WindowContainer::forAllActivities
                            ActivityRecord::forAllActivities
                                RootWindowContainer.AttachApplicationHelper::test
                                    RootWindowContainer.AttachApplicationHelper::test
                                        ActivityTaskSupervisor::realStartActivityLocked  -- 构建LaunchActivityItem

在这里插入图片描述
接上一篇知道如果进程启动了 ActivityTaskSupervisor::startSpecificActivity 就会走进去ActivityTaskSupervisor::realStartActivityLocked 。
但是可能会好奇怎么就知道要执行应用 MainActivity 到 onCreate 就一定是在这个方法里呢? 调试方法有很多,比如加 log ,打堆栈,但是对应这个逻辑比较简单的是,需要执行 Activity 启动到 onCreate 的控制在 LaunchActivityItem 中,而 LaunchActivityItem在 framework 的引用除了本身,就只有在 ActivityTaskSupervisor。
在这里插入图片描述

# ActivityManagerService

    // 当应用进程调用attachApplication 执行
    public final void attachApplication(IApplicationThread thread, long startSeq) {
        if (thread == null) {
            throw new SecurityException("Invalid application interface");
        }
        synchronized (this) {
            // 获取 应用进程的信息后执行attachApplicationLocked
            int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            // 执行
            attachApplicationLocked(thread, callingPid, callingUid, startSeq);
            Binder.restoreCallingIdentity(origId);
        }
    }

    private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
            int pid, int callingUid, long startSeq) {
            // 需要启动应用的进程数据
            ProcessRecord app;
            ......
            if (pid != MY_PID && pid >= 0) {
                synchronized (mPidsSelfLocked) {
                    // 通过mPidsSelfLocked获取
                    app = mPidsSelfLocked.get(pid);
                }
                ......
            } 
            ...... 
            // 触发ActivityThread::bindApplication 逻辑
            if (app.getIsolatedEntryPoint() != null) {
                ......
            } else if (instr2 != null) {
                // bindApplication
                ......    
            } else {
                // 重点* 1. bindApplication
                thread.bindApplication(processName, appInfo,
                        app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,
                        providerList, null, profilerInfo, null, null, null, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.isPersistent(),
                        new Configuration(app.getWindowProcessController().getConfiguration()),
                        app.getCompat(), getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial, autofillOptions, contentCaptureOptions,
                        app.getDisabledCompatChanges(), serializedSystemFontMap,
                        app.getStartElapsedTime(), app.getStartUptime());
            }
            ......
            if (!mConstants.mEnableWaitForFinishAttachApplication) {
                // 重点* 2. 
                finishAttachApplicationInner(startSeq, callingUid, pid);
            } else {
                  app.setPendingFinishAttach(true);
            }
            ......
    }

ActivityManagerService::finishAttachApplicationInner 是 U 把原来的逻辑提取新增的方法。

# ActivityManagerService

        public ActivityTaskManagerInternal mAtmInternal;

        private void finishAttachApplicationInner(long startSeq, int uid, int pid) {
            ......
            if (normalMode) {
                try {
                    // 重点 触发构建 LaunchActivityItem 流程
                    didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
                } catch (Exception e) {
                    Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                    badApp = true;
                }
            }
            ......
        }

这里是触发 LaunchActivityItem 的流程主线, mAtmInternal是 ATMS 的内部类 LocalService

# ActivityTaskManagerService$LocalService

        @Override
        public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
            ......
            return mRootWindowContainer.attachApplication(wpc);
            ......
        }

流程来到 RootWindowContainer 预感要开始处理窗口显示逻辑。

# RootWindowContainer
        private final AttachApplicationHelper mAttachApplicationHelper = new AttachApplicationHelper();

        boolean attachApplication(WindowProcessController app) throws RemoteException {
            try {
                return mAttachApplicationHelper.process(app);
            } finally {
                mAttachApplicationHelper.reset();
            }
        }

# RootWindowContainer
    // 实现 Consumer 接口
    private class AttachApplicationHelper implements Consumer<Task>, Predicate<ActivityRecord> {
        ......
        boolean process(WindowProcessController app) throws RemoteException {
            mApp = app;
            for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
                // 重点* 调用每个容器的 forAllRootTasks
                getChildAt(displayNdx).forAllRootTasks(this);
                ......
            }
            ......
        }
        ......
    }

这里看到传递了“this”,所以 AttachApplicationHelper 必然实现了 Consumer 接口, 直接看其 accept 实现即可。

# RootWindowContainer$AttachApplicationHelper

  private class AttachApplicationHelper implements Consumer<Task>, Predicate<ActivityRecord> {
        ......
        boolean process(WindowProcessController app) throws RemoteException {
            mApp = app;
            for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
                // 重点*1. 调用每个容器的 forAllRootTasks
                getChildAt(displayNdx).forAllRootTasks(this);
                ......
            }
            ......
        }
        @Override
        public void accept(Task rootTask) {
            ......
            if (rootTask.getVisibility(null /* starting */)
                    == TASK_FRAGMENT_VISIBILITY_INVISIBLE) {
                // 如果Task 不可见则不需要处理
                return;
            }
            // 执行 topRunningActivity
            mTop = rootTask.topRunningActivity();
            // 重点*2. 执行accept 让容器下的每个 ActivityRecord 执行 test
            rootTask.forAllActivities(this);
        }
        @Override
        public boolean test(ActivityRecord r) {
            // 判断 ActivityRecord 是否满足需要启动条件
            if (r.finishing || !r.showToCurrentUser() || !r.visibleIgnoringKeyguard
                    || r.app != null || mApp.mUid != r.info.applicationInfo.uid
                    || !mApp.mName.equals(r.processName)) {
                return false;
            }
            try {
                // 重点*3. 执行 realStartActivityLocked  尝试实际启动 Activity
                if (mTaskSupervisor.realStartActivityLocked(r, mApp,
                        mTop == r && r.getTask().canBeResumed(r) /* andResume */,
                        true /* checkConfig */)) {
                    mHasActivityStarted = true;
                }
            } catch (RemoteException e) {
                ......
            }
            return false;
        }
  }

这部分的逻辑也就是一路执行,比较疑惑的点也许是进入 AttachApplicationHelper::proces 方法后的几个 Lambda 表达式容易绕晕。
简单梳理一下,首先是从 RootWindowContainer 开始执行的,目的就是想要执行到所有 ActivityRecord 然后判断一下它的情况是不是需要启动对应的 Activity 。

阶段三总结

阶段三的流程相对来逻辑简单一些,知道个调用链就好,流程目的就是执行 ActivityTaskSupervisor::realStartActivityLocked 。
这部分的堆栈如下图:
在这里插入图片描述
加上应用端的调用链,完成调用链如下:

ActivityThread::main
    Looper::prepareMainLooper
    ActivityThread::init
    ActivityThread::attach
        ActivityManagerService::attachApplication  -- 跨进程
            ActivityManagerService::attachApplicationLocked
                ActivityThread::bindApplication
                ActivityManagerService::finishAttachApplicationInner
                    ActivityTaskManagerService$LocalService::attachApplication
                        RootWindowContainer::attachApplication
                            RootWindowContainer$AttachApplicationHelper::process -- 开始遍历
                                WindowContainer::forAllRootTasks  --- 省略forAllRootTasks等固定堆栈
                                    Task::forAllRootTasks  -- 1. 遍历所有root Task
                                        RootWindowContainer$AttachApplicationHelper::accept  -- 1.1 root Task执行accept
                                            WindowContainer::forAllActivities  -- 2. 遍历下面的所有ActivityRecord
                                                ActivityRecord::forAllActivities 
                                                    RootWindowContainer$AttachApplicationHelper::test  -- 2.1 ActivityRecord执行test
                                                        ActivityTaskSupervisor::realStartActivityLocked  -- 试图启动Activity
    Looper::loop


对应时序图:
在这里插入图片描述
大概流程图如下:
在这里插入图片描述
这一阶段主要就是应用进程启动后,试图拉起对应的 Activity ,能不能启动的条件就是没有正在 pause 的 Activity 了。 主要逻辑就是触发 ActivityTaskSupervisor::realStartActivityLocked

第四阶段:真正启动Activity

这个方法是要真去触发 Activity 启动的,根据前面的流程图,阶段二,三的最终就是想执行到这个方法里面,来触发 Activity 启动。
这个方法的最终目的就是通过事务执行 LaunchActivityItem 和 PauseActivityItem ,也就是会触发应用端 TargetActivity 启动,并执行生命周期到 onCreate 和 onResume 。

# ActivityTaskSupervisor 

    boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
            boolean andResume, boolean checkConfig) throws RemoteException {
            //  重点* 1. 判断是否执行完了pause 
            if (!mRootWindowContainer.allPausedActivitiesComplete()) {
                // While there are activities pausing we skipping starting any new activities until
                // pauses are complete. NOTE: that we also do this for activities that are starting in
                // the paused state because they will first be resumed then paused on the client side.
                // 如果还有Activity没完成pause,则打印日志并return
                ProtoLog.v(WM_DEBUG_STATES,
                        "realStartActivityLocked: Skipping start of r=%s some activities pausing...",
                        r);
                return false;
            }
            // 重点* 2. 表示ActivityRecord已连接到相应的进程
            r.setProcess(proc);
            ......
            // event日志: wm_restart_activity 
            EventLogTags.writeWmRestartActivity(r.mUserId, System.identityHashCode(r),
                        task.mTaskId, r.shortComponentName);
            ......
                // 重点* 3.1 创建事务,用于Activity启动
                // Create activity launch transaction.
                final ClientTransaction clientTransaction = ClientTransaction.obtain(
                        proc.getThread(), r.token);
                final boolean isTransitionForward = r.isTransitionForward();

                // 获取Activity所在 TaskFragment Token
                final IBinder fragmentToken = r.getTaskFragment().getFragmentToken();
                // 重点* 3.2 将构建的 LaunchActivityItem 添加到 clientTransaction 中
                clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
                        System.identityHashCode(r), r.info,
                        // TODO: Have this take the merged configuration instead of separate global
                        // and override configs.
                        mergedConfiguration.getGlobalConfiguration(),
                        mergedConfiguration.getOverrideConfiguration(), r.compat,
                        r.getFilteredReferrer(r.launchedFromPackage), task.voiceInteractor,
                        proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(),
                        results, newIntents, r.takeOptions(), isTransitionForward,
                        proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
                        r.shareableActivityToken, r.getLaunchedFromBubble(), fragmentToken));

                // 重点* 3.3 设置预期的最终状态为 ResumeActivityItem
                final ActivityLifecycleItem lifecycleItem;
                if (andResume) {
                    // Resume逻辑,启动走的这。 表示需要执行到onCreate
                    lifecycleItem = ResumeActivityItem.obtain(isTransitionForward);
                } else {
                    //  Pause 逻辑
                    lifecycleItem = PauseActivityItem.obtain();
                }
                clientTransaction.setLifecycleStateRequest(lifecycleItem);
                // 重点* 3.4 执行事务
                mService.getLifecycleManager().scheduleTransaction(clientTransaction);
                ......
    }

根据代码的标注解释:
1、根据注释,如果有 Activity 正在 pause 则不允许任何 Activity 启动。换句话说就是想要启动一个 Activity 必须其他的 Activity 需要 pause 的都完成了 pause 流程
2、对应之前提到的 ActivityRecord::attachedToProcess 方法如果需要返回 true ,则必须在这里执行 setProcess 方法,否则 ActivityRecord 下的 app 变量就是 null
3、这里就是开始真正执行启动 Activity 的地方了,是通过事务执行的,分为以下几步
3.1 构建一个事务
3.2 设置 LaunchActivityItem ,这一步会将 Activity 的生命周期执行到 onCreate
3.3 设置 ResumeActivityItem ,这一步会将 Activity 的生命周期执行到 onResume
3.4 执行事务

后续逻辑就是在应用端执行 Activity 的创建,以及生命周期处理了,这部分本篇大概看一遍流程。

创建Activity

这部分的调用链如下:

LaunchActivityItem::execute
    ActivityThread::handleLaunchActivity
        ActivityThread::performLaunchActivity
            Instrumentation::newActivity -- 创建Activity
            Activity::attach  -- 处理Window相关
                Window::init
                Window::setWindowManager
            Instrumentation::callActivityOnCreate -- onCreate流程
                Activity::performCreate
                    Activity::onCreate  --over

时序图图下:
在这里插入图片描述
接下来看 LaunchActivityItem::execute

# LaunchActivityItem 
    public void execute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
        ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
                mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
                mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
                client, mAssistToken, mShareableActivityToken, mLaunchedFromBubble,
                mTaskFragmentToken);
        client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }

这里的 client 是 ClientTransactionHandler 类型, 而 ActivityThread 是 ClientTransactionHandler 子类。
重点是这边创建了 ActivityClientRecord ,第一个参数就是我们要找的token

逻辑来到应用进程 ActivityThread。

# ActivityThread

    public Activity handleLaunchActivity(ActivityClientRecord r,
                PendingTransactionActions pendingActions, Intent customIntent) {
                    ......
                    
                    final Activity a = performLaunchActivity(r, customIntent);
                    ......
                }

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ......
                Activity activity = null;
                try {
                    // 重点* 1. 通过Instrumentation 反射创建Activity
                    java.lang.ClassLoader cl = appContext.getClassLoader();
                    activity = mInstrumentation.newActivity(
                            cl, component.getClassName(), r.intent);
                    ......
                }
                try {
                    ......
                    // 重点* 2. 执行 attach 流程
                    activity.attach(appContext, this, getInstrumentation(), r.token,
                            r.ident, app, r.intent, r.activityInfo, title, r.parent,
                            r.embeddedID, r.lastNonConfigurationInstances, config,
                            r.referrer, r.voiceInteractor, window, r.activityConfigCallback,
                            r.assistToken, r.shareableActivityToken);
                    ......
                    if (r.isPersistable()) {
                        mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                    } else {
                        重点* 3. onCreate流程
                        mInstrumentation.callActivityOnCreate(activity, r.state);
                    }
                }
        ......
    }

这里有3个重点:

  • Activity 是通过反射创建的。 到这里其实 Activity 启动流程基本分析完了
  • 执行 Activity::attach 。这里会触发创建 Window
  • 触发 Activity::onCreate

Activity 已经创建好了,那就剩下 onCreate 了。

# Instrumentation
    public void callActivityOnCreate(Activity activity, Bundle icicle) {
        prePerformCreate(activity);
        // onCreate流程
        activity.performCreate(icicle);
        postPerformCreate(activity);
    }

# Activity
    final void performCreate(Bundle icicle) {
        performCreate(icicle, null);
    }

    final void performCreate(Bundle icicle, PersistableBundle persistentState) {
        ......
        if (persistentState != null) {
            onCreate(icicle, persistentState);
        } else {
            // 执行onCreate
            onCreate(icicle);
        }
        ......
    }

写过应用的都知道,默认都是一个参数的onCreate。

至此,Activity 启动流程分析完毕。

阶段四小结

在这里插入图片描述
无论是阶段二还是阶段三触发了 ActivityTaskSupervisor::realStartActivityLocked 方法,并且还满足启动 Activity 条件,则会触发应用端进程 Activity 的创建和生命周期的执行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2096372.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

最新!yolov10+deepsort的目标跟踪实现

目录 yolov10介绍——实时端到端物体检测 概述 主要功能 型号 性能 方法 一致的双重任务分配&#xff0c;实现无 NMS 培训 效率-精度驱动的整体模型设计 提高效率 精度提升 实验和结果 比较 deepsort介绍&#xff1a; yolov10结合deepsort实现目标跟踪 效果展示…

Elasticsearch的部署和使用

首先对java来说,我们可用的有原生elasticsearch和经过spring二次封装的spring data elasticsearch. 后者自带了一些方法,类似于mybatisplus,可以直接使用,十分方便. 如果是spring项目都建议使用第二种,除非你要深度使用. 首先是服务器的部署.部署之前要知道版本,我在部署时遇到…

GoLang:Go语言开发环境的配置

Go语言 Go语言开发环境的配置 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/qq_28550263/a…

一款管理苹果设备的软件iMazing3中文破解安装激活教程

iMazing3官方版是一款管理苹果设备的软件&#xff0c;是一款帮助用户管理 IOS 手机的PC端应用程序&#xff0c;能力远超 iTunes 提供的终极 iOS 设备管理器。在iMazing官方版上与苹果设备连接后&#xff0c;可以轻松传输文件&#xff0c;浏览保存信息等&#xff0c;功能比Itune…

NDK编译c/c++文件成so库

目录 背景 Android NDK下载及配置 工程准备 创建Android.mk文件 创建Application.mk文件 编译项目 总结 背景 做算法开发&#xff0c;有时需要将算法编程成so库给其他人调用&#xff0c;很多时候都是在Android平台上使用&#xff0c;这样就会使用到Android NDK进行编译&…

高职院校大数据分析与可视化微服务架构实训室解决方案

一、前言 随着信息技术的飞速发展&#xff0c;大数据已成为推动社会进步与产业升级的关键力量。为了培养适应未来市场需求的高素质技术技能型人才&#xff0c;高职院校纷纷加大对大数据分析与可视化技术的教学投入。唯众&#xff0c;作为国内领先的职业教育解决方案提供商&…

论文速读|大型语言模型作为通用模式机器

项目地址&#xff1a;Large Language Models as General Pattern Machines 本研究探讨了大型语言模型&#xff08;LLMs&#xff09;作为通用模式机器的潜力&#xff0c;特别是在机器人技术领域。研究发现&#xff0c;LLMs 能够在没有额外训练的情况下&#xff0c;通过上下文学…

这才是HR想看到的应届生简历

速创猫今天给大家分享的是应届毕业生简历优化案例&#xff0c;希望对大家求职有帮助。速创猫总结了以下七条简历制作干货&#xff0c;希望对大家有帮助&#xff1a; 简洁明了&#xff1a;简历不是自传&#xff0c;不需要长篇大论。保持每份简历在一页纸内&#xff0c;突出关键…

Linux(CentOS)同步服务器时间之~chrony

Chrony 是一款开源的网络时间协议&#xff08;NTP&#xff09;客户端和服务端软件&#xff0c;旨在提供高精度的时间同步功能。相较于传统的 NTP 实现如 ntpd&#xff0c;Chrony 提供了一些改进和优势&#xff0c;包括更快的同步速度、低延迟、低CPU占用和低内存消耗。以下是 C…

c++ 154 引用

#include<iostream> using namespace std; //引用作为函数参数不需要初始化 void myswap(int *a,int *b) {int c 0;c *a;*a *b;*b c; } void main03() {int a 10;//引用语法 Type & name var;int& b a;b 100;//相当于把a改成100&#xff1b;printf("…

素材无水印素材网站在哪下载?高清的无水印素材资源库分享

找高清无水印素材&#xff1f;蛙学网、Pixabay 等资源库全揭秘&#xff01; 创意十足的你&#xff0c;是不是常为网上素材的烦人水印而头疼&#xff1f;总在寻找高清、干净、无水印的素材资源&#xff0c;却无从下手&#xff1f;别急&#xff0c;今天就为大家推荐几个超实用的…

c++应用网络编程之八SOCKET探究

一、socket 在目前主流的网络通信中&#xff0c;SOCKET编程其实就是网络编程的代名词。在前面反复提到socket&#xff0c;那么socket到底是什么呢&#xff1f;英文的愿意是“插座、槽”的意思。这里虽然不讲解传统的网络协议但不得不简单说明一下。 首先从宏观上看&#xff0c…

《数字信号处理》学习01-离散时间信号与序列的卷积和运算

目录 一&#xff0c;信号 二&#xff0c;序列的运算 1&#xff0c;卷积和 2&#xff0c;matlab实现 相关的电子书籍请到这篇文章所在的专栏&#xff0c;并通过夸克网盘链接下载。 很多简单的知识点我就不再赘述了&#xff0c;接下来就着重记录我学习过程中遇到的较难理…

class 3: vue.js 3 计算属性

计算属性是一种Options API&#xff0c;Options API是一种通过对象定义属性、方法等框架API的方式我们知道&#xff0c;在模板中可以直接通过插值语法显示一些data属性中的数据。但是在某些情况下&#xff0c;可能需要对数据进行一些转化操作之后再显示&#xff0c;或者需要将多…

PostgreSQL技术内幕5:PostgreSQL存储引擎从磁盘到内存的读取

文章目录 0.简介1.背景知识1.1 计算机存储结构1.2 数据库常见的磁盘和内存访问形式 2. 整体获取层次3.元组介绍4. Buffer管理4.1 Buffer组成4.2 修改后落盘4.3 获取buffer页的流程 5.存储管理器&#xff08;SMGR)6.磁盘管理器&#xff08;MD)7.虚拟文件管理器&#xff08;VFD)8…

【攻防世界新手入门】simple_js

小宁发现了一个网页&#xff0c;但却一直输不对密码。&#xff08;Flag格式为 Cyberpeace{xxxxxxxxx} &#xff09; 该题来自攻防世界新手练习区的 GFSJ0480。 访问靶场&#xff0c;输入任意密码&#xff0c;弹出错误窗口并加载空页面&#xff0c;使用检查器查看对应源代码&…

zdppy+vue3+onlyoffice文档管理系统实战 20240901 上课笔记 基于验证码登录功能基本完成

遗留的问题 1、点击切换验证码2、1分钟后自动切换验证码 点击切换验证码 实现步骤&#xff1a; 1、点击事件2、调用验证码接口3、更新验证码的值 点击事件 给图片添加点击事件&#xff1a; <img :src" data:image/png;base64, captchaImg"style"widt…

ffplay源码分析(五)包缓存队列和帧缓存队列

在音视频处理流程中&#xff0c;ffplay的有两种队列&#xff0c;包缓存队列&#xff08;Packet Buffer Queue&#xff09;和帧缓存队列&#xff08;Frame Buffer Queue&#xff09;。这两个队列的存在&#xff0c;是为了适应音视频数据处理过程中的多线程架构——包括收包线程、…

win11+vscode+Flutter 开发环境配置

https://blog.csdn.net/Oven_maizi/article/details/126804404 1 vscode插件 安装 安装红框中的两个 2 flutter sdk 安装 dart sdk 包含在flutter sdk 里面&#xff0c;路径&#xff1a;flutter_windows_3.24.1-stable\flutter\bin\cache\dart-sdk 方式1&#xff1a; 通过…

[001-07-001].Redis7缓存双写一致性之更新策略探讨

1、面试题&#xff1a; 1.只要使用缓存&#xff0c;就可能会涉及到redis缓存与数据库双存储双写&#xff0c;只要是双写&#xff0c;就存在数据一致性问题&#xff0c;那么是如何解决数据一致性问题的2.双写一致性&#xff0c;你先动缓存redis还是数据库MySQL&#xff0c;哪一个…