Skip to content

System AIDL Services

Simão Gomes Viana edited this page Mar 16, 2026 · 1 revision

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.

When to Use

  • 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

Architecture

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()

AIDL Module

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.

Service Registration

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.

SELinux

System AIDL services need three things in SELinux:

1. Service type declaration

In device/<org>/sepolicy/common/private/service.te:

type my_foo_service, system_api_service, system_server_service, service_manager_type;
  • system_server_service — allows system_server to register it (add_service)
  • system_api_service — allows priv_app (SystemUI, Settings) to find it
  • service_manager_type — required base attribute

2. Service context mapping

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().

3. Attributes (no extra work needed)

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.

Client Usage

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.

Key Differences from HAL AIDLs

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

Clone this wiki locally