Steps
1. Create an AIDL Interface
System services expose their API through AIDL.
Location:
frameworks/base/core/java/android/os/
Example: IMyService.aidl
package android.os;
interface IMyService {
String sayHello(String name);
}
This generates the Binder interface (Stub, Proxy) used for IPC.
2. Create the Service Implementation
Location:
frameworks/base/services/core/java/com/android/server/
Example: MyService.java
package com.android.server;
import android.content.Context;
import android.os.IMyService;
public class MyService extends IMyService.Stub {
private final Context mContext;
public MyService(Context context) {
mContext = context;
}
@Override
public String sayHello(String name) {
return "Hello " + name + " from System Service";
}
}
This class extends the AIDL Stub, meaning it receives Binder calls.
3. Create a Manager Class (Framework API)
Apps shouldn’t talk to Binder directly. They use a Manager.
Location:
frameworks/base/core/java/android/os/
Example: MyServiceManager.java
package android.os;
public class MyServiceManager {
private IMyService mService;
public MyServiceManager() {
mService = IMyService.Stub.asInterface(ServiceManager.getService("myservice"));
}
public String sayHello(String name) {
try {
return mService.sayHello(name);
} catch (Exception e) {
return null;
}
}
}
4. Add Service Constant to Context
Apps retrieve services using:
Context.getSystemService()
So add constant in:
frameworks/base/core/java/android/content/Context.java
public static final String MY_SERVICE = "myservice";
5. Register Service in SystemServer
Now Android needs to start your service during boot.
Edit:
frameworks/base/services/java/com/android/server/SystemServer.java
Inside startOtherServices():
import com.android.server.MyService;
import android.os.ServiceManager;
ServiceManager.addService("myservice", new MyService(context));
6. Register in SystemServiceRegistry
File:
frameworks/base/core/java/android/app/SystemServiceRegistry.java
Add:
registerService(
Context.MY_SERVICE,
MyServiceManager.class,
new CachedServiceFetcher<MyServiceManager>() {
@Override
public MyServiceManager createService(ContextImpl ctx) {
return new MyServiceManager();
}
}
);
SystemServiceRegistry maps a service name to its manager class so that applications can access system services through Context.getSystemService() instead of interacting with Binder or ServiceManager directly.
Without SystemServiceRegistry you would have to manually get access to service using a binder.
IBinder b = ServiceManager.getService("myservice");
IMyService service = IMyService.Stub.asInterface(b);
CachedServiceFetcher ensures: one manager instance per app process
Without that, every call to getSystemService() would create new objects.
7. Rebuild AOSP
source build/envsetup.sh
lunch aosp_arm64-eng
make -j8
8. Using the Service in an App
MyServiceManager service = (MyServiceManager) context.getSystemService(Context.MY_SERVICE);
String msg = service.sayHello("Captain");
9. Verify if the service is running
adb shell service list
10. Service not starting
We can see from the below logs our service not started in the boot time.
adb logcat | grep MathService
01-19 01:04:46.553 653 653 I SystemServerTiming: MathService
01-19 01:04:46.553 653 653 E SystemServer: BOOT FAILURE starting MathService
01-19 01:04:46.554 653 653 D SystemServerTiming: MathService took to complete: 1ms
AVC Denial, If SELinux blocks your service, check for avc denial:
avc: denied { add }
for pid=648 uid=1000 name=math
scontext=u:r:system_server:s0
tcontext=u:object_r:default_android_service:s0
tclass=service_manager
permissive=0
11. Update SEPolicy
SELinux policy might block your service from starting which we can see in the above logs. Update the policy for math service.
Update the below se policy in service_contexts available in system/sepolicy/private
Add the following line:
math u:object_r:activity_service:s0