The Binder Chicken-and-Egg Problem
Every Binder transaction requires a destination handle. If your application wants to talk to the Activity Manager, it needs an integer handle pointing to that specific object in the system server process. This creates an immediate chicken-and-egg problem. How do you find the handle to the process that gives you handles? The platform solves this with a dedicated discovery daemon called the ServiceManager.
Instead of passing raw integer handles around, Android maps system services to human-readable strings. When you request the "activity" service, you ask for a specific Binder handle. The ServiceManager acts exactly like a DNS server for these lookups. It maintains a dictionary mapping string names to their actual Binder references.
This raises another question. If the ServiceManager handles discovery, how do you find the ServiceManager itself? The Binder driver assigns this daemon a universally known address known as Handle 0. Every component on the system knows that sending a message to Handle 0 reaches the ServiceManager. The system can now securely bootstrap itself without relying on configuration files.
Registering System Services
When the device boots up, system components must announce their presence before applications can use them. The system_server process creates instances of core managers like the Activity Manager and the Package Manager. These managers are useless if other processes cannot find them. System components solve this by registering themselves with the ServiceManager.
The system_server registers a service by making a Binder transaction to Handle 0 with an addService() request. The ServiceManager receives this request and extracts the Binder object reference. It then checks if the calling process has the correct SELinux permissions to register that specific name.
If the security check passes, the daemon stores the string mapping in its internal dictionary. With the service registered, the platform is ready to serve client applications. This centralized registration prevents rogue processes from hijacking important system services.
Looking Up Services
Applications need a way to find services without keeping track of process addresses. Client applications only consume services, meaning they never register them. They use the framework to ask the ServiceManager for the correct handle. When a developer calls getSystemService(), the framework translates that into a lookup request.
Your application sends the string "activity" to Handle 0. The ServiceManager searches its dictionary for that string. It enforces SELinux rules again by checking the device security policy to verify your application is allowed to see this service. If permitted, the daemon returns the stored Binder handle back to the client.
You will see a sequence diagram below that shows how an application uses Handle 0 to find a system service. It visualizes the separation between the discovery phase and the actual communication phase. Watch how the client talks to the ServiceManager first, but subsequent calls go directly to the target service.
Direct communication bypasses the ServiceManager entirely. Once the client has the correct handle, it talks directly to the target process through the Binder driver. This keeps the discovery daemon out of the hot path for regular system operations.
The Kernel Driver Enforces the Magic
You might wonder how Handle 0 actually works under the hood without being a real process address. The system needs a way to guarantee that messages sent to Handle 0 always reach the authentic ServiceManager. The kernel handles this responsibility. The kernel intercepts transactions sent to Handle 0 and routes them to a specialized context manager.
When the init process starts the ServiceManager during boot, the daemon opens the Binder driver and claims the context manager role. The kernel hardcodes the routing from that point forward. Any transaction sent to Handle 0 automatically goes to the ServiceManager process.
By guarding this single point of discovery with strict kernel routing and SELinux policies, Android ensures that malicious applications cannot impersonate unauthorized system services. The ServiceManager provides a secure foundation for every inter-process communication that follows. But what happens when an application holds onto a handle and the underlying service crashes?