Service Manager是android系统服务的管理者。系统中运行的服务程序首先应向Service Manager注册。当一个
进程需要使用某个service,该进程需要首先通过Service Manager获取所需service的信息。用户、service manager
与service的关系如下图所示:
一、 ServiceManager主要功能的实现
Service Manager的实现主要在Service_Manager.c文件中,它主要完成了已下三个方面的功能。
1.注册Service
它会将新Service添加请求中的Service信息加入到系统的Service链表中(svclist)。并不是所有的注册请求都会得
到响应,当发出请求的进程具有相应的权限时,才会做出相应操作。权限可以分为以下2种:
(1)特权。具有root和system权限的进程可以注册任何服务
(2)普通权利。对于一般进程,需要查看该进程是否有权限注册它所请求的Service。每个Service对应有一个uid表
示可以对其进行注册的进程。
注册新Service的流程如下图所示。
2.查询service
根据名称查询已经注册的service,在查询的过程中也加入了权限控制。如果服务不允许沙盒进程查询,则沙盒进
程无法取得该服务的信息。(沙盒进程的进程ID偏移量为99000 -99999)。
3.列出所有Service
此功能将返回所有已注册service的名称,任何进程均有权限获取。
二、Android注册服务流程分析
Android系统中,必须将服务注册到service manager中,该服务才能被使用。服务的注册流程主要包括下面几步:
(1)客户进程向ServiceManager进程发送IPC服务注册信息;
(2)ServiceManager进程接收客户进程发送过来的IPC数据;
(3)ServiceManager进程登记注册服务;
(4)ServiceManager向客户进程发送IPC返回信息;
(5)客户进程接收ServiceManager进程发送过来的IPC数据;
在java中是通过调用ServiceManager.addService()来注册服务,addService的实现如下
public static void addService(String name, IBinder service) {
try {
getIServiceManager().addService(name, service, false);
} catch (RemoteException e) {
Log.e(TAG, "error in addService", e);
}
}
addService通过getIServiceManager()获取ServiceManager的代理ServiceManagerProxy,并调用代理对象的addService函数来注册服务。getIServiceManager的实现如下:
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// Find the service manager
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
Java层通过以下两个步骤来获取ServiceManager的代理对象的引用:
(1) BinderInternal.getContextObject() 创建一个Java层的BinderProxy对象,
该对象与C++层的BpBinder一一对应;
(2)ServiceManagerNative.asInterface(obj) 创建一个Java层面的ServiceManagerProxy代理对象,
作用与C++层的BpServiceManager相同。
ServiceManagerProxy中的addService函数通过BinderProxy与Binder驱动交互,将数据发送出去。Service
manager收到该消息后,注册相关服务并返回消息。注册Service中较为重要的JAVA类及其主要作用如下图所示:
三、Android查询服务流程分析
客户端查询service是通过调用ServiceManager.etService(),该函数的实现如下:
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return getIServiceManager().getService(name);
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
为了加快查询的速度,会将查询过的服务都存储在名为sCache的HashMap中。如果查找的服务在缓存中不存
在,则通过getIServiceManager().getService(name)来查询服务。函数getIServiceManager在注册流程中已经分析
过,它最终创建了ServiceManagerProxy,并通过其中的getService接口将查询请求发送至service manager。
Service manager收到该消息后,查询相关服务并返回服务的相关信息。