大型 Bat 面试知识总结分享—AMS 在 Android 起到什么作用?简单的分析下 Android 的源码
AMS 由 SystemServer 的 ServerThread 线程创建;
1. 初识 ActivityManagerService 总结
本节所分析的 4 个关键函数均较复杂,与之相关的知识点总结如下:
AMS 的 main 函数:创建 AMS 实例,其中最重要的工作是创建 Android 运行环境,得到一个 ActivityThread 和一个 Context 对象。
AMS 的 setSystemProcess 函数:该函数注册 AMS 和 meminfo 等服务到 ServiceManager 中。另外,它为 SystemServer 创建了一个 ProcessRecord 对象。由于 AMS 是 Java 世界的进程管理及调度中心,要做到对 Java 进程一视同仁,尽管 SystemServer 贵为系统进程,此时也不得不将其并入 AMS 的管理范围内。
AMS 的 installSystemProviders:为 SystemServer 加载 SettingsProvider。
AMS 的 systemReady:做系统启动完毕前最后一些扫尾工作。该函数调用完毕后,HomeActivity 将呈现在用户面前。 对 AMS 调用轨迹分析是我们破解 AMS 的第一条线,希望读者反复阅读,以真正理解其中
涉及的知识点,尤其是和 Android 运行环境及 Context 相关的知识。
2. startActivity
总结 本文详细 startActivity 的整个启动流程,
流程[2.1 ~2.4]:运行在调用者所在进程,比如从桌面启动 Activity,则调用者所在进程为 launcher 进程,launcher 进程利用 ActivityManagerProxy 作为 Binder Client,进入 system_server 进程(AMS 相应的 Server 端)。
流程[2.5 ~2.18]:运行在 system_server 系统进程,整个过程最为复杂、核心的过程,下面其中部分步骤:
流程[2.7]:会调用到 resolveActivity(),借助 PackageManager 来查询系统中所有符合要求的 Activity,当存在多个满足条件的 Activity 则会弹框让用户来选择;
流程[2.8]:创建 ActivityRecord 对象,并检查是否运行 App 切换,然后再处理 mPendingActivityLaunches 中的 activity;
流程[2.9]:为 Activity 找到或创建新的 Task 对象,设置 flags 信息;
流程[2.13]:当没有处于非 finishing 状态的 Activity,则直接回到桌面; 否则,当 mResumedActivity 不为空则执行 startPausingLocked()暂停该 activity;然后再进入 startSpecificActivityLocked()环节;
流程[2.14]:当目标进程已存在则直接进入流程[2.17],当进程不存在则创建进程,经过层层调用还是会进入流程[2.17];
流程[2.17]:system_server 进程利用的 ATP(Binder Client),经过 Binder,程序接下来进入目标进程。
流程[2.19 ~2.18]:运行在目标进程,通过 Handler 消息机制,该进程中的 Binder 线程向主线程发送 H.LAUNCH_ACTIVITY,最终会通过反射创建目标 Activity,然后进入 onCreate()生命周期。 从另一个角度下图来概括:
启动流程:
点击桌面 App 图标,Launcher 进程采用 Binder IPC 向 system_server 进程发起 startActivity 请求;
system_server 进程接收到请求后,向 zygote 进程发送创建进程的请求;
Zygote 进程 fork 出新的子进程,即 App 进程;
App 进程,通过 Binder IPC 向 sytem_server 进程发起 attachApplication 请求;
system_server 进程在收到请求后,进行一系列准备工作后,再通过 binder IPC 向 App 进程发送 scheduleLaunchActivity 请求;
App 进程的 binder 线程(ApplicationThread)在收到请求后,通过 handler 向主线程发送 LAUNCH_ACTIVITY 消息;
主线程在收到 Message 后,通过发射机制创建目标 Activity,并回调 Activity.onCreate()等方法。 到此,App 便正式启动,开始进入 Activity 生命周期,执行完 onCreate/onStart/onResume 方法,UI 渲染结束后便可以看到 App 的主界面。
startActivity 后半程总结
starActivity 总结
Activity 的启动就介绍到这里。这一路分析下来,相信读者也和笔者一样觉得此行绝不轻松。先回顾一下此次旅程:
行程的起点是 am。am 是 Android 中很重要的程序,读者务必要掌握它的用法。我们利用 am start 命令,发起本次目标 Activity 的启动请求。
接下来进入 ActivityManagerService 和 ActivityStack 这两个核心类。对于启动 Activity 来说,这段行程又可分细分为两个阶段:第一阶段的主要工作就是根据启动模式和启动标志找到或创建 ActivityRecord 及对应的 TaskRecord;第二阶段工作就是处理 Activity 启动或切换相关的工作。
首先讨论了 AMS 直接创建目标进程并运行 Activity 的流程,其中涉及目标进程的创建,在目标进程中 Android 运行环境的初始化,目标 Activity 的创建以及触发 onCreate、onStart 及 onResume 等其生命周期中重要函数调用等相关知识点。
接着又讨论了 AMS 先 pause 当前 Activity,然后再创建目标进程并运行 Activity 的流程。其中牵扯到两个应用进程和 AMS 的交互,其难度之大可见一斑。 读者在阅读本节时,务必要区分此旅程中两个阶段工作的重点:其一是找到合适的 ActivityRecord 和 TaskRecord;其二是调度相关进程进行 Activity 切换。在 SDK 文档中,介绍最为详细的是第一阶段中系统的处理策略,例如启动模式、启动标志的作用等。第二阶段工作其实是与 Android 组件调度相关的工作。SDK 文档只是针对单个 Activity 进行生命周期方面的介绍。 坦诚地说,这次旅程略过不少逻辑情况。原因有二,一方面受限于精力和篇幅,另方面是作为调度核心类,和 AMS 相关的代码及处理逻辑非常复杂,而且其间还夹杂了与 WMS 的交互逻辑,使复杂度更甚。再者,笔者个人感觉这部分代码绝谈不上高效、严谨和美观,甚至有些丑陋(在分析它们的过程中,远没有研究 Audio、Surface 时那种畅快淋漓的感觉)。 此处列出几个供读者深入研究的点:
各种启动模式、启动标志的处理流程。
Configuration 发生变化时 Activity 的处理,以及在 Activity 中对状态保存及恢复的处理流程。
Activity 生命周期各个阶段的转换及相关处理。Android 2.3 以后新增的与 Fragment 的生命周期相关的转换及处理。
3. 广播处理总结
4. startService 流程图
总结 5.1 流程说明 在整个 startService 过程,从进程角度看服务启动过程
Process A 进程:是指调用 startService 命令所在的进程,也就是启动服务的发起端进程,比如点击桌面 App 图标,此处 Process A 便是 Launcher 所在进程。
system_server 进程:系统进程,是 java framework 框架的核心载体,里面运行了大量的系统服务,比如这里提供 ApplicationThreadProxy(简称 ATP),ActivityManagerService(简称 AMS),这个两个服务都运行在 system_server 进程的不同线程中,由于 ATP 和 AMS 都是基于 IBinder 接口,都是 binder 线程,binder 线程的创建与销毁都是由 binder 驱动来决定的,每个进程 binder 线程个数的上限为 16。
Zygote 进程:是由 init 进程孵化而来的,用于创建 Java 层进程的母体,所有的 Java 层进程都是由 Zygote 进程孵化而来;
Remote Service 进程:远程服务所在进程,是由 Zygote 进程孵化而来的用于运行 Remote 服务的进程。主线程主要负责 Activity/Service 等组件的生命周期以及 UI 相关操作都运行在这个线程; 另外,每个 App 进程中至少会有两个 binder 线程 ApplicationThread(简称 AT)和 ActivityManagerProxy(简称 AMP),当然还有其他线程,这里不是重点就不提了。
图中涉及 3 种 IPC 通信方式:Binder、Socket 以及 Handler,在图中分别用 3 种不同的颜色来代表这 3 种通信方式。一般来说,同一进程内的线程间通信采用的是 Handler 消息队列机制,不同进程间的通信采用的是 binder 机制,另外与 Zygote 进程通信采用的 Socket。
启动流程:
Process A 进程采用 Binder IPC 向 system_server 进程发起 startService 请求;
system_server 进程接收到请求后,向 zygote 进程发送创建进程的请求;
zygote 进程 fork 出新的子进程 Remote Service 进程;
Remote Service 进程,通过 Binder IPC 向 sytem_server 进程发起 attachApplication 请求;
system_server 进程在收到请求后,进行一系列准备工作后,再通过 binder IPC 向 remote Service 进程发送 scheduleCreateService 请求;
Remote Service 进程的 binder 线程在收到请求后,通过 handler 向主线程发送 CREATE_SERVICE 消息;
主线程在收到 Message 后,通过发射机制创建目标 Service,并回调 Service.onCreate()方法。 到此,服务便正式启动完成。当创建的是本地服务或者服务所属进程已创建时,则无需经过上述步骤 2、3,直接创建服务即可。
5. AMS 中的进程管理
前面曾反复提到,Android 平台中很少能接触到进程的概念,取而代之的是有明确定义的四大组件。但是作为运行在 Linux 用户空间内的一个系统或框架,Android 不仅不能脱离进程,反而要大力利用 Linux OS 提供的进程管理机制和手段,更好地为自己服务。作为 Android 平台中组件运行管理的核心服务,ActivityManagerService 当仁不让地接手了这方面的工作。目前,AMS 对进程的管理仅涉及两个方面:
调节进程的调度优先级和调度策略。
调节进程的 OOM 值。
评论