Registering a service with the servicemanager makes it accessible via Binder IPC, but application developers do not interact with raw Binder interfaces. They use high-level, client-side APIs. Exposing your system service correctly involves creating a Manager class and registering it with the Android Application framework.
The Manager Class Pattern
In Android, every major system service has a corresponding client-side Manager class. For example, LocationManagerService is paired with LocationManager, and ActivityManagerService is paired with ActivityManager.
You must create a MyCustomManager class in the framework API (frameworks/base/core/java/android/os/).
package android.os;
import android.content.Context;
import android.os.IMyCustomService;
public class MyCustomManager {
private final Context mContext;
private final IMyCustomService mService;
/** @hide */
public MyCustomManager(Context context, IMyCustomService service) {
mContext = context;
mService = service;
}
/**
* Gets the current status of the custom hardware.
*/
public int getStatus() {
try {
return mService.getStatus();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
The Manager class hides the Binder IPC complexities (RemoteException handling) and provides a clean, object-oriented API to the application layer.
Context.getSystemService() Registration
Developers obtain Manager instances using Context.getSystemService(). To enable this, you must register your Manager class in SystemServiceRegistry.java.
// Inside frameworks/base/core/java/android/app/SystemServiceRegistry.java
static {
// ... other services ...
registerService(Context.MY_CUSTOM_SERVICE, MyCustomManager.class,
new CachedServiceFetcher<MyCustomManager>() {
@Override
public MyCustomManager createService(ContextImpl ctx) throws ServiceNotFoundException {
IBinder b = ServiceManager.getServiceOrThrow("my_custom_service");
IMyCustomService service = IMyCustomService.Stub.asInterface(b);
return new MyCustomManager(ctx, service);
}
});
}
This code snippet tells the Android framework: "When an app requests MY_CUSTOM_SERVICE, fetch the raw binder object from ServiceManager, wrap it in the AIDL stub, and pass it to the constructor of MyCustomManager, then return that Manager to the app."
Hiding APIs with @SystemApi and @hide
When adding new code to frameworks/base, you must carefully manage API visibility. Modifying the public Android SDK is a rigorous process controlled by Google. Most custom OEM features should not be added to the public SDK.
@hide: Placing this JavaDoc annotation on a class or method completely removes it from the generated SDK documentation and theandroid.jarstub file used by Android Studio. Third-party apps cannot easily compile against it.@SystemApi: This annotation (often used in conjunction with@hide) exposes the API only to applications signed with the platform certificate or installed in the/system/priv-app/directory. This is the standard way to expose APIs intended for bundled system applications (like a custom Settings app) without leaking them to the public SDK.
If you modify APIs, you will typically need to run make update-api to update the API signature tracking files (e.g., current.txt or system-current.txt) in the AOSP tree to satisfy the build system.