当前位置: 代码迷 >> 综合 >> Android系统服务管理者——ServiceManager
  详细解决方案

Android系统服务管理者——ServiceManager

热度:28   发布时间:2024-01-04 10:18:10.0

Android系统给我们提供了上百个服务,每一个服务都有一个服务中介类,例如WindowManager、ActivityManager等。 通常我们和系统服务进行交互都是通过服务中介来进行的。通过Context.getSystemService(String name)我们可以获取系统服务,并在客户端封装成中介类,然后通过该中介类去获取相关的系统服务。那么到底系统服务和中介类是怎么获取的呢? 我们知道Context的实现类为ContextImpl,所以我们进入到ContextImpl的getSystemService(String name)方法中:

@Override
public Object getSystemService(String name) {
    return SystemServiceRegistry.getSystemService(this, name);
}

这里执行了SystemServiceRegistry.getSystemService(String name)方法,继续跟踪该方法:

public static Object getSystemService(ContextImpl ctx, String name) {ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);return fetcher != null ? fetcher.getService(ctx) : null;
}

可以看到系统服务中介类是从ServiceFetcher.getService(ContextImpl ctx)方法获取的,而ServiceFetcher对象由SYSTEM_SERVICE_FETCHERS生成。SYSTEM_SERVICE_FETCHERS是一个HashMap,其Key为系统服务名,Value为ServiceFetcher对象。 那我们找一下SYSTEM_SERVICE_FETCHERS是什么时候被赋值的?在SystemServiceRegistry的registerService(String serviceName, Class<T> serviceClass, ServiceFetcher<T> serviceFetcher)方法中我们找到了:

private static <T> void registerService(String serviceName, Class<T> serviceClass,ServiceFetcher<T> serviceFetcher) {SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);//在这类SYSTEM_SERVICE_FETCHERS被赋值SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
}

再看registerService方法是什么时候被调用的?可以找到在SystemServiceRegistry类的静态代码块中调用了registerService方法:

static {registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,new CachedServiceFetcher<AccessibilityManager>() {@Overridepublic AccessibilityManager createService(ContextImpl ctx) {
    return AccessibilityManager.getInstance(ctx);}});registerService(Context.CAPTIONING_SERVICE, CaptioningManager.class,new CachedServiceFetcher<CaptioningManager>() {@Overridepublic CaptioningManager createService(ContextImpl ctx) {return new CaptioningManager(ctx);}});registerService(Context.ACCOUNT_SERVICE, AccountManager.class,new CachedServiceFetcher<AccountManager>() {@Overridepublic AccountManager createService(ContextImpl ctx) throws ServiceNotFoundException {IBinder b = ServiceManager.getServiceOrThrow(Context.ACCOUNT_SERVICE);IAccountManager service = IAccountManager.Stub.asInterface(b);return new AccountManager(ctx, service);}});registerService(Context.ACTIVITY_SERVICE, ActivityManager.class,new CachedServiceFetcher<ActivityManager>() {@Overridepublic ActivityManager createService(ContextImpl ctx) {return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());}});registerService(Context.ALARM_SERVICE, AlarmManager.class,new CachedServiceFetcher<AlarmManager>() {@Overridepublic AlarmManager createService(ContextImpl ctx) throws ServiceNotFoundException {IBinder b = ServiceManager.getServiceOrThrow(Context.ALARM_SERVICE);IAlarmManager service = IAlarmManager.Stub.asInterface(b);return new AlarmManager(service, ctx);}});...省略
}

这里多次调用了registerService方法,每一个registerService方法的参数中都new了一个ServiceFetcher对象。还记得上面我们说到的系统服务中介类是怎么来的吗?没错,就是通过ServiceFetcher对象的getService(ContextImpl ctx)获取的。而ServiceFetcher是一个接口,其getService(ContextImpl ctx)方法由子类来实现。在子类的实现方法中getService(ContextImpl ctx)方法又调用了createService(ContextImpl ctx)方法并返回,所以createService(ContextImpl ctx)方法生成的对象就是我们需要获取的服务中介类。

最开始的时候我们提到,服务中介类只是对系统服务的一个封装。那就表明在ServiceFetcher对象的createService(ContextImpl ctx)方法中肯定是能获取系统服务对象的。让我们看一个具体的例子:

registerService(Context.ALARM_SERVICE, AlarmManager.class,new CachedServiceFetcher<AlarmManager>() {@Overridepublic AlarmManager createService(ContextImpl ctx) throws ServiceNotFoundException {IBinder b = ServiceManager.getServiceOrThrow(Context.ALARM_SERVICE);IAlarmManager service = IAlarmManager.Stub.asInterface(b);return new AlarmManager(service, ctx);}});

上面是获取闹钟系统服务的一个例子。 第一步: 通过ServiceManager.getServiceOrThrow(String name)获取了服务端的Binder对象,而getServiceOrThrow最终调用的还是getService(String name)方法:

public static IBinder getService(String name) {try {IBinder service = sCache.get(name);if (service != null) {return service;} else {return Binder.allowBlocking(getIServiceManager().getService(name));}} catch (RemoteException e) {Log.e(TAG, "error in getService", e);}return null;
}

上面的代码告诉我们,如果有缓存则从缓存获取服务端的Binder对象,如果没有则调用getIServiceManager().getService(String name)获取服务端的Binder对象:

private static IServiceManagergetIServiceManager() {if (sServiceManager != null) {return sServiceManager;}// Find the service managersServiceManager = ServiceManagerNative.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));return sServiceManager;
}

从上面的代码可以看到获取服务端Binder对象也是通过Binder对象进行跨进程通信获取的(IServiceManager是一个Binder对象)。

第二步: 通过调用IAlarmManager.Stub.asInterface(Binder binder)方法将第一步获取到的Binder对象转换成所需的系统服务对象。 这里说明一下,这个方法是区分进程的,如果客户端和服务端位于同一个进程,则返回服务端的Stub对象本身,否则返回的是系统封装后的Stub.proxy对象(该对象作为代理对象,与服务端进行通信并将数据返回给客户端)。

ServiceManager在这里起到的作用是对所有的系统服务进行管理,其提供了getService(String name)addService(String name)checkService(String name)listServices(String name)等方法。

  相关解决方案