2-Activity进程启动流程

概念

ActivityThread

App 的入口,启动 App 后,会调用 ActivityThread.main (),开启 Looper、MessageQueue,与 ActivityManagerService 配合完成对 Activity 的管理。就是主线程

ActivityManagerService

负责了系统中四大组件的启动、切换、应用进程管理(创建进程)和调度工作。(是一个 system service 进程,系统进程,和一个 APP 一样)

activity 相关都交给了 ActivityTaskManagerService
unknown_filename.6|600

ActivityTaskManagerService

  • 启动应用程序 Activity 已经走到 ActivityTaskManagerService 中,如果你熟悉前以往版本的 Android 源码,你肯定会知道 ActivityManagerService,而在 Android 10 中则将 AMS 用于管理 Activity 及其容器(任务,堆栈,显示等)的系统服务分离出来放到 ATMS 中,也许是谷歌不想让 AMS 的代码越来越膨胀吧 (Android 10中 AMS 代码有一万九千行
  • ATMS 负责管理系统所有 Activity,所以应用 startActivity 最终会通过 Binder 调用到 ATMS 的 startActivity 方法,ATMS 启动一个 Activity 之前会做一些检查,例如权限、是否在清单文件注册,是否需要创建新的进程等,然后就可以启动了,ATMS 是一个系统服务,又涉及到跨进程调用,这个跨进程同样采用 Binder,媒介是通过 ActivityThread 的内部类 ApplicationThread,AMS 将生命周期跨进程传到 ApplicationThread,然后 ApplicationThread 再分发给 ActivityThread 内部的 Handler,这时候生命周期已经回调到应用主线程了,回调 Activity 的各个生命周期方法。

打开 Acitivty 整个流程

unknown_filename.12|600

unknown_filename.14

  1. 点击图标后 Launcher 进程会通过 Binder 机制向 AMS 发起打开 Activity 的请求【IPC->Binder】
  2. AMS 会通过 ActivityStarter 处理 Intent 和 Flag 启动模式等相关内容,做一些检查,例如权限、是否在清单文件注册,是否需要创建新的进程,如果需要创建进程,通过 Socket 通知 zygote 进程【IPC->Socket】
  3. zygote 进程会进行孵化 (虚拟机和资源的复制),然后 fork 出新进程(然后在新的进程里)
  4. 然后 zygote 进程会通过 invokeDynamicMain ()方法调用到 ActivityThread 的 main 方法(也就是 APP 的入口)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static void main(String[] args) {
...
Looper.prepareMainLooper();
...
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);

if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}

if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
}
  • 主线程 Looper 和 Handler 的创建、开启主线程 Looper 的消息循环。
  • ActivityThread. attach () 建立 Binder 通道
1
2
3
4
5
6
7
8
9
private void attach(boolean system, long startSeq) {
...
final IActivityManager mgr = ActivityManager.getService();
try {
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
  • IActivityManager. attachApplication—->(通知 AMS 打开 activity RootActivityContainer (attachApplication)—-> realStartActivityLocked—->scheduleTransaction)
  • ApplicationThread 收到 EXECUTE_TRANSACTION
  • ActivityThread.performLaunchActivity() 中
    • loadApk 反射创建 application,activity
    • activity. attach 里 window,windowmanager 创建出来,和 activity 建立联系 [[4-WMS#整个流程]]
    • mInstrumentation.callActivityOnCreate 调 prePerformCreate
    • Activity.onCreate () 调用 setContentView () 解析xml,最后通过 phoneWindow 把 DecorView 创建出来了
    • Activity.onResume () 将 Activity DecorView 与 WindowManager 建立联系,并对所有子 View 进行渲染并显示。

android10 Activity 启动流程详细

https://juejin.cn/post/6844904145191698439#heading-8
unknown_filename.7|1000

第一步

unknown_filename.8|1200

第二步

unknown_filename.9|1200

如果进程 没创建创建进程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
   //ActivityStackSupervisor.java
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);

if (wpc != null && wpc.hasThread()) {
try {
// app.thread 不为空,表示对应的进程存在,直接启动activity
realStartActivityLocked(r, wpc, andResume, checkConfig); //打开acitivty
return;
}
...
}
try {
//startProcess 进程不存在,创建进程
final Message msg = PooledLambda.obtainMessage(
ActivityManagerInternal::startProcess, mService.mAmInternal, r.processName,
r.info.applicationInfo, knownToBeDead, "activity", r.intent.getComponent());
mService.mH.sendMessage(msg);
}
}


/** Target client. */
private IApplicationThread mClient;
public void schedule() throws RemoteException {
mClient.scheduleTransaction(this); //1
}

mClient 则代表要启动的应用程序进程的 IApplicationThread,而当前还处于 ATMS 服务的进程,也就是 SystemServer 进程,这时 ATMS 要与即将启动的应用程序进程通信则通过 IApplicationThread 来执行 AIDL

IApplicationThread 实现为 ApplicationThread,它是 ActivityThread 的内部类,所以前面也说过 ApplicationThread 为进程间通信的桥梁。

注释1处则相当于是 IApplicationThread. scheduleTransaction,并将包含要启动 Activity 信息的 ClientTransaction 传递到了应用程序进程

第三步

回到 APP 中的是这个消息:EXECUTE_TRANSACTION
unknown_filename.10

ActivityThread 关键方法
下面在 performLaunchActivity 代码中
想想代码: [[3-Activity 生命周期#performLaunchActivity]]

注释1处获取了前面保存启动应用程序信息的 ActivityClientRecord 中的应用程序信息,包括应用程序在清单文件中注册了哪些四大组件,启动的根 Activity 是什么,
并在注释2处通过 getPackageInfo 方法获取 LoadedApk 描述对应 Apk 文件资源,
注释3处的 ComponentName 类获取则对应启动 Activity 的包名和类名,
注释4处则生成了启动应用程序的 Base 上下文环境 Context,
注释5处通过注释3获取的类名,通过类加载器和 Intent 对象实例化了 Activity 对象,

1
2
3
4
5
public @NonNull Activity instantiateActivity (@NonNull ClassLoader cl, @NonNull String className,
@Nullable Intent intent)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return (Activity) cl.loadClass (className). newInstance ();
}

注释6则根据注释2处获取 Apk 描述对象 LoadedApk 创建了应用程序的 Application 对象,并在 makeApplication 方法中调用了它的 OnCreate 方法,所以应用程序最新启动的是 Application 才到根 Activity

1
2
3
4
5
6

public @NonNull Application instantiateApplication (@NonNull ClassLoader cl,
@NonNull String className)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return (Application) cl.loadClass (className). newInstance ();
}

注释7处则前面创建的 Context、Application、Window 对象与 Activity 关联来初始化 Activity,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
final void attach (Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent,...) {
attachBaseContext (context);
...
mWindow = new PhoneWindow (this, window, activityConfigCallback);
...
if (mParent != null) {
mWindow.setContainer (mParent.getWindow ());
}
mWindowManager = mWindow.getWindowManager ();
...
}

最后注释8处还继续调用了 Instrumentation 对象的 callActivityOnCreate 方法。调用 onCreate 方法

四大组件主线程的消息模型
重要
  主线程消息循环开始以后, ActivityThread 还需要一个 handler 来和消息队列进行交互, 这个 handler 就是 ActivityThread. H,它内部定义了一组消息类型,包括四大组件的启动和停止等过程。
   ActivityThread 通过ApplicationThread 和 AMS 进行进程通信,AMS 以进程通信的方式完成 ActivityThread 的请求后回调 ApplicationThread 中的 Binder 方法,然后 ApplicationThread 会向 H 发送消息(sendMessage), H 收到消息后会将 ApplicationThread 逻辑切换到 ActivityThread 中去执行, 即切换到主线程中执行, 这就是主线程的消息模型(binder 线程到主线程)。

ActivityManager

ActivityManager 是客户端用来管理系统中正在运行的所有 Activity 包括 Task、Memory、Service 等的一些信息。在 ActivityManager 中有大量的 get ()方法,他只是提供信息给 AMS,由 AMS 去完成交互和调度工作。AMS 和 ActivityManager 之间通信需要利用 Binder 来完成。
有这些方法:
getLargeMemoryClass、getTotalRam、getAppTasks、moveTaskToFront、getMemoryInfo
unknown_filename.11


应用程序进程启动流程

深入理解 Android 之应用程序进程启动流程 (Android 10) - 掘金
https://juejin.cn/post/6844904119803576333#commen

frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor. java
打开 activity 时发现应用没启动,就创建进程

ActivityManagerService 到 Zygote

ActivityManagerInternal 实现类 LocalService 是 SystemServer 进程的本地服务 Service,通过本地服务注册到 LocalServices 中,而 AMS 也是运行在 SystemServer 进程,则可以直接使用 LocalService。

unknown_filename.1|1300

frameworks/base/core/java/android/os/ZygoteProcess. java

1
2
3
4
5
6
7
8
9
10
private void attemptConnectionToPrimaryZygote () throws IOException {
if (primaryZygoteState == null || primaryZygoteState.isClosed ()) {
primaryZygoteState =
ZygoteState.connect (mZygoteSocketAddress, mUsapPoolSocketAddress);//1

maybeSetApiBlacklistExemptions (primaryZygoteState, false);
maybeSetHiddenApiAccessLogSampleRate (primaryZygoteState);
maybeSetHiddenApiAccessStatslogSampleRate (primaryZygoteState);
}
}

由注释1调用 ZygoteState 的 connect 方法来打开 Socket 连接,mZygoteSocketAddress 则是名称为 zygote 的 Socket 服务, 并传递启动应用程序进程参数

Zygote 启动应用程序进程

unknown_filename.2

1
String zygoteSocketName = "zygote";//3

注释3出设置 Socket 连接名称为 zygote

1
2
3
4
5
6
caller = zygoteServer.runSelectLoop (abiList);//8
if (caller != null) {
caller.run (); //9
}


注释8的 runSelectLoop 方法则是 Zygote 进程等待接收 AMS 请求启动应用程序进程的关键方法,如果获取到就执行

1
2
3
4
Runnable processOneCommand (ZygoteServer zygoteServer) {
...
args = Zygote.readArgumentList (mSocketReader);

传过来的参数有:进程 ID、包名

frameworks/base/core/java/com/android/internal/os/ZygoteServer. java

1
2
3
4
5
6
7
8
9
10
11
12
13
Runnable runSelectLoop (String abiList) {
......
while (true) {
...
// 从 Zygote 服务器套接字接受会话套接字
try {
ZygoteConnection connection = peers.get (pollIndex);
final Runnable command = connection.processOneCommand (this); //1
......
return command;
}
.......
}

通过一个死循环等待接收请求, 底层 Native fork 进程,if (pid == 0) 就创建成功,创建成功后创建 binder 线程池、则当前应用程序就拥有了 Binder 通信的能力,通过反射创建 android. app. ActivityThread,调用 main 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
protected static Runnable findStaticMain (String className, String[] argv,
ClassLoader classLoader) {
Class<?> cl;

try {
cl = Class.forName (className, true, classLoader);//1
} catch (ClassNotFoundException ex) {
throw new RuntimeException (
"Missing class when invoking static main " + className,
ex);
}

Method m;
try {
m = cl.getMethod ("main", new Class[] { String[]. class });//2
}
......
return new MethodAndArgsCaller (m, argv);
}

run 调用 main 方法

1
2
3
4
5
6
7
8
9
10
static class MethodAndArgsCaller implements Runnable {
public void run () {
try {
mMethod.invoke (null, new Object[] { mArgs }); //1
}
...
}
}


ActivityThread 是每个应程序主线程的管理类,到此,应用程序进程启动完成,当 ATMS 与应用程序 Binder 通信通过 IApplicationThread 为 ActivityThread 的内部类,然后调用 ActivityThread 的 performLaunchActivity 方法来启动 Activity。

Socket 通信方式

Socket 通信方式也是 C/S 架构,在 Android 系统中采用 Socket 通信方式的主要有:

  • zygote:用于孵化进程,system_server 创建进程是通过 socket 向 zygote 进程发起请求;
  • installd:用于安装 App 的守护进程,上层 PackageManagerService 很多实现最终都是交给它来完成;
    Socket 方式更多的用于 Android framework 层与 native 层之间的通信.

ZygoteServer
ZygoteServer 类负责创建和管理 Zygote 的服务器套接字。通过 LocalServerSocket 创建

具体来说,通过调用 ServerSocket 类的构造函数创建一个服务器套接字 ServerSocket 对象,并绑定到指定的端口上。然后使用 ServerSocket 对象的 accept () 方法监听客户端的连接请求。

一旦有客户端发起连接请求,accept () 方法会返回一个新的 Socket 对象,表示与客户端建立的连接。然后,可以使用返回的 Socket 对象与客户端进行通信,发送和接收数据(getInputStream)。

这里的 Zygote 服务器套接字负责监听并接受来自客户端的命令请求,然后根据请求的内容执行相应的操作,并将结果返回给客户端。在 zygoteServer.runSelectLoop (abiList) 中的循环中,不断接收和处理客户端的请求

unknown_filename.15|1000

总结

unknown_filename.2

其他问题

SystemServiceManager 和 ServiceManager 的区别和作用

[[Binder 进程间通信#ServiceManager]]

  • ServiceManager:是一个通用的服务管理类,用于管理系统中所有服务。
  • SystemService:是一个具体的 ServiceManager 实例,用于管理系统服务。

作用

  • ServiceManager:提供通用的服务管理功能,包括服务注册、服务获取、服务启动、服务停止等。其他进程可以通过ServiceManager获取SystemServiceManager实例,并通过SystemServiceManager来访问系统服务。
  • SystemService:用于管理系统服务,包括ActivityManagerService、WindowManagerService、PowerManagerService等。

ams-Zygote 通信为什么用 Socket

  1. 先后时序问题:
    binder 驱动是早于 init 进程加载的。而 init 进程是安卓系统启动的第一个进程。安卓中一般使用的 binder 引用,都是保存在 ServiceManager 进程中的,而如果想从 ServiceManager 中获取到对应的 binder 引用,前提是需要注册。虽然 Init 进程是先创建 ServiceManager,后创建 Zygote 进程的。虽然 Zygote 更晚创建,但是也不能保证 Zygote 进程去注册 binder 的时候,ServiceManager 已经初始化好了。注册时间点无法保证,AMS 无法获取到 Zygote 的 binder 引用,这是原因之一。

image.png

unknown_filename.4|900

为何 Binder/Socket 用于进程间通信,能否用于线程间通信呢?

  • 答案是肯定,对于两个具有独立地址空间的进程通信都可以,当然也能用于共享内存空间的两个线程间通信,这就好比杀鸡用牛刀。接着可能还有人会疑惑,那 handler 消息机制能否用于进程间通信?答案是不能,Handler 只能用于共享内存地址空间的两个线程间通信,即同进程的两个线程间通信。
  • Handler 消息机制用于同进程的线程间通信,其核心是线程间共享内存空间,而不同进程拥有不同的地址空间
  • Handler 可以是 UI 线程向工作线程发送消息,也可以是多个工作线程之间通过 handler 发送消息

Instrumentation (ins 追妹忒神)是什么?
管理着组件 Application, Activity,Service 等的创建,生命周期调用。

1
2
3
int = Process. start (“android . app . ActivityThread” , 
mSimpleProcessManagement? app. processName : gid, debugFlags, null);

什么是 actityrecord

一个 Activityrecord 对应一个 Activity, 保存了一个 Activity 的所有信息; 但是一个 Activity 可能会有多个 Activityrecord, 因为 Activity 可以被多次启动,这个主要取决于其启动模式

什么是 Taskrecord

Taskrecord, 内部维护一个 Arraylist<Activityrecord 用来保存 Activityrecord.
一个 Taskrecord 由一个或者多个 Actvityrecord 组成,这就是我们常说的任务栈,具有后进先出的特点。

https://blog.csdn.net/qijinglai/article/details/81163574

handleLaunchActivity 方法都做哪些事呢?

  1. 通过 Instrumentation newActivity 方法,创建要启动的 Activity 实例
  2. 为这个 Activity 创建一个上下文 Context 对象,并与 Activity 进行关联
  3. 通过 Instrumentation callActivityOnCreate 方法,执行 Activity on Create 方法,从而启动 Activity

2-Activity进程启动流程
http://peiniwan.github.io/2024/04/474d141336eb.html
作者
六月的雨
发布于
2024年4月6日
许可协议