【Android 启动过程】Activity 启动源码分析 ( AMS -> ActivityThread、AMS 线程阶段 二 )(一)

文章目录

前言

一、热启动与冷启动选择

二、AMS 进程中执行的相关操作

三、通过 Binder 机制转到 ActivityThread 中执行的操作

总结

前言

上一篇博客 【Android 启动过程】Activity 启动源码分析 ( AMS -> ActivityThread、AMS 线程阶段 ) 分析的分支是启动 Activity 时 , 没有 Activity 对应的进程 , 需要先调用 Zygote 启动相应进程 , 然后再启动 Activity , 属于冷启动 ;


本篇博客补充下 " 热启动 " 的流程 ;






一、热启动与冷启动选择


在 ActivityStackSupervisor.startSpecificActivityLocked 方法中 , 判定要启动的 Activity 是否存在 , 决定要使用冷启动还是热启动 ;



如果启动时 , 发现已经存在 Activity 对应进程 , 那么执行下面的热启动方法 :


 

// 如果启动 Activity 时 , 发现进程存在 , 则直接启动 Activity , 热启动
                realStartActivityLocked(r, app, andResume, checkConfig);


如果启动时 , 发现不存在 Activity 对应进程 , 那么执行下面的冷启动方法 :


// 如果启动 Activity 时 , 发现进程不存在 , 则启动进程, 然后再启动 Activity , 冷启动 
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);



ActivityStackSupervisor.startSpecificActivityLocked 方法代码 :


public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener,
        RecentTasks.Callbacks {
    void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // 此活动的应用程序是否已在运行?
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);
        getLaunchTimeTracker().setLaunchTime(r);
        if (app != null && app.thread != null) {
            try {
                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {
                    // 如果它是一个标记为在多个进程中运行的平台组件,请不要添加此项,
                    // 因为它实际上是框架的一部分,因此在进程中作为单独的apk进行跟踪没有意义。
                    app.addPackage(r.info.packageName, r.info.applicationInfo.longVersionCode,
                            mService.mProcessStats);
                }
   
    // 如果启动 Activity 时 , 发现进程存在 , 则直接启动 Activity , 热启动
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity "
                        + r.intent.getComponent().flattenToShortString(), e);
            }
            // 如果抛出了死对象异常,则通过fall-through重新启动应用程序。
        }
  // 如果启动 Activity 时 , 发现进程不存在 , 则启动进程, 然后再启动 Activity , 冷启动 
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }
}


完整代码参考 /frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java ;






二、AMS 进程中执行的相关操作


在 ActivityStackSupervisor.realStartActivityLocked 启动 Activity ;


最终调用 mService.getLifecycleManager().scheduleTransaction(clientTransaction) 方法 , 启动相关 Activity 启动事物 ;



ActivityStackSupervisor.realStartActivityLocked 相关代码如下 :
public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener,
        RecentTasks.Callbacks {
    final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
                                          boolean andResume, boolean checkConfig) throws RemoteException {
        if (!allPausedActivitiesComplete()) {
            // 当有活动暂停时,我们将跳过开始任何新活动,直到暂停完成。
            // 注意:对于在暂停状态下启动的活动,我们也会这样做,因为它们将首先恢复,然后在客户端暂停。
            if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
                    "realStartActivityLocked: Skipping start of r=" + r
                            + " some activities pausing...");
            return false;
        }
        final TaskRecord task = r.getTask();
        final ActivityStack stack = task.getStack();
        beginDeferResume();
        try {
            r.startFreezingScreenLocked(app, 0);
            // 安排启动时间以收集有关慢速应用程序的信息。
            r.startLaunchTickingLocked();
            r.setProcess(app);
            if (getKeyguardController().isKeyguardLocked()) {
                r.notifyUnknownVisibilityLaunched();
            }
            // 让窗口管理器根据新的活动顺序重新评估屏幕方向。
            // 注意,这样做的结果是,它可以使用新的方向调用activity manager。
            // 我们不关心这一点,因为活动当前未运行,所以我们只是重新启动它。
            if (checkConfig) {
                // 推迟恢复,因为我们将很快启动新活动。
                // 我们不希望在确保配置和尝试恢复重点堆栈的*活动的同时,重复启动同一记录。
                ensureVisibilityAndConfig(r, r.getDisplayId(),
                        false /* markFrozenIfConfigChanged */, true /* deferResume */);
            }
            if (r.getStack().checkKeyguardVisibility(r, true /* shouldBeVisible */,
                    true /* isTop */)) {
                // 仅当基于keyguard状态允许活动可见时,我们才将可见性设置为true。
                // 这样可以避免在窗口管理器中将此设置为运动状态,
                // 而由于以后的调用而取消该设置,以确保将可见性设置回false的可见活动。
                r.setVisibility(true);
            }
            try {
                // 下面的代码是启动 Activity 的核心代码
                // Create activity launch transaction.
                final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
                        r.appToken);
                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, app.repProcState, r.icicle,
                        r.persistentState, results, newIntents, mService.isNextTransitionForward(),
                        profilerInfo));
                // 设置所需的最终状态。配置生命周期
                final ActivityLifecycleItem lifecycleItem;
                if (andResume) {
                    // 开启新的 Activity
                    lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
                } else {
                    // 终止 Activity
                    lifecycleItem = PauseActivityItem.obtain();
                }
                clientTransaction.setLifecycleStateRequest(lifecycleItem);
                // 安排事务。
                mService.getLifecycleManager().scheduleTransaction(clientTransaction);
                // 上面的代码是启动 Activity 的核心代码
            } catch (RemoteException e) {
            }
        } finally {
            endDeferResume();
        }
        return true;
    }
}


完整代码参考 /frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java ;


上一篇:太方便了!DLA消息回执,及时通知您的异步Query


下一篇:SQL Server锁分区特性引发死锁解析