系统源码路线
本文面向已经会使用 rg 和 Git 阅读 AOSP,理解 C++ 函数、Java 类、进程和 Binder 基本概念的读者。前置阅读可选 C++调用链、Java调用链 和 搜索调用链。
本文不提供按目录浏览的静态清单,而是回答一个阅读决策问题:当你想解释一个 Android 系统行为时,如何从启动链确定进程边界、入口函数、状态 owner 和下一处源码,而不会一开始陷入整个 AOSP?主线固定在 Android 17:PID 1 的多阶段 init、zygote 的预加载与 fork、SystemServer 的服务启动和 boot phase。读完后,读者应能从现象选择入口,沿最小源码路径走到消费者,并知道哪些结论仍需专题文章证明。
1. 路线问题
系统启动路线的价值不在于记住所有服务名称,而在于给每次阅读建立四个坐标:
| 坐标 | 要回答的问题 | Android 17 入口 |
|---|---|---|
| 进程 | 谁拥有当前状态? | init、zygote、system_server、app |
| 阶段 | 当前代码何时生效? | first stage、SELinux setup、second stage、boot phase |
| 入口 | 从哪个函数开始反查? | main、FirstStageMain、ZygoteInit.main、SystemServer.run |
| 消费者 | 结果最终谁读取? | init action、Zygote socket、SystemService、Binder client |
一个问题应先被改写成“现象 + 进程 + 阶段”。例如“Launcher 没启动”不应直接搜索 Launcher,而应先确认是 init 没启动 zygote、zygote 没 fork system_server、system_server 没完成 boot phase,还是 ActivityManager 的用户启动路径失败。
2. PID 1入口
2.1 模式分发
Android 17 的 system/core/init/main.cpp 把多个用户空间阶段集中在同一个 main 中。argv[0] 和 argv[1] 决定它进入 ueventd、subcontext、SELinux setup、second stage 或 first stage:
源码文件:system/core/init/main.cpp
int main(int argc, char** argv) {
setpriority(PRIO_PROCESS, 0, -20);
if (!strcmp(basename(argv[0]), "ueventd")) {
return ueventd_main(argc, argv);
}
if (argc > 1) {
if (!strcmp(argv[1], "subcontext")) {
const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();
return SubcontextMain(argc, argv, &function_map);
}
if (!strcmp(argv[1], "selinux_setup")) {
return SetupSelinux(argv);
}
if (!strcmp(argv[1], "second_stage")) {
return SecondStageMain(argc, argv);
}
}
#if defined(FIRST_STAGE_INIT) || defined(RECOVERY)
return FirstStageMain(argc, argv);
#else
LOG(FATAL) << "Second-stage init requires an argument to main()";
#endif
}关键事实是 exec 复用同一个 PID,而不是有多个 init 进程。阅读启动失败时,先把命令行参数和二进制模式分开;否则会把 SetupSelinux 或 SecondStageMain 的问题误归到首阶段挂载。
2.2 首阶段
FirstStageMain 负责在 system 分区可用前建立最小用户空间,随后把控制交给 SELinux setup。它是物理存储和策略加载之间的边界:这里读的是 ramdisk 和 block device,不能假设普通 system 文件已经可用。
源码文件:system/core/init/first_stage_init.cpp
int FirstStageMain(int argc, char** argv) {
boot_clock::time_point start_time = boot_clock::now();
std::vector<std::pair<std::string, int>> errors;
umask(0);
CHECKCALL(clearenv());
CHECKCALL(setenv("PATH", _PATH_DEFPATH, 1));
CHECKCALL(mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"));
CHECKCALL(mkdir("/dev/pts", 0755));
CHECKCALL(mount("devpts", "/dev/pts", "devpts", 0, NULL));
CHECKCALL(mount("proc", "/proc", "proc", 0,
"hidepid=2,gid=" MAKE_STR(AID_READPROC)));
CHECKCALL(mount("sysfs", "/sys", "sysfs", 0, NULL));
CHECKCALL(mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL));
// ... first-stage mount, module loading, and ramdisk handoff ...
}实际挂载和设备映射逻辑继续位于 first_stage_mount.cpp。入口负责阶段分发,资源算法进入下一个 owner,不应把所有首阶段代码复制到路线图中。
2.3 策略阶段
SetupSelinux 是首阶段和 second stage 之间的切换点。它加载已挂载分区上的 SELinux policy,并通过 execv 重新进入带 second_stage 参数的 init。于是同一 PID 1 在新策略下继续运行。
源码文件:system/core/init/selinux.cpp
int SetupSelinux(char** argv) {
SetStdioToDevNull(argv);
InitKernelLogging(argv);
SelinuxSetupKernelLogging();
bool use_overlays = EarlySetupOverlays();
if (IsMicrodroid()) {
LoadSelinuxPolicyMicrodroid();
} else {
LoadSelinuxPolicyAndroid();
}
SelinuxSetEnforcement();
// ... restorecon and overlay handling ...
const char* path = "/system/bin/init";
const char* args[] = {path, "second_stage", nullptr};
execv(path, const_cast<char**>(args));
PLOG(FATAL) << "execv failed";
}源码中的 helper 会随构建变体组合,但阅读重点稳定:策略加载、文件恢复标签、exec 复用 PID。遇到 AVC 应转到 SELinux策略链,不要把它当作 init action 语法问题。
3. Second stage
3.1 rc解析
SecondStageMain 在策略和基本文件系统就绪后创建 init 的核心对象,解析 init.rc、vendor rc、odm rc 和 product rc,并开始执行 action。这里的 owner 是 init parser 和 service manager,不是 zygote。
源码文件:system/core/init/init.cpp
int SecondStageMain(int argc, char** argv) {
if (REBOOT_BOOTLOADER_ON_PANIC && !AttemptingToBootNewSlot()) {
InstallRebootSignalHandlers();
}
SetStdioToDevNull(argv);
InitKernelLogging(argv);
LOG(INFO) << "init second stage started!";
SelinuxSetupKernelLogging();
PropertyInit();
UmountSecondStageRes();
MountExtraFilesystems();
SelabelInitialize();
SelinuxRestoreContext();
}读真实源码时应把上面抽象回 ActionManager、ServiceList、Epoll 的实际定义。学习结果不是记住三个 trigger,而是知道启动服务要从 rc 的 service 声明回到 Service::Start、fork、exec 和子进程回收。
3.2 服务状态
init 的 service owner 持有启动标志、PID、重启计数和 socket/namespace 配置。服务失败后,init 根据 service 状态和 class/trigger 规则决定重启或停止。
源码文件:system/core/init/service.cpp
Result<void> Service::Start() {
auto reboot_on_failure = make_scope_guard([this] {
if (on_failure_reboot_target_) {
trigger_shutdown(*on_failure_reboot_target_);
}
});
if (is_updatable() && !IsDefaultMountNamespaceReady()) {
ServiceList::GetInstance().DelayService(*this);
return Error() << "Cannot start an updatable service before APEX configs are loaded";
}
bool disabled = (flags_ & (SVC_DISABLED | SVC_RESET));
ResetFlagsForStart();
if (flags_ & SVC_RUNNING) {
if ((flags_ & SVC_ONESHOT) && disabled) {
flags_ |= SVC_RESTART;
}
reboot_on_failure.Disable();
return {};
}
}遇到 native daemon 未启动,下一步应搜其 rc 声明和 Service::Start,而不是直接读 daemon 的业务 main。
4. Zygote入口
4.1 启动参数
zygote 是 init 通过 rc 启动的 app_process Java runtime。进入 ZygoteInit.main 后,它解析 start-system-server、ABI 列表和 socket 名称。
源码文件:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String[] argv) {
RuntimeInit.preForkInit();
boolean startSystemServer = false;
String zygoteSocketName = "zygote";
String abiList = null;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
}
}
preload(bootTimingsTraceLog);
Zygote.initNativeState(isPrimaryZygote);
zygoteServer = new ZygoteServer(isPrimaryZygote);
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
if (r != null) {
r.run();
return;
}
}
zygoteServer.runSelectLoop(abiList);
}预加载是 zygote 的状态准备,runSelectLoop 是后续应用 fork 的消费者。SystemServer 的服务注册不属于 zygote;zygote 只负责准备运行时、fork 和监听命令 socket。
4.2 Fork边界
forkSystemServer 构造 uid、gid、capability、nice name 和 com.android.server.SystemServer 参数,再调用 native Zygote.forkSystemServer。返回值决定父子路径:
源码文件:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
String[] args = {
"--setuid=1000",
"--setgid=1000",
"--nice-name=system_server",
"--runtime-args",
"--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
"com.android.server.SystemServer",
};
int pid = Zygote.forkSystemServer(
parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,
parsedArgs.mRuntimeFlags, null,
parsedArgs.mPermittedCapabilities,
parsedArgs.mEffectiveCapabilities);
if (pid == 0) {
zygoteServer.closeServerSocket();
return handleSystemServerProcess(parsedArgs);
}
return null;
}父进程返回 null 并继续 select loop,子进程返回 Runnable 并运行 SystemServer。忽略返回值会把 system_server 错看成 zygote 内执行的普通 Java 方法。
5. SystemServer阶段
5.1 主循环
SystemServer 的 Java 入口很短,真正的路线从 run 开始。它建立 Looper、Binder 线程上限、异步初始化线程池和 native library,再启动服务阶段。
源码文件:frameworks/base/services/java/com/android/server/SystemServer.java
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
Looper.prepareMainLooper();
BinderInternal.setMaxThreads(sMaxBinderThreads);
SystemServerInitThreadPool.start();
System.loadLibrary("android_servers");
startBootstrapServices(t);
startCoreServices(t);
startOtherServices(t);
startApexServices(t);
updateWatchdogTimeout(t);
CriticalEventLog.getInstance().logSystemServerStarted();
Looper.loop();
}异步线程池使部分昂贵初始化并行,但服务依赖仍由显式阶段和 boot phase 控制。读服务启动问题时,先看阶段,再看异步任务何时提交和消费。
5.2 Bootstrap
startBootstrapServices 放置最早的核心 owner,例如 Watchdog、PlatformCompat、Installer、ActivityManagerService 和 PackageManagerService:
源码文件:frameworks/base/services/java/com/android/server/SystemServer.java
private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
t.traceBegin("startBootstrapServices");
Watchdog watchdog = Watchdog.getInstance();
watchdog.start();
PlatformCompat platformCompat = new PlatformCompat(mSystemContext);
ServiceManager.addService(Context.PLATFORM_COMPAT_SERVICE, platformCompat);
mSystemServiceManager.startService(Installer.class);
mActivityManagerService = mSystemServiceManager
.startService(ActivityManagerService.Lifecycle.class)
.getService();
mPackageManagerService = PackageManagerService.main(
mSystemContext, installer, domainVerificationService,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF);
t.traceEnd();
}这组服务的共同特征是后续服务需要它们提供进程、包、权限或安装基础设施。
5.3 Core与Other
startCoreServices 启动系统配置、电池、UsageStats、WebView、设备状态和统计服务;startOtherServices 创建面向功能的服务,并处理显示、输入、窗口和 boot phase。
源码文件:frameworks/base/services/java/com/android/server/SystemServer.java
private void startCoreServices(@NonNull TimingsTraceAndSlog t) {
t.traceBegin("startCoreServices");
mSystemServiceManager.startService(SystemConfigService.class);
mSystemServiceManager.startService(BatteryService.class);
mSystemServiceManager.startService(UsageStatsService.class);
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_WEBVIEW)) {
mWebViewUpdateService =
mSystemServiceManager.startService(WebViewUpdateService.class);
}
t.traceEnd();
}
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
t.traceBegin("startOtherServices");
WindowManagerService wm = WindowManagerService.main(
context, inputManager, !mFirstBoot, ...);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
mActivityManagerService.setWindowManager(wm);
wm.onInitReady();
t.traceEnd();
}Other services 不是简单的“最后启动”。它们经常在局部依赖满足后通过 startBootPhase、onInitReady 或异步线程池完成握手。
5.4 就绪信号
SystemServer 捕获启动异常并记录 Failure starting system services;成功后记录 system server ready 统计事件,随后进入 Looper:
源码文件:frameworks/base/services/java/com/android/server/SystemServer.java
try {
t.traceBegin("StartServices");
startBootstrapServices(t);
startCoreServices(t);
startOtherServices(t);
startApexServices(t);
updateWatchdogTimeout(t);
CriticalEventLog.getInstance().logSystemServerStarted();
} catch (Throwable ex) {
Slog.e("System",
"************ Failure starting system services", ex);
throw ex;
} finally {
t.traceEnd();
}这个边界把“服务构造失败”和“系统已经可响应”分开。
6. 阅读分支
不要按“init、zygote、SystemServer 全部读完”推进。根据现象选择分支:
| 现象 | 第一入口 | 第二入口 | 关键消费者 |
|---|---|---|---|
| 服务没启动 | rc 的 service | Service::Start | init ServiceList |
| AVC denied | scontext/tcontext | .te、file_contexts | 内核 SELinux |
| app 进程没创建 | ZygoteInit.main | ZygoteServer、fork 参数 | ActivityManager |
| system_server 崩溃 | SystemServer.run | 对应 start 阶段 | Watchdog/日志 |
| 服务已构造但未 ready | startBootPhase | onBootPhase/onInitReady | SystemServiceManager |
| Binder 调用失败 | 接口/AIDL | 发送者和 Stub | 服务消费者 |
路线图只有在每行都能落到真实入口时才有用。不要把 Framework 或 HAL 当作入口名;它们是范围,不是符号。
7. 策略边界
从本文列出的源码可以直接看到:
- init main 根据 argv 分发多个阶段,并在 first/SELinux/second stage 间复用 PID;
- zygote 预加载运行时后创建 ZygoteServer,通过 forkSystemServer 分出 system_server;
- SystemServer 以 bootstrap/core/other/apex 阶段启动服务,并在异常时终止启动;
- 服务问题应根据进程和阶段选择不同源码入口。
本文没有声称所有设备的 rc、vendor service 或启动耗时都相同;没有声称 SystemServer 中每个服务都严格串行;也没有把 Launcher、用户解锁和 boot completed 的完整链路纳入本文。它们需要进入 ActivityManager、PackageManager、WindowManager 或用户生命周期专题。
8. 阅读验证
在 Android 源码 checkout 中执行:
rg -n "return (FirstStageMain|SetupSelinux|SecondStageMain)" \
system/core/init/main.cpp
rg -n "forkSystemServer|startSystemServer|runSelectLoop" \
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
rg -n "startBootstrapServices|startCoreServices|startOtherServices|startApexServices" \
frameworks/base/services/java/com/android/server/SystemServer.java
rg -n "se_neverallow_test|domain_auto_trans" \
system/sepolicy/Android.bp system/sepolicy/private练习:假设 system_server 已出现,但某个服务没有对外提供 Binder。先判断它属于哪个 start 阶段,再搜索该服务的 onStart、ServiceManager.addService 或 onBootPhase,最后检查启动异常和依赖 phase。这个练习用于检查你是否能从现象选择入口,不等于覆盖系统启动的全部实现。
9. 边界
从 init 到 SystemServer 的路线应被当作导航坐标,而不是替代专题。每到一个边界都要记录:当前进程是谁、状态由谁拥有、下一阶段何时生效、失败由谁清理。沿这四个问题推进,才能从启动入口继续进入 Binder、服务状态、SELinux、HAL 或应用生命周期,而不会把目录浏览误当成源码理解。
