The system_server process is the beating heart of Android. It hosts almost all core system services (ActivityManager, PackageManager, WindowManager, etc.). However, it does not start from a standard init script like native daemons. Instead, it is the very first process forked by Zygote.
ZygoteInit.forkSystemServer()
When Android boots, the init process starts the Zygote daemon (app_process). Zygote initializes the Dalvik/ART virtual machine, preloads common Java classes and resources into memory, and then calls ZygoteInit.main().
The first meaningful action ZygoteInit.main() takes is calling forkSystemServer().
// Simplified snippet from ZygoteInit.java
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
if (r != null) {
r.run(); // Runs in the newly forked system_server process
return;
}
This fork is identical to how user applications are launched later, but with special privileges. Because it is forked, system_server inherits the preloaded ART VM and classes, ensuring a rapid startup.
UID and GID Assignment to system_server
A crucial part of forkSystemServer() is assigning the correct Linux identity. It parses arguments specifying the UID, GID, and supplementary groups.
The system_server is assigned a fixed UID of 1000 (defined as AID_SYSTEM). It is also granted numerous supplementary GIDs (like AID_AUDIO, AID_CAMERA, AID_NET_ADMIN) allowing it to bypass standard file and device node permissions to interact directly with hardware drivers and network interfaces.
Capabilities Assigned to system_server
In addition to standard Linux UIDs/GIDs, Android utilizes Linux Capabilities to grant fine-grained root-like privileges without running the process as full root (UID 0).
During the fork, Zygote grants system_server specific capabilities such as CAP_SYS_NICE (to change thread priorities for other processes), CAP_NET_ADMIN (to configure network interfaces), and CAP_BLOCK_SUSPEND (to acquire wake locks and prevent the CPU from sleeping).
system_server Process Initialization
Once the native fork() completes:
- Zygote State Cleanup: The child process (now
system_server) closes the Zygote listening socket, as it should not accept app launch requests. - Native Setup: It calls
nativeZygoteInit()to establish the Binder thread pool. This is critical; without it,system_servercannot receive IPC calls from native daemons or future apps. - Java Entry: Finally, it uses reflection to locate
com.android.server.SystemServer.main()and executes it, transferring control to the main Java initialization sequence.