Search code examples
androidandroid-source

AOSP Stubs vs getSystemService


I've been mucking around with AOSP and I've noticed something about System Services. A lot of them like to use access the System Service Stubs directly like so:

IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
                ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));

This is done instead of requesting them using mContext, like so:

DevicePolicyManager dpm = (DevicePolicyManager)  
     context.getSystemService(Context.DEVICE_POLICY_SERVICE);

Now at first I thought it might be because there is no context available but there is. An excellent example of this is in the deletePackageX method which is a part of the PackageManagerService class. You can change the stub method to the getSystemService method and everything still SEEMS to work just fine.

Naturally there is security reasons to why apps can not use the stub method, but there must be some reason that they are using the stub method for system services.

So the question is why are they using Stubs over context for getting other system services?


Solution

  • So after digging into ContextImpl.java to see what the getSystemService call is doing, it's really just a wrapper around the Stub.asInterface call you often see in system services. So when you make a system service and you want it to be exposed to the SDK then you need to register it with the context so that non system apps are able to get a handle to it. Registration looks like this for most services:

    registerService(ALARM_SERVICE, new ServiceFetcher() {
                    public Object createService(ContextImpl ctx) {
                        IBinder b = ServiceManager.getService(ALARM_SERVICE);
                        IAlarmManager service = IAlarmManager.Stub.asInterface(b);
                        return new AlarmManager(service, ctx);
                    }});
    

    Looks familiar? But when you get the system service back, the service fetcher will do some other overhead like cache your service so you can get it back faster on subsequent calls. (there's more overhead there that I haven't looked into in great detail but I assume is for optimization)

    So basically, by directly getting the service via the stub you are saving on overhead and performing the operation a faster than if you go through the context. The context is only there so that your service can be accessed by non-system apps, and you want to expose it via the SDK. But ultimately, the same code is getting executed in the end.

    If you are a system app, it's probably faster to get the service via the stub.