理解 Android 系统启动过程

一直以来,对 Android 底层的认识与学习都不是很多,最近通过阅读《Android 进阶解密》,以及结合其他一些优秀的博文,对这一块知识点有了一点浅显的认知。

自己能力有限,水平一般,对比较底层的流程只能做到了解,主要就是参考这些博文以及结合最新的 Android Q 的代码来做一个浅显的认识,文中对这些文章中关键内容的拷贝,仅抱以学习之心,特此说明,所有参考文章均在文末附上链接。

启动电源

引导芯片从固化在 ROM 中的代码处执行。

加载引导程序

引导程序即 BootLoader 是在 Android 系统运行前的一个小程序,通过被加载到 RAM 中来拉起 Android 系统。

Linux Kernel 启动

这一步主要是完成系统的设置,通过 init.rc 文件来启动 init 进程。

init 进程启动

创建和挂载启动所需文件目录,启动属性服务,在 system/core/init/init.cpp 中通过解析system/core/rootdir/init.zygote64.rc (64位下)脚本文件来启动 Zygote 进程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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 //service 命令会通过create_socket函数来在/dev/socket目录下创建zygote文件,并通过文件描述符写入到环境变量中
socket usap_pool_primary stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks

这里意思 Service 通知 init 进程来创建名为 zygote 的进程,其中 /system/bin/app_process64 为需要执行的程序路径,后边的-Xzygote/system/bin--zygote--start-system-server为参数,onrestart 关键字表示的为 zygote 进程重启时需要执行的命令。

Zygote 进程启动

Service 类型的解析是在 system/core/init/service.cpp 中,通过一系列的解析,会去执行 /system/bin/app_process64 ,其对应的文件为 frameworks/base/cmds/app_process/app_main.cpp ,它的 main 方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class AppRuntime : public AndroidRuntime
...
static const char ZYGOTE_NICE_NAME[] = "zygote64";
int main(int argc, char* const argv[])
{
...
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
}
...
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
}
...
}

这里 runtime 是 AppRuntime 类型,而 AppRuntime 又是继承自 /frameworks/base/core/jni/AndroidRuntime.cpp,其 start 方法会启动 Android 运行时库,并调用 “className” 的 “static void main(String[] args)” 方法,代码如下:

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
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
...
/* 启动Java虚拟机 */
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
...
/* 注册JNI方法 */
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
...
//要调用的 main 方法的参数
stringClass = env->FindClass("java/lang/String");
strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
//替换 className 中的 '.' 为 '/'
char* slashClassName = toSlashClassName(className != NULL ? className : "");
//要调用的 class 为 ZygoteInit
jclass startClass = env->FindClass(slashClassName);
//要调用的方法为 main
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
//通过 JNI 调用 ZygoteInit 的 main 方法
env->CallStaticVoidMethod(startClass, startMeth, strArray);

最后通过 JNI 去调用了 ZygoteInit 的 main 方法,此时 Zygote 进程已经启动,并且从 C++ 层走到了 Java 层。

Socket 创建

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java 的 main 方法如下:

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
29
30
31
32
33
34
35
36
37
public static void main(String argv[]) {
...
// Zygote goes into its own process group.
try {
Os.setpgid(0, 0);//设置 pid 和 gid 为0
} catch (ErrnoException ex) {
throw new RuntimeException("Failed to setpgid(0,0)", ex);
}
...
boolean startSystemServer = false;
String zygoteSocketName = "zygote";
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if (argv[i].startsWith("--socket-name=")) {
zygoteSocketName = argv[i].substring("--socket-name=".length());
}
...
}
...
//创建 Socket 接口
zygoteServer = new ZygoteServer(isPrimaryZygote);
if (startSystemServer) {
//fork SystemServer 进程
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
if (r != null) {
r.run();
return;
}
}
//等待 AMS 请求
caller = zygoteServer.runSelectLoop(abiList);
if (caller != null) {
caller.run();
}
...
}

/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java 的构造函数中,会通过调用 frameworks/base/core/java/com/android/internal/os/Zygote.java 的静态方法 createManagedSocketFromInitSocket 来创建一个名为 “zygote” 的 Socket 服务端,用于等待 ActivityManagerService 创建新应用进程的请求。

1
2
3
4
5
ZygoteServer(boolean isPrimaryZygote) {
...
mZygoteSocket = Zygote.createManagedSocketFromInitSocket("zygote");
...
}

Zygote#createManagedSocketFromInitSocket() 代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
int fileDesc;
try {
String env = System.getenv("ANDROID_SOCKET_zygote");//得到 Socket 环境变量的值
fileDesc = Integer.parseInt(env);//转换为文件描述符
} catch (RuntimeException ex) {
throw new RuntimeException("Socket unset or invalid: " + fullSocketName, ex);
}

try {
FileDescriptor fd = new FileDescriptor();
fd.setInt$(fileDesc);
return new LocalServerSocket(fd);//创建 Socket 并返回
} catch (IOException ex) {
throw new RuntimeException(
"Error building socket from file descriptor: " + fileDesc, ex);
}
}

这里通过环境变量 “ANDROID_SOCKET_zygote” 得到的文件描述符代表的文件为 dev/socket/zygote,该环境变量的设置,就是在 init.cpp 中解析 init.zygote64.rc文件时设置的。创建好了 Socket 后,再调用 ZygoteServer#runSelectLoop() 在 Zygote 进程中通过 while(true) 无限循环等待接收新的请求。

SystemServer 进程启动

SystemServer 进程的创建是通过调用 ZygoteInit#forkSystemServer 来 fork 出的,代码如下:

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
29
30
31
32
33
34
35
36
37
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
` ...
/* Hardcoded command line to start the system server */
String args[] = {
"--setuid=1000",//用户 id 为 1000
"--setgid=1000",//用户组 id 为 1000
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
+ "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",//进程名为 system_server
"--runtime-args",
"--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
"com.android.server.SystemServer",//启动的类名
};
ZygoteArguments parsedArgs = null;
int pid;
try {
parsedArgs = new ZygoteArguments(args);
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.mUid, parsedArgs.mGid,
parsedArgs.mGids,
parsedArgs.mRuntimeFlags,
null,
parsedArgs.mPermittedCapabilities,
parsedArgs.mEffectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
...
zygoteServer.closeServerSocket();
return handleSystemServerProcess(parsedArgs);
}
}

这里 pid 如果返回为 0,则说明是当前是运行在子进程中,即 SystemServer 进程中,因为 SystemServer 进程是通过 Zygote 进程 fork 而来,因此也会有 Zygote 进程创建的 Socket,但 system_server 并不需要它,因此需要调用 closeServerSocket() 来关闭。

创建完成后接下来则需要启动 SystemServer 进程,通过调用 handleSystemServerProcess() 来实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* Finish remaining work for the newly forked system server process.
*/
private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
createSystemServerClassLoader();//为 SystemServer 创建 PathClassLoader
ClassLoader cl = sCachedSystemServerClassLoader;
if (cl != null) {
Thread.currentThread().setContextClassLoader(cl);
}
/*
* Pass the remaining arguments to SystemServer.
*/
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mRemainingArgs, cl);
}

ZygoteInit#zygoteInit() 中通过 ZygoteInit.nativeZygoteInit() 来启动 Binder 线程池,方便可以进行进程间通信,而 RuntimeInit.applicationInit() 则是通过反射获取到 SystemServer 类的实例并调用它的 main 方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) {
...
ZygoteInit.nativeZygoteInit();//
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}

//com.android.internal.os.RuntimeInit#applicationInit
protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) {
...
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
//com.android.internal.os.RuntimeInit#findStaticMain
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
...
cl = Class.forName(className, true, classLoader);
m = cl.getMethod("main", new Class[] { String[].class });
...
mMethod.invoke(null, new Object[] { mArgs });
}

接下来流程便走到了 /frameworks/base/services/java/com/android/server/SystemServer.java 的 main 方法中,它里面又调用了 run() 方法:

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
29
30
31
public static void main(String[] args) {
new SystemServer().run();
}

private void run() {
...
// Prepare the main looper thread (this thread).
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_FOREGROUND);
android.os.Process.setCanSelfBackground(false);
Looper.prepareMainLooper();
// Initialize native services.
System.loadLibrary("android_servers");
// Initialize the system context.
createSystemContext();
// Create the system service manager.
mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager.setStartInfo(mRuntimeRestart,
mRuntimeStartElapsedTime, mRuntimeStartUptime);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Prepare the thread pool for init tasks that can be parallelized
SystemServerInitThreadPool.get();
...
// Start services.
startBootstrapServices();
startCoreServices();
startOtherServices();
SystemServerInitThreadPool.shutdown();
...
// Loop forever.
Looper.loop();
}

run() 方法中,会去创建 Looper 和 Context,SystemServiceManager 主要是用来对系统服务进行创建、启动和管理声明周期,创建是通过反射来获取实例,然后添加到一个名为 mServices 的 ArrayList 中,它用与保存所有的服务,最后会调用 service.onStart(),所有的服务类都会去继承 SystemService 或是通过内部类继承。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public SystemService startService(String className) {
...
final Class<SystemService> serviceClass;
serviceClass = (Class<SystemService>)Class.forName(className);
...
Constructor<T> constructor = serviceClass.getConstructor(Context.class);
service = constructor.newInstance(mContext);
...
return startService(service);
}

public void startService(@NonNull final SystemService service) {
// Register it.
mServices.add(service);
// Start it.
long time = SystemClock.elapsedRealtime();
...
service.onStart();
...
}

系统服务的启动被分为了3个方法来执行,startBootstrapServices() 是用来启动系统启动所需服务,这些服务都是彼此依赖比较复杂,因此需要统一初始化,这里会初始化很多重要的服务,例如 AMS、PMS等:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private void startBootstrapServices() {
//启动 WatchDog
final Watchdog watchdog = Watchdog.getInstance();
watchdog.start();
//安装 Apk 所需的服务
Installer installer = mSystemServiceManager.startService(Installer.class);
//用与四大组件管理的服务
mActivityManagerService = ActivityManagerService.Lifecycle.startService(
mSystemServiceManager, atm);
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
//用与管理安装包的服务
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
//
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);

}

startCoreServices() 主要用来启动一些必要但是并不和系统启动紧密依赖的服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private void startCoreServices() {
//追踪电池电量的服务
mSystemServiceManager.startService(BatteryService.class);
//跟踪应用程序使用情况的服务
mSystemServiceManager.startService(UsageStatsService.class);
//追踪 binder 调用的 cpu 耗时的服务
mSystemServiceManager.startService(BinderCallsStatsService.LifeCycle.class);
//追踪 handler 处理消息耗时的服务
mSystemServiceManager.startService(LooperStatsService.Lifecycle.class);
//捕获异常的服务
mSystemServiceManager.startService(BugreportManagerService.class);
//GPU 和 GPU 驱动的服务
mSystemServiceManager.startService(GpuService.class);
}

startOtherServices() 中启动的服务很多,比较熟悉的有以下一些:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private void startOtherServices() {
mSystemServiceManager.startService(new AlarmManagerService(context));
inputManager = new InputManagerService(context);
//窗口管理服务,并设置给 AMS
wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
mActivityManagerService.setWindowManager(wm);
mSystemServiceManager.startService(WALLPAPER_SERVICE_CLASS);
mSystemServiceManager.startService(AudioService.Lifecycle.class);
mSystemServiceManager.startService(ADB_SERVICE_CLASS);
mSystemServiceManager.startService(USB_SERVICE_CLASS);
//息屏显示
mSystemServiceManager.startService(DreamManagerService.class);
//通知AMS可以去加载初始化的应用,这里会去加载 Launcher
mActivityManagerService.systemReady(() -> {
...
})
//启动 SystemUI
startSystemUi(context, windowManagerF);
}

Launcher 启动

由于 Launcher 的启动过程还包括进程 fork 等操作,这里先不去关注那些细节,只看下 Launcher 启动的大致流程。在 SystemServer#startOtherServices() 中会调用 mActivityManagerService.systemReady() 来通知 AMS系统已经准备就绪,这里 AMS 会去启动主界面的 Activity。

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
29
30
31
public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
...
mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");
...
}
//com.android.server.wm.ActivityTaskManagerService.LocalService#startHomeOnAllDisplays()
@Override
public boolean startHomeOnAllDisplays(int userId, String reason) {
synchronized (mGlobalLock) {
return mRootActivityContainer.startHomeOnAllDisplays(userId, reason);
}
}
//com.android.server.wm.RootActivityContainer#startHomeOnAllDisplays()
boolean startHomeOnAllDisplays(int userId, String reason) {
boolean homeStarted = false;
for (int i = mActivityDisplays.size() - 1; i >= 0; i--) {
final int displayId = mActivityDisplays.get(i).mDisplayId;
homeStarted |= startHomeOnDisplay(userId, reason, displayId);
}
return homeStarted;
}
//com.android.server.wm.RootActivityContainer#startHomeOnDisplay()
boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting, boolean fromHomeKey) {
...
homeIntent = mService.getHomeIntent();
aInfo = resolveHomeActivity(userId, homeIntent);
...
mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,
displayId);
return true;
}

上面是一些调用的流程,可以看到最后是调用到了 RootActivityContainer#startHomeOnDisplay() 中,首先会获得一个包含属性 "android.intent.category.HOME" 的 Intent,接着会调用RootActivityContainer#resolveHomeActivity()并传入这个 Intent,通过 PMS 来查找符合条件的 ActivityInfo。最后会通过 ActivityStartController#startHomeActivity 来启动 Acitivty。

SystemUI 启动

startSystemUi() 中会去启动 SystemUIService,在 Service 的 onCreate() 中再去调用 SystemUIApplication#startServicesIfNeeded(),该方法内会通过遍历一个 String 数组来以此启动所有的 SystemUI 服务。

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
private static void startSystemUi(Context context, WindowManagerService windowManager) {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.android.systemui",
"com.android.systemui.SystemUIService"));
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
context.startServiceAsUser(intent, UserHandle.SYSTEM);
windowManager.onSystemUiStarted();
}

public class SystemUIService extends Service {

@Override
public void onCreate() {
super.onCreate();
((SystemUIApplication) getApplication()).startServicesIfNeeded();
...
}
...
}

//com.android.systemui.SystemUIApplication#startServicesIfNeeded()
public void startServicesIfNeeded() {
String[] names = getResources().getStringArray(R.array.config_systemUIServiceComponents);
startServicesIfNeeded(names);
}

config_systemUIServiceComponents 中包含了所有的 System UI 模块,例如通知、锁屏、最近任务、状态栏等等,他们均继承了抽象类 com.android.systemui.SystemUIstartServicesIfNeeded()内部依旧是通过反射来获取实例并调用 SystemUI#start() 来通知各个模块初始化。

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
<string-array name="config_systemUIServiceComponents" translatable="false">
<item>com.android.systemui.Dependency$DependencyCreator</item>
<item>com.android.systemui.util.NotificationChannels</item>
<item>com.android.systemui.statusbar.CommandQueue$CommandQueueStart</item>
<item>com.android.systemui.keyguard.KeyguardViewMediator</item>
<item>com.android.systemui.recents.Recents</item>
<item>com.android.systemui.volume.VolumeUI</item>
<item>com.android.systemui.stackdivider.Divider</item>
<item>com.android.systemui.SystemBars</item>
<item>com.android.systemui.usb.StorageNotification</item>
<item>com.android.systemui.power.PowerUI</item>
<item>com.android.systemui.media.RingtonePlayer</item>
<item>com.android.systemui.keyboard.KeyboardUI</item>
<item>com.android.systemui.pip.PipUI</item>
<item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item>
<item>@string/config_systemUIVendorServiceComponent</item>
<item>com.android.systemui.util.leak.GarbageMonitor$Service</item>
<item>com.android.systemui.LatencyTester</item>
<item>com.android.systemui.globalactions.GlobalActionsComponent</item>
<item>com.android.systemui.ScreenDecorations</item>
<item>com.android.systemui.biometrics.BiometricDialogImpl</item>
<item>com.android.systemui.SliceBroadcastRelayHandler</item>
<item>com.android.systemui.SizeCompatModeActivityController</item>
<item>com.android.systemui.statusbar.notification.InstantAppNotifier</item>
<item>com.android.systemui.theme.ThemeOverlayController</item>
</string-array>

参考

刘望舒:《Android 进阶解密》第2章 Android 系统启动

Gityuan:Android系统启动-综述

老罗-Android系统进程Zygote启动过程的源代码分析

大猫玩程序-Android10.0系统启动之Launcher(桌面)启动流程