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

简介: 【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 ;


目录
相关文章
|
2月前
|
存储 NoSQL Redis
Redis 新版本引入多线程的利弊分析
【10月更文挑战第16天】Redis 新版本引入多线程是一个具有挑战性和机遇的改变。虽然多线程带来了一些潜在的问题和挑战,但也为 Redis 提供了进一步提升性能和扩展能力的可能性。在实际应用中,我们需要根据具体的需求和场景,综合评估多线程的利弊,谨慎地选择和使用 Redis 的新版本。同时,Redis 开发者也需要不断努力,优化和完善多线程机制,以提供更加稳定、高效和可靠的 Redis 服务。
61 1
|
2月前
线程CPU异常定位分析
【10月更文挑战第3天】 开发过程中会出现一些CPU异常升高的问题,想要定位到具体的位置就需要一系列的分析,记录一些分析手段。
81 0
|
22天前
|
调度 开发者
核心概念解析:进程与线程的对比分析
在操作系统和计算机编程领域,进程和线程是两个基本而核心的概念。它们是程序执行和资源管理的基础,但它们之间存在显著的差异。本文将深入探讨进程与线程的区别,并分析它们在现代软件开发中的应用和重要性。
40 4
|
2月前
|
Android开发
Android面试之Activity启动流程简述
Android面试之Activity启动流程简述
94 6
|
2月前
|
消息中间件 Android开发 索引
Android面试高频知识点(4) 详解Activity的启动流程
Android面试高频知识点(4) 详解Activity的启动流程
31 3
|
2月前
|
缓存 前端开发 Android开发
Android实战之如何截取Activity或者Fragment的内容?
本文首发于公众号“AntDream”,介绍了如何在Android中截取Activity或Fragment的屏幕内容并保存为图片。包括截取整个Activity、特定控件或区域的方法,以及处理包含RecyclerView的复杂情况。
27 3
|
2月前
|
Android开发
Android面试之Activity启动流程简述
Android面试之Activity启动流程简述
20 0
|
3月前
|
消息中间件 Android开发 索引
Android面试高频知识点(4) 详解Activity的启动流程
讲解Activity的启动流程了,Activity的启动流程相对复杂一下,涉及到了Activity中的生命周期方法,涉及到了Android体系的CS模式,涉及到了Android中进程通讯Binder机制等等, 首先介绍一下Activity,这里引用一下Android guide中对Activity的介绍:
59 4
|
3月前
|
Android开发 开发者
Android面试之Activity启动流程简述
每个Android开发者都熟悉的Activity,但你是否了解它的启动流程呢?本文将带你深入了解。启动流程涉及四个关键角色:Launcher进程、SystemServer的AMS、应用程序的ActivityThread及Zygote进程。核心在于AMS与ActivityThread间的通信。文章详细解析了从Launcher启动Activity的过程,包括通过AIDL获取AMS、Zygote进程启动以及ActivityThread与AMS的通信机制。接着介绍了如何创建Application及Activity的具体步骤。整体流程清晰明了,帮助你更深入理解Activity的工作原理。
59 0
|
Java Android开发 调度