系统服务
主要关注以下几个方面:
- 如何使用系统服务
- 系统服务的发布
- 系统服务的注册原理
先画个图表来简单的概括一下
Android系统利用ServiceManager来统一管理系统服务;这样对于service端来说,只要将自身注册到Servicemanager中,就可以安心等待被调用,对于client端来说,需要调用某个服务时,只要在Servicemanager来查询是否有所需的服务,然后远程调用,免去了到处找服务的必要,很方便.
我们先从如何使用系统服务开始
上代码:
@Override
public Object getSystemService(String name) {
return SystemServiceRegistry.getSystemService(this, name);
}
一般使用系统服务时,通过Context的getSystemService()方法,传入服务的名称,然后这个方法会返回这个服务的接口对象,这个方法的实现原理具体是怎么养的呢?我们接下来追一追源码:这里首先调用了SystemServiceRegistry的getSystemService()方法,根据这个SystemServiceRegistry的注解,我们知道他是管理所有的系统服务的类.
/**
* Manages all of the system services that can be returned by {@link Context#getSystemService}.
* Used by {@link ContextImpl}.
*/
final class SystemServiceRegistry {
...
}
/**
* Gets a system service from a given context.
*/
public static Object getSystemService(ContextImpl ctx, String name) {
ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
return fetcher != null ? fetcher.getService(ctx) : null;
}
在getSystemService()方法中,通过服务的名称拿到服务对应的feacher,然后再调用ServiceFether的getServicemanager()方法来获取系统服务的接口对象;这个SYSTEM_SERVICE_FETCHERS是什么呢?
private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
new HashMap<String, ServiceFetcher<?>>();
根据定义,我们看到这个SYSTEM_SERVICE_FETCHERS是一个HashMap,就是说我们是根据服务的名称在这个HashMap中查找ServiceFetcher.再来看看getService()方法中做了什么:
public final T getService(ContextImpl ctx) {
final Object[] cache = ctx.mServiceCache;
final int[] gates = ctx.mServiceInitializationStateArray;
for (;;) {
boolean doInitialize = false;
synchronized (cache) {
// Return it if we already have a cached instance.
T service = (T) cache[mCacheIndex];
if (service != null || ...) {
return service;
}
...
}
...
if (doInitialize) {
// Only the first thread gets here.
T service = null;
@ServiceInitializationState int newState = ContextImpl.STATE_NOT_FOUND;
try {
// This thread is the first one to get here. Instantiate the service
// *without* the cache lock held.
service = createService(ctx);
newState = ContextImpl.STATE_READY;
} catch (ServiceNotFoundException e) {
onServiceNotFound(e);
} finally {
synchronized (cache) {
cache[mCacheIndex] = service;
gates[mCacheIndex] = newState;
cache.notifyAll();
}
}
return service;
}
...
}
...
}
在getService()方法中,首先看这个cache,这个cache是什么呢?我们看定义:
// The system service cache for the system services that are cached per-ContextImpl.
final Object[] mServiceCache = SystemServiceRegistry.createServiceCache();
可以看出,mServiceCache是一个数组,这个每个context都有一个mServiceCache,有多少个Context就有多少个mServiceCache;
然后进入for循环,根据mCacheIndex来获取一个service,这个service就是我们要的服务接口对象,当service为空,也就是说我们cache中还没有service,此时就需要创建新的service对象了,并且要保证只会创建一次,创建完成后讲将service塞到cache中,下次获取service时就可以直接从cache获取了,最后返回service.
那么这个createService是怎么实现的呢?继续追代码:
public abstract T createService(ContextImpl ctx) throws ServiceNotFoundException;
在这里,createService()是个抽象方法,看来他的具体实现得要根据具体的服务来具体实现;我们就选择RadioManager来看看:
registerService(Context.RADIO_SERVICE, RadioManager.class,
new CachedServiceFetcher<RadioManager>() {
@Override
public RadioManager createService(ContextImpl ctx) throws ServiceNotFoundException {
return new RadioManager(ctx);
}});
public RadioManager(@NonNull Context context) throws ServiceNotFoundException {
mContext = context;
mService = IRadioService.Stub.asInterface(
ServiceManager.getServiceOrThrow(Context.RADIO_SERVICE));
}
我们可以看到:先要获取一个IBinder对象,然后封装成IRadioService对象,这是为了可以进程Binder通信。对new 出来的RadioManager对象的操作,最后装移到mServices(IRadioService.Stub对象)上。mServices是怎么获取的呢?
是通过Context.RADIO_SERVICE常量(就是服务的名称)来获取一个IBinder对象,然后将获取到的IBinder传入asInterface()方法中转换成我们所需要的mService ;我们先看看怎么通过Context.RADIO_SERVICE来获取IBinder 的。
/**
* Returns a reference to a service with the given name, or throws
* {@link NullPointerException} if none is found.
*
* @hide
*/
public static IBinder getServiceOrThrow(String name) throws ServiceNotFoundException {
final IBinder binder = getService(name);
if (binder != null) {
return binder;
} else {
throw new ServiceNotFoundException(name);
}
}
.....
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return Binder.allowBlocking(rawGetService(name));
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
...
private static IBinder rawGetService(String name) throws RemoteException {
final long start = sStatLogger.getTime();
....
final IBinder binder = getIServiceManager().getService(name);
...
}
通过以上代码,再通过各个法发调用关系,我们找到 final IBinder binder = getIServiceManager().getService(name);通过
getIServiceManager方法获得IServiceManager的对象(ServiceManager代理端,可以进行binder通信)。通过Binder通信在ServiceManager中在查找服务并返回。【这里就先不继续,现在只要知道服务的查找是在ServiceManager中实现的,在后面和服务的添加的内容一起讲讲】
系统服务发布
系统服务要向被其他的应用或者服务调用,就得让其他进程找到别切自身具备进程通讯的能力,这些有SystemServiceManager创建并启动的服务,都是继承SystemService,但是并没有实现IBinder,所以不可以进程binder通信,但是绝大部分SystemService都会在onStart()中调用SystemManagerService#publicBinderService(String name, IBinder service, boolean allowIsolated);就是在onStart()中注册Binder服务。
我们看看publicBinderService()方法是怎样的:
/**
* Publish the service so it is accessible to other services and apps.
*/
protected final void publishBinderService(String name, IBinder service) {
publishBinderService(name, service, false);
}
...
protected final void publishBinderService(String name, IBinder service,
boolean allowIsolated, int dumpPriority) {
ServiceManager.addService(name, service, allowIsolated, dumpPriority);
}
public static void addService(String name, IBinder service, boolean allowIsolated,
int dumpPriority) {
try {
getIServiceManager().addService(name, service, allowIsolated, dumpPriority);
} catch (RemoteException e) {
Log.e(TAG, "error in addService", e);
}
}
从上面的代码可以看到,系统服务最后会调用ServiceManager的addService()方法向ServiceManager注册。在ServiceManager的addService()方法中首先调用getIServiceManager方法获得IServiceManager的对象(ServiceManager代理端,可以进行binder通信)。通过Binder通信在ServiceManager中在服务添加。【这里就先不继续,现在只要知道服务的发乎就是要在ServiceManager中添加,在后面和服务的查找一起讲讲】
我们先回来看看怎么获取IServiceManager对象的:
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// Find the service manager
sServiceManager = ServiceManagerNative
.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
return sServiceManager;
}
static public IServiceManager asInterface(IBinder obj)
{
if (obj == null) {
return null;
}
IServiceManager in =
(IServiceManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ServiceManagerProxy(obj);
}
getIServiceManager()方法主要是获取sServiceManager 【sServiceManager就是IServiceManager的实例】。如果系统中sServiceManager已经存在就直接返回,如果不存在就创建新的sServiceManager。
那我们就看看怎么获取sServiceManager的?首先通过BinderInternal。getContextObject()来过去一个全局上下文,这通常是一般是IServiceManager的实现,然后通过这个上下文获取到一个IBidner对象,最后将IBidner传入ServiceManagerNative.asInterface()方法获得sServiceManager。
我们看看asInterface()方法是怎么通过IBInder来获取到ServiceManager的代理对象的?这里是通过queryLocalInterface()方法请求相应的描述符时返回给定的所有者iInterface,此处即是获取IServiceManager。【因为IServiceManager是实现IInterface的】;如果descripter不存在,那就重新new 一个ServiceManagerProxy。到此,我们就知道怎么获取ServiceManager的代理对象的。
系统服务的查找和添加原理
前面说到查找和发布服务是通过ServiceManage添加的,在ServiceManager的代理对象拿服务后,真正进行服务添加的是在ServiceManager进程中,ServiceManager是拥Binder通信能力的独立服务【主要都是C++在底层实现的】,它在创建的时候就将自己注册成为Binder管理者,主要就是对跨进程服务的管理(添加和查找)【这个涉及到Binder的,比较大,目前我也还没有深入,这里就简单说说,只要知道它是个系统服务的管理者就够了,实际开发中这方面好像也不需要我们来参与什么】
ServiceManager在成为系统服务的的管理者后,主要任务也不多,就是系统服务的查找和注册。
int main(int argc, char** argv)
{
...
bs = binder_open(driver, 128*1024); // 打开Binder
...
if (binder_become_context_manager(bs)) { // 把自己注册为Binder管理者
ALOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
...
binder_loop(bs, svcmgr_handler); // 进入loop.
return 0;
}
int svcmgr_handler(...)
{
....
switch(txn->code) {
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE: // 查找服务
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid);
if (!handle)
break;
bio_put_ref(reply, handle);
return 0;
case SVC_MGR_ADD_SERVICE: // 添加服务
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
handle = bio_get_ref(msg);
allow_isolated = bio_get_uint32(msg) ? 1 : 0;
dumpsys_priority = bio_get_uint32(msg);
if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, dumpsys_priority,
txn->sender_pid))
return -1;
break;
case SVC_MGR_LIST_SERVICES: {
...
default:
ALOGE("unknown code %d\n", txn->code);
return -1;
}
bio_put_uint32(reply, 0);
return 0;
}
ServiceManager使用C++实现的,接下来主要看main函数做了什么。它主要做了三件事:
- 打开Binder
- 把自己注册为Binder管理者
- 进入loop监听,使用svcmgr_handler来处理应用请求
我们之前通过向ServiceManager查找和添加服务的操作,最后都是在svcmgr_handler函数中处理的,在svcmgr_handler函数通传进来的请求码确定是要查找还是添加服务,然后进行相应的处理;需要注意的是:这里传入的和返回都是服务的handler,并不是对实际的服务进行操作,这样是的ServiceManager变的很小很轻(内存占用少,操作对象简单)。【这里面就不具体深入,我们知道ServiceManager是怎么个处理流程就好。】
通过追源码,我们知道系统服务的使用,注册和查找的基本流程,但是Android系统服务这一块也是很大的,具体细节还需要具体深入查看源码和和其他资料。