AOSP Framework & Internals
4 min read

Service Startup Order

Learn about Service Startup Order.

If you boot an Android device, over 100 system services need to initialize before the user sees the lock screen. Imagine throwing all 100 into a thread pool and starting them simultaneously. The system would instantly crash as services try to bind to dependencies that do not exist yet.

To prevent this chaos, Android forces a strict, hardcoded boot sequence. The SystemServer process acts as the conductor for this sequence. This process explicitly divides the startup execution into three distinct phases. By controlling the exact order of initialization, the system guarantees that dependencies are ready before any service asks for them.

Laying the Foundation

You cannot draw a window if the screen is off. You cannot track processes if you cannot parse packages. The system must establish a baseline of survival before it attempts anything complex.

This requirement gives us the Bootstrap phase. SystemServer triggers this early execution by calling startBootstrapServices(). Executing this method initializes the absolute most critical services required to keep the device alive.

ActivityManagerService starts first to manage memory and processes. Next, PowerManagerService initializes immediately so the CPU does not go back to sleep mid-boot. We then see PackageManagerService spin up to resolve application binaries, followed closely by DisplayManagerService preparing the screen. Without these core pillars, the rest of Android cannot wake up.

Adding Essential Hardware Monitoring

Once the CPU and memory are stable, the system needs to monitor the physical state of the device. Attempting high-level operations without knowing battery levels or thermal constraints risks hardware damage.

This brings us to the Core phase. SystemServer invokes startCoreServices() to build on top of the Bootstrap layer. These services rely entirely on the foundational managers being active.

Here, you will find BatteryService monitoring hardware temperatures and charge levels. UsageStatsService starts tracking app usage. This tracking requires both the Activity and Package managers to be fully awake. WebViewUpdateService also initializes to ensure rendering engines are prepared. The system has now gained enough stability to start preparing user-facing features.

Booting the Rest of the World

With the foundation and hardware monitoring in place, the device still needs to handle touch events, play audio, and draw the UI. The remaining 80 services must start in a specific order to avoid race conditions.

The SystemServer handles this massive workload by calling startOtherServices(). Platform engineers strictly hardcoded the order throughout this massive method. For instance, WindowManagerService cannot start before DisplayManagerService. The window manager needs the physical dimensions of the screen to calculate layouts. Similarly, NotificationManagerService waits for AudioManager so it knows how to route notification sounds.

This phase boots InputManagerService to listen for screen taps and starts NetworkManagementService to configure routing tables. By the end of this method, every single service has registered with ServiceManager. The device has populated all of its components, but Android still forbids the services from talking to each other.

The Starting Pistol

When hundreds of services depend on each other, you inevitably hit circular dependencies. If the Window Manager needs the Activity Manager, but the Activity Manager needs the Window Manager, they cannot simply wait for each other to finish starting.

Android solves this using a two-phased initialization model. The boot sequence instantiates services in their respective phases. However, Android forbids them from communicating with other services during creation. Instead, they must wait for a specific signal that confirms the entire system is awake.

The following sequence diagram maps out this starting pistol mechanism. Visualizing this callback chain reveals how Android safely breaks circular dependencies without deadlocking. Pay attention to how the Activity Manager takes over coordination duties from the SystemServer to notify the remaining components.

The systemReady() callback acts as the universal synchronization point. Once startOtherServices() finishes, SystemServer calls ActivityManagerService.systemReady(). The Activity Manager then turns around and invokes the systemReady() method on every other registered service.

When a service receives this callback, it finally knows the entire system has initialized. Making Binder calls to WindowManager, PackageManager, or any other component is now completely safe. Services no longer risk throwing a NullPointerException or a DeadObjectException. The framework is fully alive and waiting for instructions. But it currently has no user applications to run. How does this newly awakened system actually spawn a fresh application process from scratch?