瞧一瞧API30时Activity启动流程有何不同~

854 阅读14分钟

前言

Activity一般是安卓开发接触到的第一个重要组件,代表着与用户交互的活动视窗,活动与活动之间往往不是相互独立的,startActivity()就是从一个活动跳转到另一个活动的桥梁。而对于startActivity()的了解,我们往往只停留在它的使用上,很少去深究它的原理 。

今天,就让我们跟随着源码,一步一步的追溯它的调用流程,初步了解下它的调用链,后续我们还可以继续挖掘,关于应用启动、启动模式、hook启动流程等相关技术支持。

此系列博客在未声明API版本情况下,将使用API30 版本的AndroidSDK源码。

源码查看工具使用AndroidStudio。源码来源%AndroidSDK%/sources。一般方式:备份一份source目录,使用AndroidStudio Open你想观察的api版本的源码目录。

源码分析

Activity.startActivity()

我们日常编写的activity.startActivity(intent)的代码,实际是调用以下代码:

{@link android.app.Activity#startActivity}
@Override
public void startActivity(Intent intent) {
    this.startActivity(intent, null);
}

@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
    // API 30 此处新增关于自动填充相关的处理代码,API26无此项
    if (options != null) {
        startActivityForResult(intent, -1, options);
    } else {
        // Note we want to go through this call for compatibility with
        // applications that may have overridden the method.
        startActivityForResult(intent, -1);
    }
}

Activity.startActivityForResult()

有上述代码可知,startActivity() 实际是调用 startActivityForResult():

{@link android.app.Activity#startActivityForResult}
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
        @Nullable Bundle options) {
    if (mParent == null) {
        options = transferSpringboardActivityOptions(options);
        // 注意此处,mMainThread.getApplicationThread() 实际为 IApplicationThread
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode, options);
        if (ar != null) {
            mMainThread.sendActivityResult(
                mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                ar.getResultData());
        }
        if (requestCode >= 0) {
            //如果这个start请求一个结果,我们可以在收到结果之前避免使活动可见。
            //在onCreate(Bundle savedInstanceState)或onResume()期间设置此代码将保持活动在此期间隐藏,以避免闪烁。
            //这只能在请求结果时执行,因为这保证了无论活动发生了什么,我们都会在活动完成时获得信息
            mStartedActivity = true;
        }

        cancelInputsAndStartExitTransition(options);
    } else {
        // 实际也是调用mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options);此处不做赘述
        if (options != null) {
            mParent.startActivityFromChild(this, intent, requestCode, options);
        } else {
            // 注意,我们想要遍历这个方法,以便与可能已覆盖它的现有应用程序兼容。
            mParent.startActivityFromChild(this, intent, requestCode);
        }
    }
}

此处,我们抛开其他代码,关注这里的if else 最终都是调用mInstrumentation.execStartActivity(),从字面意义上说,它代表“执行启动活动”,显然我们应当关注此方法。

Instrumentation.execStartActivity()

Instrumentation类。此处我们不做详细分析,但应当知道的是,它的作用及能力:

实现应用程序插装代码的基类。在启动插装的情况下运行时,这个类将在任何应用程序代码之前为您实例化,允许您监视系统与应用程序之间的所有交互。通过AndroidManifest.xml的< Instrumentation >标签向系统描述了一个Instrumentation实现。

{@link android.app.Instrumentation#execStartActivity}
@UnsupportedAppUsage
public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    // 此处省略代码
    try {
        intent.migrateExtraStreamToClipData(who);
        intent.prepareToLeaveProcess(who);
        // 注意此处
        int result = ActivityTaskManager.getService().startActivity(whoThread,
                who.getBasePackageName(), who.getAttributionTag(), intent,
                intent.resolveTypeIfNeeded(who.getContentResolver()), token,
                target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

这里,我们可以看到,Instrumentation.execStartActivity()调用了ActivityTaskManager.getService().startActivity()将启动活动委托给了某个“服务”执行,我们来看看这个“服务”是什么。

ActivityTaskManager.getService()

{@link android.app.ActivityTaskManager}
public static IActivityTaskManager getService() {
    return IActivityTaskManagerSingleton.get();
}

@UnsupportedAppUsage(trackingBug = 129726065)
private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
        new Singleton<IActivityTaskManager>() {
            @Override
            protected IActivityTaskManager create() {
                final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
                return IActivityTaskManager.Stub.asInterface(b);
            }
        };

这里代码的作用其实是通过获取IBinder类型的服务生产一个启动活动的代理类,实现方式: 使用的是名为ACTIVITY_TASK_SERVICE的IBinder生产了一个IActivityTaskManager

使用过AIDL的同学应该看出来了,这里类似的,也是通过跨进程通信的方式操作的。

IActivityTaskManager.startActivity()

由于我们没办法直接获取到IActivityTaskManager的实现类,我们通过搜索IActivityTaskManager.Stub的实现类来寻找前面提到的“服务”具体是什么。

api30_IActivityTaskManager

由上图可知,这个“服务”应该就是com.android.server.wm.ActivityTaskManagerService,我们找到startActivity()方法,验证其入参是否一致:

{@link com.android.server.wm.ActivityTaskManagerService}
@Override
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) {
    return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
            resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
            UserHandle.getCallingUserId());
}

通过入参比对,基本确认此方法是Instrumentation.execStartActivity()中调用ActivityTaskManager.getService().startActivity()的后续流程了。

ActivityTaskManagerService.startActivityAsUser

startActivityAsUser包含一系列重载方法,最终都是执行以下代码:

{@link com.android.server.wm.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) {
    assertPackageMatchesCallingUid(callingPackage);
    enforceNotIsolatedCaller("startActivityAsUser");

    userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
            Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

    // TODO: Switch to user app stacks here.
    // 注意这里的caller为 IApplicationThread
    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();

}

这里主要通过工厂生产出ActivityStarter对象,并调用execute()执行。

ActivityStarter.execute()

由该方法注释我们可知其作用:

根据前面提供的请求参数解析必要的信息,并执行开始启动活动旅程的请求。

{@link com.android.server.wm.ActivityStarter}
{@link }
int execute() {
    try {
      // 此处省略代码
        int res;
        synchronized (mService.mGlobalLock) {
            // 此处省略代码
            res = executeRequest(mRequest);

            Binder.restoreCallingIdentity(origId);
            // 此处省略代码
            return getExternalResult(mRequest.waitResult == null ? res
                    : waitForResult(res, mLastStartActivityRecord));
        }
    } finally {
        onExecutionComplete();
    }
}

而这个方法的核心是调用executeRequest(mRequest),由于代码较长,此处省略具体实现:

{@link com.android.server.wm.ActivityStarter}
private int executeRequest(Request request) {
    // 省略其他定义
    final IApplicationThread caller = request.caller;
    final IBinder resultTo = request.resultTo;
    // 省略其他检查代码
    // 检查权限等
    boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
        requestCode, callingPid, callingUid, callingPackage, callingFeatureId,
        request.ignoreTargetSecurity, inTask != null, callerApp, resultRecord, resultStack);
    abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
            callingPid, resolvedType, aInfo.applicationInfo);
    abort |= !mService.getPermissionPolicyInternal().checkStartActivity(intent, callingUid,
            callingPackage);
    // 省略其他检查及设置状态代码
    // 创建ActivityRecord,注意此处callerApp为 对 IApplicationThread的封装
    final ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
            callingPackage, callingFeatureId, intent, resolvedType, aInfo,
            mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode,
            request.componentSpecified, voiceSession != null, mSupervisor, checkedOptions,
            sourceRecord);
    mLastStartActivityRecord = r;
    // 省略代码
    mService.onStartActivitySetDidAppSwitch();
    mController.doPendingActivityLaunches(false);

    mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
            request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask,
            restrictedBgActivity, intentGrants);

    if (request.outActivity != null) {
        request.outActivity[0] = mLastStartActivityRecord;
    }

    return mLastStartActivityResult;
}

executeRequest 做了基本的启动检查,创建包含IApplicationThread对象的Activity的表示类ActivityRecord(历史堆栈中的一个条目,表示一个活动),并最终调用 startActivityUnchecked() 方法,startActivityUnchecked()中主要调用 startActivityInner() 方法:

{@link com.android.server.wm.ActivityStarter}
int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        int startFlags, boolean doResume, ActivityOptions options, Task inTask,
        boolean restrictedBgActivity, NeededUriGrants intentGrants) {
    // 省略代码
    // 计算是否有一个现有的任务可用于加载Activity。
    final Task targetTask = reusedTask != null ? reusedTask : computeTargetTask();
    final boolean newTask = targetTask == null;
    // 省略以下代码:
    // 以下判断主要针对目标Activity
    // 判断是否正在栈顶
    // 判断并执行是否可以栈顶复用
    // 判断并执行是否需要开启新栈
    // 判断并执行是否移动到栈顶(singleTask弹栈)
    // =====
    // 操作目标Activity栈,启动模式、转场动画相关逻辑
    mTargetStack.startActivityLocked(mStartActivity, topStack.getTopNonFinishingActivity(),
                newTask, mKeepCurTransition, mOptions);
    if (mDoResume) {
        final ActivityRecord topTaskActivity =
                mStartActivity.getTask().topRunningActivityLocked();
        if (!mTargetStack.isTopActivityFocusable()
                || (topTaskActivity != null && topTaskActivity.isTaskOverlay()
                && mStartActivity != topTaskActivity)) {
            // 如果该活动是不可调焦的,我们不能恢复它,但仍然希望确保它在开始时可见(这也将触发进入动画)。
            // 这方面的一个例子是PIP活动。同样,我们不希望在一个任务中恢复当前有覆盖的活动,因为开始的活动只是需要在可见的暂停状态,直到覆盖被删除。
            // 传递{@code null}作为start参数可以确保所有活动都是可见的。
            mTargetStack.ensureActivitiesVisible(null /* starting */,
                    0 /* configChanges */, !PRESERVE_WINDOWS);
            // 继续并告诉窗口管理器为这个活动执行应用程序过渡,因为应用程序过渡不会通过resume通道触发。
            mTargetStack.getDisplay().mDisplayContent.executeAppTransition();
        } else {
            // 如果目标堆栈之前不是可调焦的(该堆栈上之前的top运行活动不可见),那么之前任何将该堆栈移动到该堆栈的调用都不会更新被调焦的堆栈。
            // 如果现在启动新的活动允许任务堆栈可调焦,那么请确保我们现在相应地更新已调焦的堆栈。
            if (mTargetStack.isTopActivityFocusable()
                    && !mRootWindowContainer.isTopDisplayFocusedStack(mTargetStack)) {
                mTargetStack.moveToFront("startActivityInner");
            }
            mRootWindowContainer.resumeFocusedStacksTopActivities(
                    mTargetStack, mStartActivity, mOptions);
        }
    }
     mRootWindowContainer.updateUserStack(mStartActivity.mUserId, mTargetStack);

    // 当活动启动时,立即更新最近任务列表
    mSupervisor.mRecentTasks.add(mStartActivity.getTask());
    mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(),
            mPreferredWindowingMode, mPreferredTaskDisplayArea, mTargetStack);

    return START_SUCCESS;
}

由于这里代码较长,故忽略了大量代码,我们对这个方法的功能做一个简单的总结:

  • 根据当前栈的情况,判断目标Activity入栈操作:是否需要新栈,是否栈顶复用,是否弹栈等
  • 转场动画相关操作
  • 判断目标活动是否可获得焦点,执行对应操作

那么,在判断目标活动是否可获得焦点的分支里,我们启动的activity自然是需要焦点(可见可操作)的,所以我们主要关注mRootWindowContainer.resumeFocusedStacksTopActivities(mTargetStack, mStartActivity, mOptions);.

RootWindowContainer.resumeFocusedStacksTopActivities()

{@link com.android.server.wm.RootWindowContainer}
boolean resumeFocusedStacksTopActivities(
        ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {

    if (!mStackSupervisor.readyToResume()) {
        return false;
    }

    boolean result = false;
    // 如果目标在栈顶展示区域,则调用(状态模式)ResumeActivityItem执行resume操作
    if (targetStack != null && (targetStack.isTopStackInDisplayArea()
            || getTopDisplayFocusedStack() == targetStack)) {
        result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }

    for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
        // 省略展示区域相关判断及计算
        if (!resumedOnDisplay) {
            // 在没有有效活动的情况下(例如,设备刚刚启动或启动程序崩溃),可能什么都没有恢复显示。
            // 显式地请求集中堆栈中的top活动的resume将确保至少home活动被启动和恢复,并且不会发生递归。
            final ActivityStack focusedStack = display.getFocusedStack();
            if (focusedStack != null) {
                result |= focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions);
            } else if (targetStack == null) {
                result |= resumeHomeActivity(null /* prev */, "no-focusable-task",
                        display.getDefaultTaskDisplayArea());
            }
        }
    }

    return result;
}

观察上述代码,主要做了以下事情:

  • 如果目标已展示在栈顶可见区域,则执行resume
  • 如果不存在有效的活动(崩溃或首次启动),则启动首页
  • 如果存在有效活动(存在有焦点的栈),继续执行启动流程

此处,我们以存在有效活动为条件,继续关注启动流程,跟进resumeTopActivityUncheckedLocked();

ActivityStack.resumeTopActivityUncheckedLocked()

{@link com.android.server.wm.ActivityStack}
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
    if (mInResumeTopActivity) {
        // (如果在栈顶可见),甚至不要开始递归.
        return false;
    }

    boolean result = false;
    try {
        // 防止递归。
        mInResumeTopActivity = true;
        result = resumeTopActivityInnerLocked(prev, options);

        // 当恢复top活动时,可能需要暂停top活动(例如,返回锁屏。
        // 我们在{@link #resumeTopActivityUncheckedLocked}中取消了正常的暂停逻辑,因为顶部活动在结束时恢复。我们在这里再次调用{@link ActivityStackSupervisor# checkreadyforsleepplocked}来确保任何必要的暂停逻辑发生。
        // 在不考虑锁屏的情况下,活动将被显示,对{@link ActivityStackSupervisor# checkreadyforsleepplocked}的调用被跳过。
        final ActivityRecord next = topRunningActivity(true /* focusableOnly */);
        if (next == null || !next.canTurnScreenOn()) {
            checkReadyForSleep();
        }
    } finally {
        mInResumeTopActivity = false;
    }

    return result;
}

观察代码,这里主要做了防止递归调用的措施,以及调用了resumeTopActivityInnerLocked()方法,代码较长,此处将做忽略和拆解:

{@link com.android.server.wm.ActivityStack}
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
    // 忽略部分判断
    if (!hasRunningActivity) {
        // 栈里没有活动了,我们去别的地方看看。
        // 备注:注意,此处可能会出现递归调用,即会调用前面的流程:RootWindowContainer.resumeFocusedStacksTopActivities()
        // 这里也是前序流程中防范递归的原因
        return resumeNextFocusableActivityWhenStackIsEmpty(prev, options);
    }
    // 省略大量代码
    // 执行栈中其他activity的pause操作
    // 我们正在启动下一个活动,因此告诉窗口管理器前一个活动将很快被隐藏。这样它就可以知道在计算所需的屏幕方向时忽略它。
    if (next.attachedToProcess()) {
    // 更新进程信息
    // 检查特殊场景,例如半透明Activity等
    }else {
        // 哎呀,需要重新启动这个Activity!
        if (!next.hasBeenLaunched) {
            next.hasBeenLaunched = true;
        } else {
            if (SHOW_APP_STARTING_PREVIEW) {
                next.showStartingWindow(null /* prev */, false /* newTask */,
                        false /* taskSwich */);
            }
            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
        }
        if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
        mStackSupervisor.startSpecificActivity(next, true, true);
    }

    return true;
}

代码比较长,其中大部分的操作在上述代码的注释中有说明,此处不做过多关注,我们看到与startActivity()有关的代码为mStackSupervisor.startSpecificActivity(next, true, true), 我们来看一下它的作用是什么。

ActivityStackSupervisor.startSpecificActivity()

Supervisor :主管。这个类字面意思是活动栈的主管,它的作用从注释中可以了解到:

  • 将与层次结构相关的东西移动到RootWindowContainer
  • 将与活动生命周期相关的东西移动到一个新的类ActivityLifeCycler中
  • 移动接口事物到ActivityTaskManagerService。
  • 所有其他的小事情到其他文件。
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
    // Is this activity's application already running?
    // 真是个糟糕的注释,让我想起了偶尔会遇到的一个报错  ┗|`O′|┛
    final WindowProcessController wpc =
            mService.getProcessController(r.processName, r.info.applicationInfo.uid);

    boolean knownToBeDead = false;
    // 如果applicationThread存在,则执行真实的启动Activity
    if (wpc != null && wpc.hasThread()) {
        try {
            realStartActivityLocked(r, wpc, andResume, checkConfig);
            return;
        } catch (RemoteException e) {
            Slog.w(TAG, "Exception when starting activity "
                    + r.intent.getComponent().flattenToShortString(), e);
        }

        // 如果抛出了死对象异常——重新启动应用程序。
        knownToBeDead = true;
    }

    r.notifyUnknownVisibilityLaunchedForKeyguardTransition();

    final boolean isTop = andResume && r.isTopRunningActivity();
    // 若applicationThread不存在,将启动新的进程
    mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
}

上述代码中,主要做了三次校验:

  • 若目标ApplicationThread对象存在,则继续执行启动流程
  • 若启动流程执行失败,则重启应用程序
  • 若目标ApplicationThread对象不存在,则启动新的进程;此流程暂不做关注,可自行跟进,最终会调用ActivityManagerService.startProcessLocked()及后续ZygoteProcess相关方法。

ActivityStackSupervisor.realStartActivityLocked()

ActivityStackSupervisor.realStartActivityLocked()基本算得上启动流程中相当重要的一部分了,基本算得上是调用链的结束,后续将执行目标ActivityThread执行Launch操作,故单独做一小节讲述。

{@link com.android.server.wm.ActivityStackSupervisor}
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
        boolean andResume, boolean checkConfig) throws RemoteException {

    if (!mRootWindowContainer.allPausedActivitiesComplete()) {
        // 当有活动暂停时,我们跳过开始任何新的活动,直到暂停完成。
        // 注意:对于在暂停状态下启动的活动,我们也会这样做,因为它们首先会被恢复,然后在客户端暂停。
        // 思考:那么,你会担心当此启动未成功吗?可还记得。我们启动流程其实包含递归操作,如果此次中断,不代表后续就不再执行启动操作了。
        if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
                "realStartActivityLocked: Skipping start of r=" + r
                + " some activities pausing...");
        return false;
    }

    // 省略大量代码    
    
    // 因为我们可能会在系统进程中启动一个活动,所以这可能不会跨越创建新配置的绑定器接口。因此,我们必须总是在这里创建一个新的配置。

    final MergedConfiguration mergedConfiguration = new MergedConfiguration(
            proc.getConfiguration(), r.getMergedOverrideConfiguration());
    r.setLastReportedConfiguration(mergedConfiguration);

    logIfTransactionTooLarge(r.intent, r.getSavedState());

    // 创建活动启动事务。
    final ClientTransaction clientTransaction = ClientTransaction.obtain(
            proc.getThread(), r.appToken);

    final DisplayContent dc = r.getDisplay().mDisplayContent;
    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.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
            r.getSavedState(), r.getPersistentSavedState(), results, newIntents,
            dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
            r.assistToken, r.createFixedRotationAdjustmentsIfNeeded()));

    // Set desired final state.
    final ActivityLifecycleItem lifecycleItem;
    if (andResume) {
        lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
    } else {
        lifecycleItem = PauseActivityItem.obtain();
    }
    clientTransaction.setLifecycleStateRequest(lifecycleItem);

    // Schedule transaction.
    mService.getLifecycleManager().scheduleTransaction(clientTransaction);
    
    // 再次省略大量代码
    // 设置活动状态后,执行OOM评分,使流程可以更新为最新状态。    
    proc.onStartActivity(mService.mTopProcessState, r.info);
    //如果需要,启动新版本设置屏幕。我们在启动初始化的activity(即home)之后做这个操作,这样它就有机会在后台初始化自己,使切换回它更快,看起来更好。
    if (mRootWindowContainer.isTopDisplayFocusedStack(stack)) {
        mService.getActivityStartController().startSetupActivity();
    }

    // 更新我们绑定到的任何可能关心其客户端是否有活动的服务。
    if (r.app != null) {
        r.app.updateServiceConnectionActivities();
    }

    return true;
}

从上述代码及注释我们可知,realStartActivityLocked的主要功能是:

  • 若有正在pause的活动,等待它操作完毕
  • 创建 LaunchActivityItem (启动Activity的策略/状态)并封装成事务
  • 执行启动Activity的事务
  • 更新进程信息及其他相关服务

那么,我们知道activity启动流程的最后两步即是:创建 LaunchActivityItem 及执行 ClientTransaction,这里我们分两各部分介绍,先介绍 ClientTransaction 的调用流程,再介绍 LaunchActivityItem 是什么。

执行LaunchActivityItem事务

ActivityStackSupervisor.realStartActivityLocked()中调用的mService.getLifecycleManager().scheduleTransaction(clientTransaction);实际是ClientLifecycleManager.scheduleTransaction():

{@link com.android.server.wm.ClientLifecycleManager}
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
    final IApplicationThread client = transaction.getClient();
    transaction.schedule();
    if (!(client instanceof Binder)) {
        // 如果client不是Binder的实例——它是一个远程调用,此时可以安全地回收对象。
        // 在ActivityThread的客户端上执行事务后,用于本地调用的所有对象都将被回收。
        transaction.recycle();
    }
}

这里主要调用了ClientTransaction.schedule():

{@link android.app.servertransaction.ClientTransaction}
/** Target client. */
private IApplicationThread mClient;

public void schedule() throws RemoteException {
    mClient.scheduleTransaction(this);
}

由代码可知,这里调用了IApplicationThread.scheduleTransaction()。这里的IApplicationThread来源于ClientTransaction.obtain()入参,向前追溯则是通过ActivityRecorder获取的,实际是前述启动流程中传递的caller【此处描述可能不够严谨,如有错误请评论或联系作者】。

这里我们首先应该找到 IApplicationThread的实现,如果你对ActivityThread有一定了解的话,可以知道其内部类 ApplicationThread 实现了 IApplicationThread.Stub:

{@link android.app.ActivityThread}

public final class ActivityThread extends ClientTransactionHandler {

    private class ApplicationThread extends IApplicationThread.Stub {
        // 忽略其他代码
        @Override
        public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
            ActivityThread.this.scheduleTransaction(transaction);
        }
    }
}

public abstract class ClientTransactionHandler {

    // Schedule phase related logic and handlers.

    /** Prepare and schedule transaction for execution. */
    void scheduleTransaction(ClientTransaction transaction) {
        transaction.preExecute(this);
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
    }
}

  class H extends Handler {
      
      public void handleMessage(Message msg) {
            switch (msg.what) {
                case EXECUTE_TRANSACTION:
                    final ClientTransaction transaction = (ClientTransaction) msg.obj;
                    mTransactionExecutor.execute(transaction);
                    if (isSystem()) {
                        // 系统进程内部的客户端事务在客户端循环,而不是在ClientLifecycleManager中循环,以避免在此消息被处理之前被清除。
                        transaction.recycle();
                    }
                    // TODO(lifecycler): Recycle locally scheduled transactions.
                    break;
            }
      }
  }

那么,调用IApplicationThread.scheduleTransaction(),实际上是向ActivityThread.H发送了Message,而后ActivityThread.H处理消息并调用了mTransactionExecutor.execute(transaction):

{@link android.app.servertransaction.TransactionExecutor}
public void execute(ClientTransaction transaction) {
    // 忽略代码

    executeCallbacks(transaction);

    executeLifecycleState(transaction);
    mPendingActions.clear();
    if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
}

/** Cycle through all states requested by callbacks and execute them at proper times. */
@VisibleForTesting
public void executeCallbacks(ClientTransaction transaction) {
    // 忽略代码

    final int size = callbacks.size();
    for (int i = 0; i < size; ++i) {
        final ClientTransactionItem item = callbacks.get(i);
        // 忽略代码

        item.execute(mTransactionHandler, token, mPendingActions);
        item.postExecute(mTransactionHandler, token, mPendingActions);
        // 忽略代码
    }
}

TransactionExecutor.execute()及后续executeCallbacks()最终调用到了 BaseClientRequest.execute(),也就是LaunchActivityItem.execute()。

LaunchActivityItem

在Android API 29及以上SDK中,Google将可以调度和执行的到客户端的回调消息封装为事务,包含Launch、Start、Stop等各种状态。

继承自 ClientTransactionItem 及上层 BaseClientRequest,核心方法为execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions),已知的ClientTransactionHandler 有ActivityThread。

{@link android.app.servertransaction.LaunchActivityItem}
@Override
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, mIsForward,
            mProfilerInfo, client, mAssistToken, mFixedRotationAdjustments);
    client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
    Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}

LaunchActivityItem.execute()中主要调用了client.handleLaunchActivity(r, pendingActions, null /* customIntent */),也就是调用了ActivityThread的相关方法。

当然的ActivityThread.handleLaunchActivity() 就是实际的新的Activity从创建到展示的流程了。

至此,其实整个从 startActivity的调用到目标Activity创建的调用流程就已经分析完毕了。

最后,我们来画一画整个流程的时序图。

分步骤时序图

Activity->ActivityManagerService a_ams

Activity检查及准备阶段 a_check

IApplication -> ActivityThread -> Activity ap_am_a

整体流程时序图

whole_line