-
Notifications
You must be signed in to change notification settings - Fork 11
System AIDL Services
AIDL interfaces for communication between system components (e.g., a system service in system_server exposing an API to SystemUI). Unlike HAL AIDLs which cross the vendor/framework boundary, these live entirely in the system partition.
- A system service needs to expose an API to other system apps (SystemUI, Settings, etc.)
- You want type-safe IPC without polluting the boot classpath
- The alternative (Settings.Global/System flags, config resource overlays) doesn't fit
frameworks/custom/interfaces/ # Standalone AIDL module
category/
Android.bp # java_library
package/name/IFoo.aidl
services/core/ # System service implements the stub
com/android/server/foo/FooService.java
→ publishBinderService("namespace.service.name", mStub)
packages/SystemUI/ # Client queries via ServiceManager
→ ServiceManager.checkService("namespace.service.name")
→ IFoo.Stub.asInterface(binder).method()
Keep it out of frameworks/base/core/java/ — that ends up in framework.jar on the boot classpath, which has a strict package allowlist. Use a standalone java_library instead:
// frameworks/custom/interfaces/category/Android.bp
java_library {
name: "my.service.aidl",
srcs: ["my/service/IFoo.aidl"],
sdk_version: "system_current",
}
Both the service module (services.core) and the client (SystemUI) add this to static_libs.
Use publishBinderService() in SystemService.onStart():
public class FooService extends SystemService {
private static final String SERVICE_NAME = "my.namespace.service.foo";
private final IFooManager.Stub mStub = new IFooManager.Stub() {
@Override
public boolean isSupported() { return mBackendAvailable; }
};
@Override
public void onStart() {
publishBinderService(SERVICE_NAME, mStub);
}
}Service name: Use a fully-qualified namespace (e.g., custom.system.service.charging), not a bare name like "battery". AOSP owns the short namespace.
System AIDL services need three things in SELinux:
In device/<org>/sepolicy/common/private/service.te:
type my_foo_service, system_api_service, system_server_service, service_manager_type;
-
system_server_service— allowssystem_serverto register it (add_service) -
system_api_service— allowspriv_app(SystemUI, Settings) to find it -
service_manager_type— required base attribute
In device/<org>/sepolicy/common/private/service_contexts:
my.namespace.service.foo u:object_r:my_foo_service:s0
The string must match the SERVICE_NAME passed to publishBinderService().
system_server already has blanket add_service permission for system_server_service types, and priv_app has blanket find permission for system_api_service types. No per-service allow rules needed.
val binder = ServiceManager.checkService("my.namespace.service.foo") ?: return false
val service = IFooManager.Stub.asInterface(binder)
service.isSupported()Use checkService (non-blocking) rather than getService (blocking) in UI code like QS tiles.
| Aspect | HAL AIDL | System AIDL |
|---|---|---|
| Partition boundary | vendor ↔ framework | framework ↔ framework |
| Stability |
@VintfStability, frozen versions |
No stability requirement |
| Registration |
AServiceManager_addService (native) |
publishBinderService (Java) |
| SELinux |
hal_service_type in dynamic policy |
system_server_service in private policy |
| Build module |
aidl_interface with NDK/Java backends |
Simple java_library
|
| Service discovery | VINTF manifest |
ServiceManager directly |