Once you have defined your AIDL interface and written the concrete Java or C++ implementation, your service needs to be made available to the rest of the Android system. This is accomplished by registering it with the servicemanager.
Most high-level Android system services (like ActivityManagerService or PowerManagerService) are initialized and registered within the SystemServer process.
The SystemService Wrapper
In AOSP, you rarely call ServiceManager.addService() directly in your service's constructor. Instead, you create a wrapper class that extends com.android.server.SystemService. This wrapper provides lifecycle hooks that the SystemServer will call at appropriate times during boot.
package com.android.server.mycustom;
import android.content.Context;
import com.android.server.SystemService;
import android.os.ServiceManager;
public class MyCustomSystemService extends SystemService {
private final MyCustomService mImpl;
public MyCustomSystemService(Context context) {
super(context);
mImpl = new MyCustomService(context); // Your actual AIDL implementation
}
@Override
public void onStart() {
// Publish the service so clients can find it
publishBinderService("my_custom_service", mImpl);
}
@Override
public void onBootPhase(int phase) {
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
// Safe to interact with other core services here
mImpl.systemReady();
}
}
}
Adding Service in SystemServer.java
To actually start your service, you must modify frameworks/base/services/java/com/android/server/SystemServer.java. The SystemServer runs through several phases (Bootstrap, Core, and Other services). You must decide where your service fits.
If your service is not critical to the very early boot process, you typically add it in startOtherServices():
// Inside SystemServer.java
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
// ... other services ...
t.traceBegin("StartMyCustomService");
mSystemServiceManager.startService(MyCustomSystemService.class);
t.traceEnd();
// ...
}
When mSystemServiceManager.startService() is called, it instantiates your wrapper class and immediately calls its onStart() method.
publishBinderService vs ServiceManager.addService
The publishBinderService() method provided by the SystemService base class is just a convenient wrapper around the lower-level ServiceManager.addService() API.
What happens under the hood?
- The service implementation (which extends the generated AIDL stub) is cast to an
IBinderobject. - An IPC call is made to the
/dev/binderdriver, destined for context manager (process 0, which is theservicemanagerdaemon). - The
servicemanagerchecks the SELinux policy (service_contextsand.tefiles) to verify thatsystem_serveris permitted toadda service of this specific type. - If permitted,
servicemanageradds the string name ("my_custom_service") and the Binder reference to its internal hash map.
Service Startup Ordering and systemReady()
Booting an OS is a complex dependency graph. Your service might need to query the PackageManager to check app permissions, but the PackageManager might not be fully initialized when your service's onStart() is called.
To solve this, use the onBootPhase() hook. The system guarantees that when PHASE_SYSTEM_SERVICES_READY is reached, all core services are registered and functioning. You should defer any cross-service initialization logic to your custom systemReady() method, which is called during this phase.