AMS是ActivityManagerService的简称,看名字,似乎是Activity的manager,实际上,它管理的可不只是Activity。

系统启动流程

1
2
3
4
5
6
7
8
9
graph TD;
style A fill:#fff
style F fill:#5befb9
Z{{Boot ROM}} --> A([Boot Loader]);
A --> B(Kernel);
B --> C("init(pid=1)/C++ Framework Native");
C --> D(Zygote/Android Runtime);
D --> E(System Server/Java Framework);
E --> F(Apps);

面试题:一个应用启动,为什么不从init进程或者SystemServer进程fork,而是从Zygote进程fork。

Zygote作为一个孵化器,可以提前加载一些资源,这样fork时给予Copy-on-Write机制创建的其他进程能够直接利用这些资源,而不用重新加载。比如system_server就可以直接使用Zygote中的JNI函数、共享库、常用的类以及主题资源。

SystemServer相比Zygote多运行了AMS、WMS等服务,这些对于一个应用程序来说是不需要的,另外fork对多线程不友好,仅会将发起调用的线程拷贝到子进程,这可能会导致死锁,而SystemServer中肯定是有很多多线程的。

如何导致死锁的?

在POSIX标准中,fork行为是这样的:赋值整个用户空间的数据(通常使用copy-on-write的策略,所以可以实现速度很快)以及所有系统对象,然后仅复制当前线程到子进程。这里:所有父进程中别的线程,到了子进程都是突然蒸发掉的。

对于锁来说,从OS看,每个锁都有一个所有者,即最后依次lock它的线程。假设这样一个环境,在fork之前,有一个子线程lock了某个锁,获得了对锁的所有权,fork以后,在子进程中,所有的额外线程都人间蒸发了,而锁却被正常赋值了,在子进程看来,这个锁没有主人,所以没有任何人可以对它解锁,当子进程中的某个线程想lock这个锁时候,不再有任何手段可以解开了,程序发生死锁。

Zygote集成启动

1
2
3
4
5
6
graph TD;
A["init.cpp - main()"] --> B[解析init.zygote.rc];
B --> C["启动main类型服务 do_class_start()"];
C --> D["启动zygote服务 start()"];
D --> E["创建Zygote进程 fork()"];
E --> |execv|F["app_main.cpp - main()"];

System Server进程启动

1
2
3
4
5
6
7
8
9
graph TD;
A["app_main.cpp - main()"] --> B["AndroidRuntime.start()"];
B --> C["startVM()"];
C --> D["startReg()"];
D --> E["ZygoteInit.main()"];
E --> F["registerZygoteSocket()"];
F --> G["preload"];
G --> H["startSystemServer"];
H --> I["runSelectLoop"];

SystemServer.java

AMS启动流程

ActivityManagerService.java

在SystemServer的startBootstrapServices方法中,开始了AMS的启动。

AMS启动过程中做了哪些事?

adb shell dumpsys相关的一些process服务,比如meminfogfxinfodbinfo等,具体请参考setSystemProcess方法。

Activity启动流程

ActivityStactSupervisor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
flowchart LR;
A[ActivityStactSupervisor] --> B[mHomeStack];
A --> C[mFocusedStack];
subgraph ActivityStack["ActivityStack"]
subgraph TaskRecord
AR1[ActivityRecord]
AR2[ActivityRecord]
AR3[ActivityRecord]
end
subgraph TaskRecord2
AR4[ActivityRecord]
AR5[ActivityRecord]
AR6[ActivityRecord]
end
end
B --> ActivityStack;
C --> ActivityStack;

Activity启动简图

面试题:Zygote为什么不采用Binder机制进行IPC通信。

Binder机制中存在Binder线程池,是多线程的,如果Zygote采用Binder的话,就存在了上面说的fork多线程死锁问题了。其实严格来说,Binder机制不一定要多线程,所谓的Binder线程只不过是在循环读取Binder驱动消息而已,只注册一个Binder线程也是可以工作的,比如ServiceManager,实际上Zygote尽管没有采用Binder机制,它也不是单线程的,但它在fork前主动停止了其他线程,fork后重新启动了。

1
2
3
4
5
6
7
graph TD;
A([Launcher]) --> B{"SystemServer - AMS<br>(app是否启动)"};
B --> |否, 请求创建app进程|C[Zygote];
B -.-> |"是, 1. ActivityManager.getService()"|D(App):::app;
C -->|fork| D
D -->|"2. mgr.attachApplication(mAppThread, startSeq)"| B;
classDef app fill:#5befb9

Activity启动细节图

Launcher到AMS阶段

1
2
3
4
5
6
7
8
9
10
11
12
sequenceDiagram
participant A as Launcher
participant B as Activity
participant C as Instrumentation
participant D as IActivityManager
participant E as AMS

A ->> B: startActivity
B --> B: startActivityForResult
B ->> C: execStartActivity
C ->> D: startActivity
D ->> E: startActivity

AMS到ApplicationThread阶段

1
2
3
4
5
6
7
8
9
10
11
12
sequenceDiagram
participant A as AMS
participant B as ActivityStart
participant C as ActivityStackSupervisor
participant D as ActivityStack
participant E as ApplicationThread
A ->> A: startActivityStarter
A ->> B: startActivityMyWait
B ->> B: startActivityLocked
B ->> B: startActivity
B ->> B: startActivityUnchecked
B ->> C: startSpecificActivityLocked

ApplicationThread到Activity

本文采用CC-BY-SA-3.0协议,转载请注明出处
Author: boybeak