ServiceManager介绍
ServiceManager本身也是一个服务,它是android系统中所有服务的管理者。服务的注册与查询都要经过它的处理。ServiceManager的源码在frameworks/native/cmds/servicemanager目录下。
看下servicemanager的主函数
int main(int argc, char **argv)
{
struct binder_state *bs;
bs = binder_open(128*1024);
if (!bs) {
ALOGE("failed to open binder driver\n");
return -1;
}
if (binder_become_context_manager(bs)) {
ALOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
selinux_enabled = is_selinux_enabled();
sehandle = selinux_android_service_context_handle();
selinux_status_open(true);
if (selinux_enabled > 0) {
if (sehandle == NULL) {
ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");
abort();
}
if (getcon(&service_manager_context) != 0) {
ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");
abort();
}
}
union selinux_callback cb;
cb.func_audit = audit_callback;
selinux_set_callback(SELINUX_CB_AUDIT, cb);
cb.func_log = selinux_log_callback;
selinux_set_callback(SELINUX_CB_LOG, cb);
binder_loop(bs, svcmgr_handler);
return 0;
}
- binder_open打开Binder驱动
- binder_become_context_manager使自己成为ServiceManager进程
- binder_loop进入循环,监听客户端的请求
服务的注册
仍然以SurfaceFlinger的注册为例来。其关键代码如下:
// publish surface flinger
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);
- defaultServiceManager获取ServiceManager的Binder接口IServiceManager。该过程主要是服务的查询与获取,后文会说到。
- 调用IServiceManager的addService方法注册服务,该方法为IBinder接口。实际会调用ServiceManager的svcmgr_handler去处理。
int svcmgr_handler(struct binder_state *bs,
struct binder_transaction_data *txn,
struct binder_io *msg,
struct binder_io *reply)
{
......
switch(txn->code) {
......
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;
if (do_add_service(bs, s, len, handle, txn->sender_euid,
allow_isolated, txn->sender_pid))
return -1;
break;
......
}
bio_put_uint32(reply, 0);
return 0;
}
根据传入的code,我们调用do_add_service方法去处理。
int do_add_service(struct binder_state *bs,
const uint16_t *s, size_t len,
uint32_t handle, uid_t uid, int allow_isolated,
pid_t spid)
{
......
si = find_svc(s, len);
if (si) {
if (si->handle) {
ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
str8(s, len), handle, uid);
svcinfo_death(bs, si);
}
si->handle = handle;
} else {
si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
if (!si) {
ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",
str8(s, len), handle, uid);
return -1;
}
si->handle = handle;
si->len = len;
memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
si->name[len] = '\0';
si->death.func = (void*) svcinfo_death;
si->death.ptr = si;
si->allow_isolated = allow_isolated;
si->next = svclist;
svclist = si;
}
binder_acquire(bs, handle);
binder_link_to_death(bs, handle, &si->death);
return 0;
}
- ServiceManager通过svclist这个链表来保存系统中所有的服务。每个结点上都有服务的名字name和服务的引用handle。
- 添加服务时,先根据名字从svclist查找服务。
- 如果找到,就把新的引用赋值到节点上。
- 如果没有找到,则创建一个新的svcinfo节点,给节点赋值,最后把结点插入到服务链表svclist中。这样服务就完成了注册。
服务的查询
在文件IServiceManager.h中定义了一个全局函数getService,用来获取Binder服务。函数实现如下:
template<typename INTERFACE>
status_t getService(const String16& name, sp<INTERFACE>* outService)
{
const sp<IServiceManager> sm = defaultServiceManager();
if (sm != NULL) {
*outService = interface_cast<INTERFACE>(sm->getService(name));
if ((*outService) != NULL) return NO_ERROR;
}
return NAME_NOT_FOUND;
}
- 调用defaultServiceManager方法得到ServiceManager接口
- 调用ServiceManager接口的getService方法获取Binder服务。该函数实现在BpServiceManager::getService()方法中
virtual sp<IBinder> getService(const String16& name) const
{
unsigned n;
for (n = 0; n < 5; n++){
sp<IBinder> svc = checkService(name);
if (svc != NULL) return svc;
ALOGI("Waiting for service %s...\n", String8(name).string());
sleep(1);
}
return NULL;
}
- 该函数根据服务名字查找对应的服务,若找到则返回一个IBinder用引。(该引用指向一个BpBinder对象)
- 该函数实质调用BpServiceManager::checkService方法
virtual sp<IBinder> checkService( const String16& name) const
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
return reply.readStrongBinder();
}
- 封装parcel数据data,调用远程服务
- checkService将请发往ServiceManager服务处理。
checkService服务端的实现
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(bs, s, len, txn->sender_euid, txn->sender_pid);
if (!handle)
break;
bio_put_ref(reply, handle);
return 0;
getService和checkService走同一个分支,调用do_find_service。
uint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, uid_t uid, pid_t spid)
{
struct svcinfo *si = find_svc(s, len);
if (!si || !si->handle) {
return 0;
}
if (!si->allow_isolated) {
// If this service doesn't allow access from isolated processes,
// then check the uid to see if it is isolated.
uid_t appid = uid % AID_USER;
if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
return 0;
}
}
if (!svc_can_find(s, len, spid)) {
return 0;
}
return si->handle;
}
- do_find_service从之前注册的svclist上查找对应的服务并返回的句柄。然后我们在回到checkService客户端调用处。
- checkService函数从reply中读取服务端返回过来的数据(Bpinder对象)
- readStrongBinder从parcel数据包中读出一个IBinder接口对象,它主要调用unflatten_binder函数来展开parcel数据包
status_t unflatten_binder(const sp<ProcessState>& proc,
const Parcel& in, sp<IBinder>* out)
{
const flat_binder_object* flat = in.readObject(false);
if (flat) {
switch (flat->type) {
case BINDER_TYPE_BINDER:
*out = reinterpret_cast<IBinder*>(flat->cookie);
return finish_unflatten_binder(NULL, *flat, in);
case BINDER_TYPE_HANDLE:
*out = proc->getStrongProxyForHandle(flat->handle);
return finish_unflatten_binder(
static_cast<BpBinder*>(out->get()), *flat, in);
}
}
return BAD_TYPE;
}
- 由于是客户端调用,flag->type为BINDER_TYPE_HANDLE。
- getStrongProxyForHandle根据flat_binder_object里的handle取得得对应的代理对象,并赋值给out.
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
// We need to create a new BpBinder if there isn't currently one, OR we
// are unable to acquire a weak reference on this current one. See comment
// in getWeakProxyForHandle() for more info about this.
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
if (handle == 0) {
// Special case for context manager...
// The context manager is the only object for which we create
// a BpBinder proxy without already holding a reference.
// Perform a dummy transaction to ensure the context manager
// is registered before we create the first local reference
// to it (which will occur when creating the BpBinder).
// If a local reference is created for the BpBinder when the
// context manager is not present, the driver will fail to
// provide a reference to the context manager, but the
// driver API does not return status.
//
// Note that this is not race-free if the context manager
// dies while this code runs.
//
// TODO: add a driver API to wait for context manager, or
// stop special casing handle 0 for context manager and add
// a driver API to get a handle to the context manager with
// proper reference counting.
Parcel data;
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, NULL, 0);
if (status == DEAD_OBJECT)
return NULL;
}
b = new BpBinder(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
// This little bit of nastyness is to allow us to add a primary
// reference to the remote proxy when this team doesn't have one
// but another team is sending the handle to us.
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
- ProcessState里有个成员变量VectormHandleToObject,该变量记录了所属进程所有的handle和Binder对象的映射。
- lookupHandleLocked通过handle去mHandleToObject去查找对应的Binder对象
- 如果没有找到就创建一个与之对应的BpBinder对象
- 创建BpBinder时,传入的是handle。对应将该BpBinder对象的IBinder接口指针返回。
这样通过IServiceManager的getService方法得到一个IBinder指针,并且该指针指向一个BpBinder对象。