Android Binder机制(三) ------- 服务的管理ServiceManager

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;
}
  1. binder_open打开Binder驱动
  2. binder_become_context_manager使自己成为ServiceManager进程
  3. 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里有个成员变量Vector<handle_entry>mHandleToObject,该变量记录了所属进程所有的handle和Binder对象的映射。
  • lookupHandleLocked通过handle去mHandleToObject去查找对应的Binder对象
  • 如果没有找到就创建一个与之对应的BpBinder对象
  • 创建BpBinder时,传入的是handle。对应将该BpBinder对象的IBinder接口指针返回。

这样通过IServiceManager的getService方法得到一个IBinder指针,并且该指针指向一个BpBinder对象。

posted @ 2018-03-26 19:09  qzhang1535  阅读(530)  评论(0编辑  收藏  举报