系统启动Zygote
# 01.系统启动与Zygote
# 目录介绍
- 一、引言:按下电源键之后发生了什么
- 二、BootLoader与Linux内核启动
- 2.1 硬件上电与BootLoader
- 2.2 boot.img的结构
- 2.3 Linux内核的初始化
- 2.4 Android内核与标准Linux的差异
- 三、Init进程:Android世界的开端
- 3.1 Init进程的角色
- 3.2 Init进程源码分析
- 3.3 属性服务的实现原理
- 四、Init.rc解析与服务启动
- 4.1 init.rc的语法结构
- 4.2 Zygote服务的声明
- 4.3 服务启动的触发机制
- 五、Zygote进程的诞生
- 5.1 从app_process到ZygoteInit
- 5.2 app_process的源码分析
- 5.3 虚拟机的创建过程
- 5.4 ZygoteInit.main()的核心逻辑
- 六、Zygote的Fork机制
- 6.1 为什么使用Fork而不是New
- 6.2 Copy-On-Write(COW)原理
- 6.3 Fork过程的源码分析
- 6.4 USAP(Unspecialized App Process)池
- 七、SystemServer的启动流程
- 7.1 SystemServer的Fork
- 7.2 SystemServer.main()的核心逻辑
- 7.3 服务启动的三个阶段
- 7.4 服务启动的依赖关系
- 八、系统服务的注册与启动
- 8.1 ServiceManager的角色
- 8.2 系统服务的注册过程
- 8.3 SystemServiceManager的生命周期管理
- 九、Launcher的启动与桌面显示
- 9.1 AMS启动Launcher的时机
- 9.2 Launcher的角色与启动流程
- 9.3 开机广播的发送
- 十、Application进程的创建过程
- 10.1 完整的应用启动链路
- 10.2 AMS请求Zygote的通信过程
- 10.3 ActivityThread.main():应用的真正入口
- 十一、预加载机制与启动优化
- 11.1 Zygote预加载的内容
- 11.2 预加载的内存效益分析
- 11.3 预加载类的选择策略
- 11.4 启动速度优化策略
- 十二、Android启动中的关键设计思想
- 12.1 进程隔离与安全模型
- 12.2 分层启动的设计哲学
- 12.3 单一职责与服务化
- 12.4 预加载+COW的"空间换时间"哲学
- 十三、面试高频问题与深度分析
- 13.1 Zygote为什么用Socket而不用Binder通信?
- 13.2 SystemServer为什么不直接启动,而要从Zygote fork?
- 13.3 Android为什么有两个Zygote(32位和64位)?
- 13.4 如何观察系统启动过程?
- 十四、ActivityThread深入分析
- 14.1 ActivityThread核心流程
- 14.2 Application启动流程
- 14.3 Activity启动入口
- 十五、Context上下文设计
- 15.1 Context设计目的
- 15.2 Context类的设计
- 15.3 Context作用域
- 十六、组件通信Intent设计
- 16.1 Intent设计思想
- 16.2 Bundle与数据传递
- 16.3 PendingIntent设计
- 十七、Android硬件抽象层
- 17.1 HAL层介绍
- 17.2 HAL层设计
- 17.3 系统架构分层
- 十八、总结
# 一、引言:按下电源键之后发生了什么
当用户按下Android手机的电源键,到看到桌面图标可以操作,中间经历了一个复杂而精密的启动流程。这个过程涉及硬件初始化、Linux内核加载、Native进程启动、Java虚拟机初始化、系统服务注册等多个阶段。
理解Android系统启动流程,是深入掌握Android底层原理的第一步。它不仅帮助我们理解系统架构的设计思想,更能在实际开发中解决启动优化、系统定制、Framework层修改等高级问题。
疑惑:为什么Android不像桌面Linux那样直接启动应用,而要经过Zygote这样一个"孵化器"进程?
本文将从BootLoader开始,逐层深入,最终揭示Zygote这个Android世界的"母体"是如何工作的。
# 二、BootLoader与Linux内核启动
# 2.1 硬件上电与BootLoader
Android设备的启动从硬件层面开始:
电源键按下
↓
CPU从固定地址(ROM)读取第一条指令
↓
BootROM代码执行:初始化RAM、加载BootLoader
↓
BootLoader执行(如U-Boot/LK)
├── 初始化硬件(时钟、内存控制器、存储设备)
├── 设置CPU运行模式(从实模式切换到保护模式)
├── 加载Linux内核镜像(boot.img)到RAM
└── 跳转到内核入口地址
2
3
4
5
6
7
8
9
10
11
BootLoader是一段运行在操作系统之前的程序,它的核心职责是准备运行环境并加载内核。Android常用的BootLoader包括高通的LK(Little Kernel)和联发科的preloader。
# 2.2 boot.img的结构
Android的boot.img包含Linux内核和ramdisk:
boot.img结构:
┌─────────────────────┐
│ Boot Header │ ← 包含内核大小、ramdisk大小、加载地址等信息
├─────────────────────┤
│ Kernel (zImage) │ ← 压缩的Linux内核
├─────────────────────┤
│ Ramdisk │ ← 初始的根文件系统(包含init程序)
├─────────────────────┤
│ Second Stage │ ← 可选的第二阶段引导程序
├─────────────────────┤
│ DTB │ ← 设备树(Device Tree Blob)
└─────────────────────┘
2
3
4
5
6
7
8
9
10
11
12
# 2.3 Linux内核的初始化
内核被加载到内存后,执行流程如下:
kernel入口(start_kernel)
↓
初始化核心子系统
├── 内存管理(mm_init)
├── 调度器(sched_init)
├── 中断(trap_init)
├── 定时器(timer_init)
└── 文件系统(vfs_caches_init)
↓
挂载根文件系统
↓
启动第一个用户空间进程:/init(PID = 1)
2
3
4
5
6
7
8
9
10
11
12
关键点:Linux内核启动完成后,会创建PID为1的init进程,这是整个Android用户空间的"始祖进程"。所有后续的进程(包括Zygote、SystemServer、应用进程)都是init的子孙进程。
# 2.4 Android内核与标准Linux的差异
Android对Linux内核做了若干重要修改:
Android特有的内核组件:
├── Binder驱动 → IPC通信核心(替代传统的System V IPC)
├── Ashmem → 匿名共享内存(比POSIX shm更灵活,支持引用计数回收)
├── ION/dmabuf → 统一的内存分配器(用于GPU/Camera等硬件缓冲区共享)
├── Low Memory Killer → 内存不足时按优先级杀进程(比OOM Killer更精细)
├── Wakelocks → 电源管理(防止CPU休眠)
└── Logger → Android日志系统(logcat的内核支持)
2
3
4
5
6
7
这些修改体现了Android作为移动操作系统的特殊需求:高效的IPC、严格的内存管理、精细的电源控制。
# 三、Init进程:Android世界的开端
# 3.1 Init进程的角色
Init是Android启动后第一个用户空间进程(PID=1),它承担三个核心职责:
Init进程的三大职责:
┌─────────────────────────────────────────────┐
│ 1. 解析并执行init.rc配置文件 │
│ → 创建文件系统目录、设置权限、启动服务 │
├─────────────────────────────────────────────┤
│ 2. 属性服务(Property Service) │
│ → 管理系统属性的读写(类似Windows注册表) │
├─────────────────────────────────────────────┤
│ 3. 子进程管理 │
│ → 监控子进程退出,必要时重启关键服务 │
└─────────────────────────────────────────────┘
2
3
4
5
6
7
8
9
10
11
# 3.2 Init进程源码分析
Init进程的入口在 system/core/init/main.cpp:
// Android 12+ init进程入口
int main(int argc, char** argv) {
// 第一阶段:挂载基本文件系统
if (argc == 1 || strcmp(argv[1], "selinux_setup") == 0) {
return SetupSelinux(argv); // SELinux安全策略
}
if (strcmp(argv[1], "second_stage") == 0) {
return SecondStageMain(argc, argv); // 核心逻辑
}
return FirstStageMain(argc, argv); // 挂载/dev, /proc, /sys等
}
2
3
4
5
6
7
8
9
10
11
12
13
第一阶段(FirstStageMain)的关键工作:
int FirstStageMain(int argc, char** argv) {
// 1. 创建基本设备节点
mount("tmpfs", "/dev", "tmpfs", ...);
mount("proc", "/proc", "proc", ...);
mount("sysfs", "/sys", "sysfs", ...);
// 2. 创建必要的设备文件
mknod("/dev/null", S_IFCHR | 0666, makedev(1, 3));
mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11));
// 3. 加载SELinux策略,然后重新执行init进入第二阶段
execv("/init", argv); // 重新执行自己,进入second_stage
}
2
3
4
5
6
7
8
9
10
11
12
13
# 3.3 属性服务的实现原理
Android的属性系统是一个全局的键值对存储,通过共享内存实现高效读取:
属性服务架构:
┌──────────────────────────────────────┐
│ PropertyService │
│ ┌─────────────────────────────┐ │
│ │ 共享内存区域(mmap) │ │
│ │ ┌───────┬───────────────┐ │ │
│ │ │ Key │ Value │ │ │ ← 所有进程可读(mmap只读映射)
│ │ ├───────┼───────────────┤ │ │
│ │ │ ro.build.type │ userdebug│ │ │
│ │ │ sys.boot_completed │ 1 │ │ │
│ │ └───────┴───────────────┘ │ │
│ └─────────────────────────────┘ │
│ ┌───────────────────────┐ │
│ │ Socket接口(写请求) │ │ ← 只有init进程处理写操作
│ └───────────────────────┘ │
└──────────────────────────────────────┘
读取路径(快速):进程直接读mmap内存 → O(1),无IPC开销
写入路径(安全):进程 → socket → init进程 → SELinux权限检查 → 写入共享内存
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
设计思想:读多写少的场景下,用共享内存实现零开销读取,用socket+权限检查保证写入安全。这种"读者无锁、写者串行"的设计在Android系统中非常典型。
# 四、Init.rc解析与服务启动
# 4.1 init.rc的语法结构
init.rc使用Android特有的配置语言(Android Init Language),它由五种类型的语句组成:
init.rc语法结构:
├── Action(动作)
│ on <trigger> ← 触发条件
│ <command> ← 要执行的命令
│ <command>
│
├── Service(服务)
│ service <name> <pathname> [<argument>]*
│ <option> ← 服务选项(用户、组、能力等)
│ <option>
│
├── Import(导入)
│ import <path> ← 导入其他.rc文件
│
├── Options(选项)
│ class, user, group, oneshot, disabled...
│
└── Commands(命令)
mkdir, chmod, chown, mount, start, stop...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 4.2 Zygote服务的声明
Zygote在init.rc中的声明(以64位为例):
# /system/etc/init/hw/init.zygote64.rc
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system
socket usap_pool_primary stream 660 root system
onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
writepid /dev/cpuset/foreground/tasks
2
3
4
5
6
7
8
9
10
11
12
13
14
15
关键参数解读:
/system/bin/app_process64 → Zygote的可执行文件(实际是app_process)
-Xzygote → 传递给VM的参数
/system/bin → Java类的搜索路径
--zygote → 标记以Zygote模式启动
--start-system-server → 启动后fork出SystemServer
socket zygote stream 660 → 创建Unix域套接字,供AMS请求fork新进程
priority -20 → 高优先级(nice值-20,最高优先级)
2
3
4
5
6
7
# 4.3 服务启动的触发机制
init进程的事件循环:
while (true) {
1. 解析所有.rc文件,构建Action列表和Service列表
2. 按触发条件执行Action
on early-init → 最早执行的初始化(设置权限、创建挂载点)
on init → 基础初始化(创建目录、设置rlimit)
on late-init → 触发class_start core/main/hal
on boot → 设置系统属性、启动服务
3. 启动被标记为class=main的服务(包括Zygote)
4. 进入无限循环,处理子进程退出事件
}
2
3
4
5
6
7
8
9
10
11
# 五、Zygote进程的诞生
# 5.1 从app_process到ZygoteInit
Zygote进程的启动入口是 app_process(C++层),最终进入Java层的 ZygoteInit:
启动调用链:
init进程 fork() → app_process64
↓
app_process::main() [frameworks/base/cmds/app_process/app_main.cpp]
↓
AndroidRuntime::start("com.android.internal.os.ZygoteInit", ...)
↓
startVm() → 创建Dalvik/ART虚拟机实例
↓
startReg() → 注册JNI函数
↓
JNI调用 → ZygoteInit.main() [Java层]
2
3
4
5
6
7
8
9
10
11
12
# 5.2 app_process的源码分析
// frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[]) {
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
// 解析参数
bool zygote = false;
bool startSystemServer = false;
while (i < argc) {
if (strcmp(argv[i], "--zygote") == 0) {
zygote = true; // Zygote模式
} else if (strcmp(argv[i], "--start-system-server") == 0) {
startSystemServer = true; // 需要启动SystemServer
}
i++;
}
if (zygote) {
// 启动Zygote:创建虚拟机 → 注册JNI → 调用ZygoteInit.main()
runtime.start("com.android.internal.os.ZygoteInit", args, /*zygote=*/true);
} else {
// 普通应用进程启动
runtime.start("com.android.internal.os.RuntimeInit", args, /*zygote=*/false);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 5.3 虚拟机的创建过程
// frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, ...) {
// 1. 创建JVM实例
JNI_CreateJavaVM(&mJavaVM, &env, &initArgs);
// 此时ART虚拟机已经初始化完成,包括:
// - 堆内存分配(默认最大512MB,可调)
// - GC线程创建
// - JIT编译器初始化
// - 类加载器准备
// 2. 注册Android框架的JNI函数
startReg(env);
// 注册了大量JNI函数,例如:
// - android_os_Binder → Binder的JNI桥接
// - android_view_Surface → Surface的JNI桥接
// - android_util_Log → Log的JNI桥接
// 3. 通过反射调用Java层的main方法
jclass startClass = env->FindClass(className);
jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V");
env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 5.4 ZygoteInit.main()的核心逻辑
// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String[] argv) {
ZygoteServer zygoteServer = null;
try {
// 1. 预加载资源(关键优化点!)
preload();
// 包括:预加载常用Java类、预加载Android框架资源(图片、布局等)
// 预加载共享库(如ICU、OpenGL等)
// 2. 创建Zygote的Socket服务端
zygoteServer = new ZygoteServer();
// 3. Fork出SystemServer进程
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
if (r != null) {
r.run(); // 子进程(SystemServer)走这里
return;
}
}
// 4. Zygote进入循环,等待AMS的请求来fork新的应用进程
caller = zygoteServer.runSelectLoop(abiList);
} finally {
if (zygoteServer != null) {
zygoteServer.closeServerSocket();
}
}
if (caller != null) {
caller.run(); // 在fork出的子进程中执行
}
}
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
29
30
31
32
33
34
# 六、Zygote的Fork机制
# 6.1 为什么使用Fork而不是New
疑惑:为什么Android创建新进程使用Linux的fork(),而不是从头创建一个新的虚拟机实例?
答疑:这是Android启动性能优化的核心设计决策。
方案对比:
┌──────────────────────────────────────────────────────┐
│ 方案A:每次从头创建进程 │
│ 新建进程 → 初始化VM → 加载核心类 → 加载资源 → 就绪 │
│ 耗时:约2-5秒 │
├──────────────────────────────────────────────────────┤
│ 方案B:Fork Zygote进程(Android采用的方案) │
│ fork() → COW复制地址空间 → 特化(关闭不需要的资源) │
│ 耗时:约200-500毫秒 │
└──────────────────────────────────────────────────────┘
2
3
4
5
6
7
8
9
10
Fork的优势:
- 速度快:fork()使用COW(Copy-On-Write),瞬间完成地址空间复制
- 内存共享:预加载的类和资源在物理内存中只有一份,所有应用共享
- 一致性:所有应用进程从同一个起点出发,保证环境一致
# 6.2 Copy-On-Write(COW)原理
Fork前(Zygote进程):
虚拟页面A → 物理页面X(预加载的类)
虚拟页面B → 物理页面Y(预加载的资源)
虚拟页面C → 物理页面Z(VM堆内存)
Fork后(子进程共享物理内存):
Zygote: 虚拟页面A → 物理页面X [只读标记]
子进程: 虚拟页面A → 物理页面X [只读标记] ← 共享同一物理页
子进程写入页面A时触发COW:
子进程: 虚拟页面A → 物理页面X'(新分配并拷贝)[可写]
Zygote: 虚拟页面A → 物理页面X [恢复可写]
2
3
4
5
6
7
8
9
10
11
12
论证:通过/proc/[pid]/smaps可以观察到实际的内存共享情况:
# 查看某个应用进程的内存映射
adb shell cat /proc/$(pidof com.example.app)/smaps | grep -A 5 "boot.art"
# 典型输出:
# Size: 8192 kB ← 虚拟内存大小
# Rss: 6144 kB ← 实际驻留物理内存
# Shared_Clean: 6000 kB ← 与Zygote共享的只读页面(大部分!)
# Private_Dirty: 144 kB ← 进程私有的写时复制页面(很少)
2
3
4
5
6
7
8
这说明绝大部分预加载的内存页面是与Zygote共享的,COW极大地节省了物理内存。
# 6.3 Fork过程的源码分析
// ZygoteConnection.java → Zygote.java
static int forkAndSpecialize(int uid, int gid, int[] gids,
int runtimeFlags, int[][] rlimits, ...) {
// 1. Fork前:暂停所有线程(保证fork安全)
ZygoteHooks.preFork();
// ART内部:暂停GC线程、暂停编译线程、暂停其他daemon线程
// 原因:fork()只复制调用线程,多线程fork可能导致死锁
// 2. 执行fork
int pid = nativeForkAndSpecialize(...);
// native层调用 fork() 系统调用
// 3. Fork后的处理
ZygoteHooks.postForkCommon();
if (pid == 0) {
// 子进程:
// - 设置进程名、UID/GID
// - 关闭Zygote的socket(子进程不需要监听)
// - 重新初始化线程池
// - 调用应用的入口方法
}
return pid;
}
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
# 6.4 USAP(Unspecialized App Process)池
Android 10引入了USAP机制,进一步优化应用启动速度:
传统模式:
AMS请求 → Zygote收到 → fork() → 特化 → 应用就绪
↑ 耗时点
USAP模式:
预先fork一批进程(USAP Pool)
AMS请求 → 从池中取一个USAP → 特化 → 应用就绪
↑ fork开销已提前完成
USAP池管理:
┌──────────────────────────────────────┐
│ USAP Pool(默认保持3-10个预备进程) │
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │
│ │USAP│ │USAP│ │USAP│ │USAP│ │
│ └────┘ └────┘ └────┘ └────┘ │
│ 每个USAP已完成fork、VM初始化 │
│ 等待被"认领"并特化为具体应用进程 │
└──────────────────────────────────────┘
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 七、SystemServer的启动流程
# 7.1 SystemServer的Fork
SystemServer是Zygote fork出的第一个也是最重要的子进程:
// ZygoteInit.java
private static Runnable forkSystemServer(...) {
String[] args = {
"--setuid=1000", // system用户
"--setgid=1000",
"--setgroups=1001,1002,...",
"--capabilities=...", // 系统能力
"--nice-name=system_server",
"--runtime-args",
"--target-sdk-version=10000",
"com.android.server.SystemServer", // 入口类
};
// Fork出SystemServer进程
pid = Zygote.forkSystemServer(...);
if (pid == 0) {
// 子进程(SystemServer)
zygoteServer.closeServerSocket(); // 关闭Zygote的socket
return handleSystemServerProcess(parsedArgs);
}
return null; // 父进程(Zygote)继续
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 7.2 SystemServer.main()的核心逻辑
// frameworks/base/services/java/com/android/server/SystemServer.java
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
// 1. 设置系统属性
SystemProperties.set("persist.sys.dalvik.vm.lib.2",
VMRuntime.getRuntime().vmLibrary());
// 2. 准备主线程Looper
Looper.prepareMainLooper();
// 3. 加载libandroid_servers.so(系统服务的Native层)
System.loadLibrary("android_servers");
// 4. 创建SystemServiceManager(服务管理器)
mSystemServiceManager = new SystemServiceManager(mSystemContext);
// 5. 按顺序启动三组服务
startBootstrapServices(); // 引导服务(AMS、PMS、PowerMS等)
startCoreServices(); // 核心服务(BatteryService等)
startOtherServices(); // 其他服务(WindowMS、InputMS等)
// 6. 进入消息循环
Looper.loop();
}
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
# 7.3 服务启动的三个阶段
引导服务(Bootstrap Services):系统最核心的服务
├── Installer → APK安装相关
├── ActivityTaskManagerService → Activity任务管理(Android 10拆分自AMS)
├── ActivityManagerService → 四大组件管理
├── PowerManagerService → 电源管理
├── PackageManagerService → 包管理(解析所有APK信息)
├── UserManagerService → 多用户管理
└── DisplayManagerService → 显示管理
核心服务(Core Services):
├── BatteryService → 电池状态
├── UsageStatsService → 使用统计
├── WebViewUpdateService → WebView更新
└── BugreportManagerService → Bug报告
其他服务(Other Services):
├── WindowManagerService → 窗口管理
├── InputManagerService → 输入事件
├── NetworkManagementService → 网络管理
├── ConnectivityService → 网络连接
├── AudioService → 音频管理
├── CameraService → 相机管理
├── NotificationManagerService → 通知管理
├── LocationManagerService → 定位管理
└── ... 约100+个系统服务
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 7.4 服务启动的依赖关系
服务之间存在严格的启动顺序依赖:
AMS依赖 → PowerMS(需要电源管理能力)
PMS依赖 → Installer(需要安装能力)
WMS依赖 → AMS + InputMS(需要Activity管理和输入事件)
Launcher依赖 → AMS + PMS + WMS(需要所有核心服务就绪)
启动时序:
t=0s ──── Installer, DeviceIdentifier
t=0.5s ──── AMS, PowerMS, LightsMS
t=1s ──── PMS(扫描所有APK,耗时最长)
t=3s ──── WMS, InputMS
t=4s ──── NetworkMS, AudioMS, ...
t=5s ──── 所有服务就绪 → 发送BOOT_COMPLETED广播
2
3
4
5
6
7
8
9
10
11
12
# 八、系统服务的注册与启动
# 8.1 ServiceManager的角色
ServiceManager是Binder机制中的"DNS服务器",管理所有系统服务的注册和查找:
ServiceManager工作原理:
┌──────────────────────────────────────────┐
│ ServiceManager (Context Manager) │
│ ┌────────────────────────────────────┐ │
│ │ 服务注册表(HashMap) │ │
│ │ "activity" → AMS的Binder引用 │ │
│ │ "package" → PMS的Binder引用 │ │
│ │ "window" → WMS的Binder引用 │ │
│ │ "input" → IMS的Binder引用 │ │
│ │ ... → ... │ │
│ └────────────────────────────────────┘ │
│ │
│ addService(name, binder) ← 注册服务 │
│ getService(name) ← 查找服务 │
└──────────────────────────────────────────┘
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 8.2 系统服务的注册过程
以AMS为例,展示服务注册的完整链路:
// SystemServer中启动AMS
private void startBootstrapServices() {
// 1. 创建AMS实例
ActivityTaskManagerService atm = mSystemServiceManager.startService(
ActivityTaskManagerService.Lifecycle.class).getService();
mActivityManagerService = ActivityManagerService.Lifecycle.startService(
mSystemServiceManager, atm);
// 2. 注册到ServiceManager
mActivityManagerService.setSystemProcess();
// 内部调用:
// ServiceManager.addService("activity", this, /* allowIsolated= */ true);
}
// 应用层获取AMS
// Context.getSystemService(Context.ACTIVITY_SERVICE)
// 最终调用:ServiceManager.getService("activity")
// 返回AMS的Binder代理对象(BinderProxy)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 8.3 SystemServiceManager的生命周期管理
// SystemServiceManager管理服务的生命周期
public void startBootPhase(int phase) {
// 按阶段通知所有服务
for (SystemService service : mServices) {
service.onBootPhase(phase);
}
}
// 启动阶段定义:
PHASE_WAIT_FOR_DEFAULT_DISPLAY = 100 // 等待默认显示器
PHASE_LOCK_SETTINGS_READY = 480 // 锁屏设置就绪
PHASE_SYSTEM_SERVICES_READY = 500 // 系统服务就绪
PHASE_ACTIVITY_MANAGER_READY = 550 // AMS就绪
PHASE_THIRD_PARTY_APPS_CAN_START = 600 // 第三方应用可以启动
PHASE_BOOT_COMPLETED = 1000 // 启动完成
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 九、Launcher的启动与桌面显示
# 9.1 AMS启动Launcher的时机
当所有系统服务启动完成后,AMS会启动Home应用(Launcher):
// ActivityManagerService.java
public void systemReady(final Runnable goingCallback, ...) {
// 1. 执行一系列准备工作
// 2. 发送PHASE_ACTIVITY_MANAGER_READY
// 3. 启动持久应用(persistent apps)
// 4. 启动Home Activity(Launcher)
mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");
}
// ActivityTaskManagerService → RootWindowContainer
void startHomeOnDisplay(int userId, String reason, int displayId) {
Intent homeIntent = getHomeIntent();
// 构造HOME类型的Intent
// Action: Intent.ACTION_MAIN
// Category: Intent.CATEGORY_HOME
// 通过PMS查找匹配的Activity(即Launcher)
ActivityInfo aInfo = resolveActivityInfo(homeIntent, ...);
// 启动Launcher
mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, ...);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 9.2 Launcher的角色与启动流程
Launcher启动流程:
AMS.systemReady()
↓
startHomeOnAllDisplays()
↓
解析HOME Intent → 找到Launcher应用
↓
startActivity() → 标准Activity启动流程
↓
Zygote fork新进程 → 创建Launcher进程
↓
Launcher.onCreate()
├── 加载桌面布局
├── 查询所有已安装应用(PackageManager.queryIntentActivities)
├── 创建应用图标网格
└── 显示桌面
↓
用户看到桌面 → 系统启动完成
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 9.3 开机广播的发送
启动完成后的广播:
1. Intent.ACTION_LOCKED_BOOT_COMPLETED
→ 设备加密状态下发送(Direct Boot模式)
→ 只有声明了directBootAware的应用能收到
2. Intent.ACTION_BOOT_COMPLETED
→ 用户解锁后发送
→ 所有注册了该广播的应用都能收到
→ 很多应用利用这个广播实现"开机自启"
2
3
4
5
6
7
8
9
# 十、Application进程的创建过程
# 10.1 完整的应用启动链路
当用户点击Launcher中的应用图标时:
用户点击图标
↓
Launcher → startActivity(intent)
↓
Binder IPC → AMS.startActivity()
↓
AMS检查目标进程是否存在
├── 已存在 → 直接调度Activity
└── 不存在 → 请求Zygote创建进程 ↓
↓
AMS → socket连接 → Zygote
↓
Zygote.fork() → 新进程
↓
新进程执行 ActivityThread.main()
↓
ActivityThread → 创建Application对象
↓
Application.onCreate()
↓
AMS调度 → 创建Activity → Activity.onCreate()
↓
View绘制 → 用户看到界面
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 10.2 AMS请求Zygote的通信过程
// AMS端:Process.java
public static ProcessStartResult start(String processClass, ...) {
return ZYGOTE_PROCESS.start(processClass, ...);
}
// ZygoteProcess.java → 通过Socket发送请求
private Process.ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList<String> args) {
// 构造参数列表
// 格式:每个参数一行,以换行符分隔
// --runtime-args
// --setuid=10086
// --setgid=10086
// --target-sdk-version=33
// --nice-name=com.example.app
// android.app.ActivityThread ← 入口类
DataOutputStream out = zygoteState.mZygoteOutputStream;
out.writeInt(args.size()); // 参数数量
for (String arg : args) {
out.writeBytes(arg + "\n");
}
// 读取Zygote返回的PID
DataInputStream in = zygoteState.mZygoteInputStream;
int pid = in.readInt();
return new ProcessStartResult(pid);
}
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
29
# 10.3 ActivityThread.main():应用的真正入口
// frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
// 1. 准备主线程的Looper
Looper.prepareMainLooper();
// 2. 创建ActivityThread实例
ActivityThread thread = new ActivityThread();
// 3. 关键步骤:attach到AMS
thread.attach(false, startSeq);
// 内部通过Binder调用AMS.attachApplication()
// AMS收到后:
// - 记录进程信息
// - 回调bindApplication():创建Application对象
// - 调度待启动的Activity/Service/BroadcastReceiver
// 4. 获取主线程Handler
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
// 5. 进入消息循环(永不退出)
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
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
# 十一、预加载机制与启动优化
# 11.1 Zygote预加载的内容
// ZygoteInit.java
static void preload() {
// 1. 预加载Java类(约8000+个常用类)
preloadClasses();
// 读取 /system/etc/preloaded-classes 文件
// 包括:android.app.Activity, android.widget.TextView,
// java.util.ArrayList, java.lang.String 等
// 通过Class.forName()加载,触发类的<clinit>初始化
// 2. 预加载资源
preloadResources();
// 加载framework-res.apk中的资源
// 包括:系统主题、默认颜色、常用Drawable等
// 3. 预加载共享库
preloadSharedLibraries();
// libandroid.so, libcompiler_rt.so, libjnigraphics.so, libmedia_jni.so等
// 4. 预加载文字渲染资源
preloadTextResources();
// 字体文件、文字布局相关资源
// 5. 预加载OpenGL驱动
maybePreloadGraphicsDriver();
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 11.2 预加载的内存效益分析
预加载的核心收益 — 内存共享:
假设系统运行了20个应用进程:
不预加载:
每个进程独立加载8000个类 → 每个进程约占用20MB → 总计400MB
预加载(通过Zygote + COW):
Zygote预加载20MB → fork后20个进程共享 → 总计仅20MB物理内存
只有修改过的内存页才会复制 → 每个进程额外仅约2MB → 总计60MB
节省:400MB - 60MB = 340MB(节省85%!)
2
3
4
5
6
7
8
9
10
11
12
# 11.3 预加载类的选择策略
preloaded-classes文件的生成策略:
1. Google通过采样统计确定需要预加载的类
2. 条件:在启动阶段被至少N个应用使用的类
3. 排除条件:
- 只在少数应用中使用的特殊类
- 过大的类(加载耗时太长)
- 有副作用的静态初始化块
选择平衡点:
预加载太多 → Zygote启动变慢 + 浪费内存
预加载太少 → 应用启动变慢(需要额外加载)
2
3
4
5
6
7
8
9
10
11
# 11.4 启动速度优化策略
Android系统层面的启动优化:
├── Zygote预加载(减少进程创建时间)
├── USAP池(预先fork进程池)
├── PMS并行扫描(多线程扫描APK)
├── 延迟服务启动(非关键服务延后启动)
├── I/O预读(readahead系统调用)
└── 编译优化(AOT编译关键类)
应用层面的启动优化:
├── 减少Application.onCreate()耗时
│ ├── 延迟初始化非必要SDK
│ ├── 异步初始化(子线程)
│ └── 按需加载(用到时才初始化)
├── 减少主Activity布局复杂度
│ ├── 使用ViewStub延迟加载
│ └── 减少布局层级
├── 避免主线程I/O
│ ├── SharedPreferences异步写入
│ └── 数据库操作放子线程
└── 使用SplashScreen API(Android 12+)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 十二、Android启动中的关键设计思想
# 12.1 进程隔离与安全模型
Android的进程安全模型:
┌────────────────────────────────────┐
│ 每个应用 = 独立的Linux进程 │
│ 每个应用 = 独立的UID │
│ 每个应用 = 独立的文件系统沙箱 │
└────────────────────────────────────┘
进程创建时的安全设置:
fork() → setuid(appUid) → setgid(appGid)
→ setgroups(supplementaryGids)
→ SELinux域转换(u:r:untrusted_app:s0:...)
→ seccomp过滤(限制可用的系统调用)
结果:
应用A(UID=10001)无法访问应用B(UID=10002)的文件
应用无法直接访问系统关键目录
应用的系统调用受到限制
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 12.2 分层启动的设计哲学
Android启动的分层设计:
Layer 0: 硬件/BootLoader → 确保硬件可用
Layer 1: Linux Kernel → 提供OS基础能力
Layer 2: Init进程 → 用户空间入口,启动守护进程
Layer 3: Zygote进程 → Java世界的入口,进程孵化器
Layer 4: SystemServer → 系统服务中心
Layer 5: Launcher → 用户交互入口
每一层只依赖下一层,不跨层依赖:
- Zygote不直接操作硬件
- SystemServer不直接fork进程(通过Zygote)
- 应用不直接访问内核(通过系统服务)
2
3
4
5
6
7
8
9
10
11
12
13
# 12.3 单一职责与服务化
设计原则:每个组件只做一件事
Init: 只负责启动其他进程 + 属性管理
Zygote: 只负责fork新进程
SystemServer: 只负责管理系统服务
ServiceManager: 只负责服务注册和查找
AMS: 只负责四大组件生命周期
PMS: 只负责包信息管理
WMS: 只负责窗口管理
好处:
- 某个服务崩溃不会影响整个系统
- 可以独立升级某个服务
- 权限边界清晰
2
3
4
5
6
7
8
9
10
11
12
13
14
# 12.4 预加载+COW的"空间换时间"哲学
这是Android系统中最巧妙的设计之一:
传统思路:按需加载(懒加载)
优点:启动快,不浪费内存
缺点:每个进程首次使用时都要加载,重复劳动
Android思路:Zygote预加载 + Fork COW
1. Zygote启动时一次性加载所有常用资源(预加载阶段耗时较长)
2. Fork子进程时通过COW共享物理内存(零拷贝)
3. 子进程修改时才真正分配独立内存(按需分配)
结果:
- 第一个进程(Zygote)启动较慢 → 可接受(只在开机时发生一次)
- 后续所有应用进程启动很快 → 用户体验好
- 物理内存只有一份 → 节省大量内存
这是典型的"一次投入,多次收益"的设计。
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 十三、面试高频问题与深度分析
# 13.1 Zygote为什么用Socket而不用Binder通信?
原因分析:
1. 时序问题:
Zygote启动时,ServiceManager还未启动
→ 无法注册Binder服务
→ 只能使用更底层的IPC(Socket)
2. Fork安全性:
Binder是多线程模型(Binder线程池)
fork()只复制调用线程,其他Binder线程不会被复制
→ 子进程的Binder线程池处于不一致状态 → 可能死锁
Socket是单线程的select/poll模型
→ fork安全,不存在多线程问题
3. 使用场景简单:
Zygote只需要接收"创建进程"请求
→ 不需要Binder的复杂双向通信能力
→ 简单的请求-响应模式,Socket足够
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 13.2 SystemServer为什么不直接启动,而要从Zygote fork?
原因:
SystemServer需要运行Java代码(AMS、PMS等都是Java写的)
→ 需要一个已经初始化好的Java虚拟机
→ Zygote已经创建了VM并预加载了类
→ fork Zygote = 免费获得一个初始化好的VM环境
如果SystemServer独立启动:
→ 需要自己创建VM → 慢
→ 需要自己加载系统类 → 慢
→ 预加载的资源无法与应用进程共享 → 浪费内存
2
3
4
5
6
7
8
9
10
# 13.3 Android为什么有两个Zygote(32位和64位)?
现代Android设备同时支持32位和64位应用:
zygote64 → fork 64位应用进程
zygote32 → fork 32位应用进程
原因:
- ABI兼容性:32位应用无法在64位进程中运行
- 不同的共享库路径:/system/lib vs /system/lib64
- 不同的linker:/system/bin/linker vs /system/bin/linker64
PMS在安装APK时会检测其ABI,标记为32位或64位
AMS在启动应用时,根据标记选择对应的Zygote来fork
2
3
4
5
6
7
8
9
10
11
12
# 13.4 如何观察系统启动过程?
# 1. 查看启动日志
adb logcat -b events | grep boot
# 2. 查看系统启动时间
adb shell cat /proc/bootprof # MTK平台
adb shell dumpsys bootinfo # 通用
# 3. 使用bootchart分析
adb shell 'touch /data/bootchart/enabled'
# 重启后导出数据
adb pull /data/bootchart/
# 使用bootchart工具生成可视化报告
# 4. 查看Zygote预加载耗时
adb logcat | grep "Preloading"
# 典型输出:
# Preloading classes... (took 1234ms)
# Preloading resources... (took 567ms)
# Preloading shared libraries... (took 89ms)
# 5. 使用systrace/perfetto分析启动
adb shell perfetto --config :boot --txt -o /data/misc/perfetto-traces/boot.perfetto-trace
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 十四、ActivityThread深入分析
ActivityThread是Android应用进程的核心类,它的main方法是整个应用进程的入口。为什么我们平时将ActivityThread称之为UI线程或者主线程?因为应用进程被创建之后首先执行的就是ActivityThread的main方法。
# 14.1 ActivityThread核心流程
ActivityThread的main方法主要执行了以下操作:
ActivityThread核心流程:
ActivityThread#main()
├── Looper.prepareMainLooper() → 初始化主线程Looper
├── new ActivityThread() → 创建ActivityThread实例
├── thread.attach() → 与AMS建立通信,创建Application
│ ├── AMS.attachApplication() → 通过Binder调用AMS
│ ├── bindApplication() → 设置进程信息
│ ├── makeApplication() → 反射创建Application对象
│ └── callApplicationOnCreate() → 执行Application.onCreate()
└── Looper.loop() → 开启消息循环(永不退出)
2
3
4
5
6
7
8
9
10
11
ActivityThread是应用程序与系统之间的桥梁,主要功能包括:
- 应用程序生命周期管理:负责管理应用程序的启动、暂停、恢复、停止和销毁等阶段,通过与AMS进行通信,接收生命周期回调。
- Activity管理和调度:负责创建、启动、暂停、恢复、停止和销毁Activity,并处理Activity之间的切换和交互。
- 消息处理和线程调度:使用Handler和Looper机制处理来自系统和应用程序的消息,并将其分发给相应的处理器。
- 应用程序上下文管理:负责管理应用程序的上下文,包括全局的Context对象和资源访问。
# 14.2 Application启动流程
App点击桌面图标启动Application的完整流程:
Application启动核心路径:
ActivityManagerService#startProcessLocked()
→ Process#start()
→ ActivityThread#main() // 入口
→ ActivityThread#attach() // 与AMS建立连接
→ AMS#attachApplication() // Binder调用
→ AMS#attachApplicationLocked() // 进程启动完成
→ thread.bindApplication() // 回到ActivityThread
→ ActivityThread.ApplicationThread#bindApplication()
→ ActivityThread#handleBindApplication() // 处理bind逻辑
├── 设置进程pid,初始化进程信息
├── LockedApk.makeApplication() // 反射创建Application
│ └── 同时创建ContextImpl并关联
└── mInstrumentation.callApplicationOnCreate()
└── Application.onCreate() // 开发者入口
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
核心要点总结:
- 应用进程启动 → 创建Instrumentation → 创建Application对象 → 创建Application相关的ContextImpl对象
- 每个应用进程对应一个Instrumentation,对应一个Application
- Instrumentation与Application都是通过Java反射机制创建
- Application创建过程中会同时创建一个ContextImpl对象,并建立关联
# 14.3 Activity启动入口
ActivityThread中启动Activity的核心流程:
Activity创建核心路径:
ActivityThread.handleLaunchActivity()
→ ActivityThread.performLaunchActivity()
├── mInstrumentation.newActivity() // 反射创建Activity
├── createBaseContextForActivity() // 创建ContextImpl
├── activity.attach() // 初始化Activity
│ ├── attachBaseContext() // 设置基础上下文
│ └── new PhoneWindow() // 创建窗口对象
└── mInstrumentation.callActivityOnCreate()
└── Activity.onCreate() // 开发者入口
2
3
4
5
6
7
8
9
10
11
# 十五、Context上下文设计
# 15.1 Context设计目的
Android设计Context上下文的概念,是为了提供应用程序访问系统资源和执行特定操作的接口。Context在Android开发中扮演着重要的角色:
- 访问系统资源:允许应用程序访问包名、资源文件、数据库、SharedPreferences、系统服务等
- 启动组件:提供启动Activity、Service、BroadcastReceiver等组件的能力
- 获取应用程序级别信息:如包名、资源、文件目录等
- 访问系统服务:网络服务、传感器服务、位置服务等
- 安全性和权限管理:获取权限信息、检查和请求权限
# 15.2 Context类的设计
Context类继承关系:
Context (抽象类)
├── ContextImpl (真正的实现类)
└── ContextWrapper (代理/包装类)
├── Application
├── Service
└── ContextThemeWrapper
└── Activity
2
3
4
5
6
7
8
9
ContextWrapper:只是一个包装类,构造函数中必须包含一个真正的Context引用,调用ContextWrapper的方法都会被转向其所包含的真正Context对象ContextImpl:真正实现了Context中的所有函数,应用程序中所调用的各种Context类的方法,其实现均来自于该类- Activity继承自ContextThemeWrapper(包含主题相关接口),Service和Application直接继承ContextWrapper(不需要主题)
# 15.3 Context作用域
不同类型的Context使用能力不同:
| 功能 | Activity | Application | Service |
|---|---|---|---|
| 启动Activity | ✓ | △(需FLAG_ACTIVITY_NEW_TASK) | △ |
| 弹出Dialog | ✓ | ✗ | ✗ |
| 启动Service | ✓ | ✓ | ✓ |
| 发送Broadcast | ✓ | ✓ | ✓ |
| Layout Inflate | ✓ | △(使用系统默认主题) | △ |
一个App中Context的数量 = Application(1) + N个Activity + N个Service
# 十六、组件通信Intent设计
# 16.1 Intent设计思想
Intent(意图)用于在不同组件之间传递消息和执行操作,设计思想是实现组件之间的松耦合通信和交互。Intent提供了一种统一的机制,使得Android应用程序中的各个组件可以相互协作,共享功能和数据。
Intent的核心设计模式:
1. 命令模式(Command Pattern)
Intent封装了"动作+数据"的组合,调用方不需要知道具体的接收方
→ startActivity(new Intent(ACTION_VIEW, uri))
→ 系统通过PMS匹配最合适的组件来处理
2. 显式Intent vs 隐式Intent
显式:明确指定目标组件
→ new Intent(this, TargetActivity.class)
→ 直接通过ComponentName定位
隐式:通过Action/Category/Data描述意图
→ new Intent(Intent.ACTION_SEND)
→ PMS通过IntentFilter匹配合适的组件
→ 可能弹出选择器让用户选择
3. Intent的解析过程(PMS内部)
IntentResolver.queryIntent()
→ 遍历所有已注册的IntentFilter
→ 按Action → Category → Data三级匹配
→ 返回匹配结果列表(ResolveInfo)
4. Intent的数据传输机制
Intent → Parcel序列化 → Binder传输 → Parcel反序列化 → Intent
→ 整个过程是深拷贝,发送方和接收方持有的是不同对象
→ Binder缓冲区限制1MB,大数据不适合通过Intent传递
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
# 16.2 Bundle与数据传递
Intent传递数据和Bundle传递数据本质是一回事,Intent传递时内部调用了Bundle。Bundle只是一个信息的载体,内部其实就是维护了一个Map<String,Object>。
需要注意的是:
- Intent传递数据的限制:Intent中的数据通过Binder机制传输,Binder事务缓冲区大小限定在1MB,且这个空间是进程共享的
- 序列化问题:跨进程传递数据需要序列化(Serializable或Parcelable),这是值传递(深拷贝)
- Fragment间传递:Fragment.setArguments(Bundle)不涉及跨进程,传递的是对象引用,不存在序列化开销
- 大数据传递方案:对于Bitmap等大数据,应传递drawable_id、路径或URL,从数据源还原数据
# 16.3 PendingIntent设计
PendingIntent是一种特殊的Intent,用于在某个事件结束后执行特定的Action。即便创建该PendingIntent对象的进程被杀死了,这个PendingIntent对象在其他进程中还是可用的。常见应用场景包括短信、闹钟、通知栏点击等。
PendingIntent的底层原理:
1. 创建过程
PendingIntent.getActivity(context, requestCode, intent, flags)
→ 通过AMS.getIntentSender()在系统进程中注册
→ AMS创建PendingIntentRecord保存在内存中
→ 返回一个IIntentSender的Binder代理给调用方
2. 执行过程
通知栏点击 → NotificationManager通过PendingIntent.send()
→ AMS.sendIntentSender()
→ 从PendingIntentRecord中取出保存的Intent
→ 以原始调用方的身份和权限执行Intent
3. 安全设计
PendingIntent携带了创建者的UID/PID
→ 执行时使用创建者的身份,而非触发者的身份
→ 这就是为什么Notification能跨进程启动创建者的Activity
4. flags含义
FLAG_ONE_SHOT → 只能使用一次
FLAG_NO_CREATE → 如果不存在则返回null
FLAG_CANCEL_CURRENT → 取消旧的,创建新的
FLAG_UPDATE_CURRENT → 更新旧的extras数据
FLAG_IMMUTABLE → PendingIntent不可修改(Android 12+推荐)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 十七、Android硬件抽象层
# 17.1 HAL层介绍
Android硬件抽象层(Hardware Abstraction Layer,HAL)是Android系统架构中的重要组成部分,提供了一个标准化的接口,用于在操作系统和底层硬件之间进行通信和交互。
HAL的设计旨在实现硬件的抽象和解耦,使得Android系统可以在不同的硬件平台上运行,而无需对上层应用程序进行修改。
HAL层在系统中的位置与作用:
Framework层 (Java)
↓ JNI调用
Native服务层 (C++)
↓ dlopen加载HAL模块
HAL层 (.so动态库)
↓ 系统调用
Linux内核驱动
HAL的核心价值:
1. 保护厂商知识产权
→ Linux内核使用GPL协议,驱动代码必须开源
→ HAL运行在用户空间,使用Apache协议,厂商可以闭源
→ 厂商将核心算法放在HAL层,只在内核实现基本IO
2. 提供统一接口
→ 不同厂商的Camera硬件各不相同
→ 但CameraHAL接口定义是统一的
→ Framework层调用HAL接口时不需要关心具体硬件
3. HAL的演进
Legacy HAL (Android 7.0-):.so直接加载到Framework进程
HIDL HAL (Android 8.0+):HAL运行在独立进程,通过HIDL接口通信
AIDL HAL (Android 11+):使用稳定版AIDL代替HIDL
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 17.2 HAL层设计
HAL层的关键设计包括:
- 接口定义:定义了一组标准化的接口,描述摄像头、传感器、音频、蓝牙、Wi-Fi等硬件功能和操作
- HAL实现:每个硬件厂商根据接口定义实现相应的HAL库(.so文件),负责与底层硬件通信
- 设备树:描述硬件配置和功能的数据结构,使HAL能够动态识别和加载适当的硬件驱动
- 与上层框架的交互:通过标准化接口,使上层应用框架可以与硬件交互,而无需关心具体硬件实现
# 17.3 系统架构分层
Android系统架构:
应用层
├── 四大组件 (Activity, Service, BroadcastReceiver, ContentProvider)
└── 第三方应用
应用框架层 (Java)
├── AMS → 管理组件生命周期
├── PMS → 管理应用安装
├── WMS → 管理窗口
└── 其他系统服务
C/C++库 + Android运行时
├── 核心库 (Java/C/C++/媒体库)
├── ART虚拟机 (Dex → 本地机器码)
└── JNI桥接
HAL层
└── 标准化硬件接口
Linux内核层
├── 硬件驱动
├── 进程/内存管理
├── Binder驱动
└── 网络协议栈
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25