Fork me on GitHub

Android-Framework-AMS专项-Activity启动的整体流程与第一个阶段解读参数

Activity 启动整体流程分析

我们把 Activity 的启动简单分为几个部分

  • Intent

    startActivity(intent):
    ActivityA ActivityB

  • 解析 Activity 启动参数
    ActivityRecord

  • activityStack ActivityRecord,管理和启动 ActivityB

  • AMS:
    activityStackSupervisor: 封装 clientTransaction(触发事件)

  • 通信的流程:clientTransaction
    Application: process Activit

Activity 启动第一阶段解析参数

ActivityStarter:解析 Activity 启动参数,每一个 Activity 启动都会有一个 Starter 去启动它。
ActivityStartController:Controller 回去生产 Starter 对象,控制 Starter 的创建。

Q:为什么需要 ActivityStartController?

AMS 和 ATMS

在 Android 操作系统中,ATMS(ActivityTaskManagerService)和AMS(ActivityManagerService)是两个关键的系统服务,负责管理应用程序的生命周期和任务栈。它们在 Android 的多任务处理和应用管理方面扮演着重要角色。随着 Android 系统的发展,这两个服务的职责和架构也发生了一些变化。下面是它们之间主要的区别:

  1. 职责分工

    • AMS(ActivityManagerService):在 Android 10 及其之前的版本中,AMS 是负责管理系统中的所有活动(Activities)、应用进程和服务的核心服务。它处理应用的启动、切换、生命周期管理等任务。
    • ATMS(ActivityTaskManagerService):从 Android 10(API 级别 29)开始引入,ATMS 负责管理活动和任务的栈管理(Activity and Task Stack Management)。这意味着 ATMS 处理应用的 UI/界面任务,如任务视图、活动栈、分屏模式和最近应用的管理。ATMS 实质上是从 AMS 中拆分出来的,专注于任务和活动栈的管理,而让 AMS 能更专注于后台进程和应用管理。
  2. 架构变化

    • 随着 Android 系统的发展,其架构也在不断演进。引入 ATMS 是 Android 系统为了更好地模块化和清晰地区分不同服务的职责而做的改变。这种变化有助于简化系统服务的管理,使得系统架构更加清晰,同时也为未来的扩展和维护提供了便利。
  3. 目的

    • 分拆 AMS 和引入 ATMS 的目的是为了更好地分离和管理 Android 系统中的活动和任务栈管理逻辑,从而提高系统的稳定性和可维护性。ATMS 的引入,让 AMS 能够更加专注于进程管理和服务管理,而不是同时处理与 UI/界面相关的复杂逻辑。

总结来说,ATMS 和 AMS 在 Android 10 之后的版本中共同工作,以更高效和清晰的方式管理应用的生命周期和用户界面任务。ATMS 的引入是 Android 系统架构演进的一个例证,显示了 Android 团队在不断追求更好的系统管理和性能优化方面的努力。

ActivityStartController

Android 10 之前的版本,ActivityStartController 是在 AMS 的 initialize 时创建
Android 10 开始,AMS 分离出了一些职责到 ATMS 中,包含了 initialize

starter,factory,pool 与 recycle,reset

在这个 initalize 中初始化了 ActivityStartController
ActivityStartController 初始化时去获取 starter

实际上是由 ActivityStartController 初始化时去 创建了一个 Factory
这个 Factory 是定义在 ActivityStartController 内部的 DefaultFactory,通过 DefaultFactory 的 obtain 函数去获取一个 ActivityStarter

DefaultFactory 中构建了一个 synchronizedPool 复用池子,就和 Hanlder 一样,通过 obtain 去获取 ActivityStarter,设置三个缓存
采用享元模式去复用,避免内存抖动,同样的,使用完之后要去 recycle,recycle 的时候要去 reset,之后添加回 pool

所以 本质上是使用工厂模式去建造 ActivityStartController 缓存池,并管控 ActivityStartController 的复用,由 AMS 创建

Activity 的启动参数到底被谁持有了?

activity 的启动参数实际上是被添加到了 ActivityStarter 的 Request 中,之后执行 ActivityStarter 的 execute 函数

Request 是 Activity 的内部类,在这个内部类中包含了 Activity 启动过程中一系列的交互参数
比如我们要从 Activity A 启动 Activity B,这个过程中需要记录 Activity A 与 Activity B 的核心参数( 如果我们对 Activity A 启动 Activity B 之后,Activity A 和 B 生命周期函数的执行顺序有所了解,就非常容易理解这里为什么需要记录 A B 双方的核心参数,启动 B 的过程也是 A B 进行交互的过程)

ActivityStarter 的 execute 函数会执行 executeRequest, 这时候 ActivityStarter 就会去创建一个 ActivityRecord,这就是我们要启动的 Activity

在启动之前,会先执行 ActivityStartController 的 doPendingActivityLaunches 函数
这个函数是用来启动那些没有来得及启动的 Activity(举个例子,在启动之前按了 Home 键)

之后再调用 StartActivityUnchecked,其中调用 StartActivityInner
这里注意下 StartActivityInner 头两个参数是 final ActivityRecord r,ActivityRecord sourceRecord
这个函数里会计算 ActivityRecord (要启动的 Activity 的 task 标志),也就是启动模式,接着计算 sourceRecord(源 Activity)所在的 task,将计算后的启动模式 mLaunchFlags 设置给 Intent ( mIntent.setFlags(mLaunchFlags)

Launcher 启动创建黑白屏

注意完成上述操作之后我们去调用 Launcher 去启动一个 Activity 的时候,为了让用户知道我们已经进行了响应,会启动一个黑白屏

Q:这个时候 Activity 有启动吗?

A:并没有,上述操作只是在构建一个 Activity 的启动流程,并没有真正的去启动一个 Activity,因为 Activity 必须依附于一个进程存在,所以黑白屏是为了表示已经开始响应启动流程,但是进程的创建是一个相对缓慢的过程,之后进程创建之后才会启动 Activity

Activity的真正启动

启动完黑白屏之后,通过调用 mRootWindowContainer.resumeFocusedStackTopActivities 启动 Activity

首先,什么是 RootWindowContainer,注释上写 RootWindowContainer 就是 WindowContainer 的根容器,管理了所有窗口容器,
设备上所有的窗口(Window)、显示(Display)都是由它管理的 它通过 RootWindowContainer 来检查当前任务栈顶部的 Activity 是否真的可见。

在这个过程中,RootWindowContainer 会考虑多个因素来确定一个 Activity 的可见性,包括但不限于:

  • 屏幕的显示状态:例如,如果设备处于锁屏状态,则处于前台的 Activity 可能不会被认为是可见的。
  • 其他应用的窗口:例如,如果有一个全屏模式的应用或是一个浮动窗口覆盖在当前 Activity 上方,可能会影响当前 Activity 的可见性。
  • 系统对话框或通知:这些元素也可能覆盖在活动 Activity 上方,影响其可见性。
  • 分屏模式:在分屏模式下,两个 Activity 可以同时处于可见状态,RootWindowContainer 需要管理这些 Activity 的可见性和布局。

基于上述因素的判断,如果 RootWindowContainer 确定任务栈顶部的 Activity 是可见的,resumeFocusedStackTopActivities 方法就会继续执行,恢复该 Activity。这个过程涉及调用 ActivityonResume() 方法,使其成为用户可以与之交互的活动界面。

这一机制确保了 Android 系统在恢复 Activity 时能够正确地管理用户界面的状态和交互,保持应用的流畅运行和用户体验的一致性。

当启动一个新的 Activity 时,resumeFocusedStackTopActivities 方法负责将这个新的 Activity 放置到正确的任务栈和位置上。如果判断结果为 !resumeOnDisplay,并且 focusedStack != null,那么就会执行 focusedStack.resumeTopActivityUncheckLocked,进入启动的第二阶段

,