zoukankan      html  css  js  c++  java
  • Android源码分析(十二)ServiceManager服务分析

    一.启动过程分析

    基于 binder 机制实现通信,添加服务,查询服务,获取服务。查询,获取服务时候需要检查权限,android是基于Linux底层,所以也很好的实现了linux多用户管理。
    frameworks
    ativecmdsservicemanagerservicemanager.rc
    service servicemanager /system/bin/servicemanager
        class core animation
        user system
        group system readproc
        critical
        onrestart restart healthd
        onrestart restart zygote
        onrestart restart audioserver
        onrestart restart media
        onrestart restart surfaceflinger
        onrestart restart inputflinger
        onrestart restart drm
        onrestart restart cameraserver
        writepid /dev/cpuset/system-background/tasks

    从上面可知,如果ServiceManager服务异常退出的话,系统会重启。

    frameworks
    ativecmdsservicemanagerservice_manager.c
    int main(int argc, char** argv)
    {
        struct binder_state *bs;
        union selinux_callback cb;
        char *driver;
    
        if (argc > 1) {
            driver = argv[1];
        } else {
            driver = "/dev/binder";
        }
    
        bs = binder_open(driver, 128*1024);
        if (!bs) {
        #ifdef VENDORSERVICEMANAGER
            ALOGW("failed to open binder driver %s
    ", driver);
            while (true) {
                sleep(UINT_MAX);
            }
        #else
            ALOGE("failed to open binder driver %s
    ", driver);
        #endif
            return -1;
        }
    
        if (binder_become_context_manager(bs)) {
            ALOGE("cannot become context manager (%s)
    ", strerror(errno));
            return -1;
        }
    
        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);
    
        #ifdef VENDORSERVICEMANAGER
        sehandle = selinux_android_vendor_service_context_handle();
        #else
        sehandle = selinux_android_service_context_handle();
        #endif
        selinux_status_open(true);
    
        if (sehandle == NULL) {
            ALOGE("SELinux: Failed to acquire sehandle. Aborting.
    ");
            abort();
        }
    
        if (getcon(&service_manager_context) != 0) {
            ALOGE("SELinux: Failed to acquire service_manager context. Aborting.
    ");
            abort();
        }
    
    
        //loop 接受消息。并将binder解析完的消息返回给svcmgr_handler处理。
        binder_loop(bs, svcmgr_handler);
    
        return 0;
    }

    从这我们知道,ServiceManager是基于binder机制实现的。进入binder.c中了解下binder_open,binder_loop,然后binder将解析完的消息,返回给svcmag_handler处理

    frameworks ativecmdsservicemanagerinder.c

        struct binder_state *binder_open(const char* driver, size_t mapsize)
    {
        struct binder_state *bs;
        struct binder_version vers;
    
        bs = malloc(sizeof(*bs));
        if (!bs) {
            errno = ENOMEM;
            return NULL;
        }
    
        bs->fd = open(driver, O_RDWR | O_CLOEXEC);
        if (bs->fd < 0) {
            fprintf(stderr,"binder: cannot open %s (%s)
    ",
                    driver, strerror(errno));
            goto fail_open;
        }
    
        if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
            (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
            fprintf(stderr,
                    "binder: kernel driver version (%d) differs from user space version (%d)
    ",
                    vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION);
            goto fail_open;
        }
    
        bs->mapsize = mapsize;
        bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
        if (bs->mapped == MAP_FAILED) {
            fprintf(stderr,"binder: cannot map device (%s)
    ",
                    strerror(errno));
            goto fail_map;
        }
    
        return bs;
    }
    View Code
    void binder_loop(struct binder_state *bs, binder_handler func)
    {
        int res;
        struct binder_write_read bwr;
        uint32_t readbuf[32];
    
        bwr.write_size = 0;
        bwr.write_consumed = 0;
        bwr.write_buffer = 0;
    
        readbuf[0] = BC_ENTER_LOOPER;
        binder_write(bs, readbuf, sizeof(uint32_t));
    
        for (;;) {
            bwr.read_size = sizeof(readbuf);
            bwr.read_consumed = 0;
            bwr.read_buffer = (uintptr_t) readbuf;
    
            res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
    
            if (res < 0) {
                ALOGE("binder_loop: ioctl failed (%s)
    ", strerror(errno));
                break;
            }
    
            //解析消息
            res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
            if (res == 0) {
                ALOGE("binder_loop: unexpected reply?!
    ");
                break;
            }
            if (res < 0) {
                ALOGE("binder_loop: io error %d %s
    ", res, strerror(errno));
                break;
            }
        }
    }
    View Code
    binder_parse 解析接受到的消息 
    binder_send_reply 接收到消息,并解析完消息后,binder将解析后的消息返回给ServiceManager
    void binder_send_reply(struct binder_state *bs,
                           struct binder_io *reply,
                           binder_uintptr_t buffer_to_free,
                           int status)
    {
        struct {
            uint32_t cmd_free;
            binder_uintptr_t buffer;
            uint32_t cmd_reply;
            struct binder_transaction_data txn;
        } __attribute__((packed)) data;
    
        data.cmd_free = BC_FREE_BUFFER;
        data.buffer = buffer_to_free;
        data.cmd_reply = BC_REPLY;
        data.txn.target.ptr = 0;
        data.txn.cookie = 0;
        data.txn.code = 0;
        if (status) {
            data.txn.flags = TF_STATUS_CODE;
            data.txn.data_size = sizeof(int);
            data.txn.offsets_size = 0;
            data.txn.data.ptr.buffer = (uintptr_t)&status;
            data.txn.data.ptr.offsets = 0;
        } else {
            data.txn.flags = 0;
            data.txn.data_size = reply->data - reply->data0;
            data.txn.offsets_size = ((char*) reply->offs) - ((char*) reply->offs0);
            data.txn.data.ptr.buffer = (uintptr_t)reply->data0;
            data.txn.data.ptr.offsets = (uintptr_t)reply->offs0;
        }
        binder_write(bs, &data, sizeof(data));
    }
    View Code

    继续回到serviceManager里分析binder解析返回回来的服务消息

    frameworks ativecmdsservicemanagerservicemanager.rc

    int svcmgr_handler(struct binder_state *bs,
                       struct binder_transaction_data *txn,
                       struct binder_io *msg,
                       struct binder_io *reply)
    {
        struct svcinfo *si;
        uint16_t *s;
        size_t len;
        uint32_t handle;
        uint32_t strict_policy;
        int allow_isolated;
    
        //ALOGI("target=%p code=%d pid=%d uid=%d
    ",
        //      (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid);
    
        if (txn->target.ptr != BINDER_SERVICE_MANAGER)
            return -1;
    
        if (txn->code == PING_TRANSACTION)
            return 0;
    
        // Equivalent to Parcel::enforceInterface(), reading the RPC
        // header with the strict mode policy mask and the interface name.
        // Note that we ignore the strict_policy and don't propagate it
        // further (since we do no outbound RPCs anyway).
        strict_policy = bio_get_uint32(msg);
        s = bio_get_string16(msg, &len);
        if (s == NULL) {
            return -1;
        }
    
        //检查是否是servicemanager服务
        if ((len != (sizeof(svcmgr_id) / 2)) ||
            memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
            fprintf(stderr,"invalid id %s
    ", str8(s, len));
            return -1;
        }
    
        if (sehandle && selinux_status_updated() > 0) {
            struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle();
            if (tmp_sehandle) {
                selabel_close(sehandle);
                sehandle = tmp_sehandle;
            }
        }
    
        switch(txn->code) {
        case SVC_MGR_GET_SERVICE:
        //检查服务,do_find_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;
    
        //添加服务 do_add_service 获取服务 在do_add_service会检查是否具有权限
        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;
        //查询服务
        case SVC_MGR_LIST_SERVICES: {
            uint32_t n = bio_get_uint32(msg);
    
            if (!svc_can_list(txn->sender_pid, txn->sender_euid)) {
                ALOGE("list_service() uid=%d - PERMISSION DENIED
    ",
                        txn->sender_euid);
                return -1;
            }
            si = svclist;
            while ((n-- > 0) && si)
                si = si->next;
            if (si) {
                bio_put_string16(reply, si->name);
                return 0;
            }
            return -1;
        }
        default:
            ALOGE("unknown code %d
    ", txn->code);
            return -1;
        }
    
        bio_put_uint32(reply, 0);
        return 0;
    }

    进入 do_find_service  do_add_service了解下做了什么事。

    uint32_t do_find_service(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, uid)) {
            return 0;
        }
    
        return si->handle;
    }
    View Code
    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)
    {
        struct svcinfo *si;
    
        //ALOGI("add_service('%s',%x,%s) uid=%d
    ", str8(s, len), handle,
        //        allow_isolated ? "allow_isolated" : "!allow_isolated", uid);
    
        if (!handle || (len == 0) || (len > 127))
            return -1;
    
        //检查是否有权限
        if (!svc_can_register(s, len, spid, uid)) {
            ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED
    ",
                 str8(s, len), handle, uid);
            return -1;
        }
    
        si = find_svc(s, len);
        if (si) {
            if (si->handle) {
                ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE
    ",
                     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
    ",
                     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] = '';
            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;
    }
    View Code

    二. ServiceManager如何管理服务

     从上面源码分析我们知道了ServiceManager利用binder通信机制来管理一系列服务。
     上面源码的执行路径可以用下图所示:(注意,图中do_find_service7 应该是do_find_service.操作手误。)

                                            

      代码分析抽象成逻辑分析,如下图所示:

            

  • 相关阅读:
    HTML 标签
    HTML与CSS的关系
    用node搭建本地服务环境
    Windows平台下SVN安装配置及使用
    CSS Flex布局整理
    zepto 选中select option 的值
    Zepto tap 穿透bug、解决移动端点击穿透问题
    jquery 上下滚动显示隐藏
    es6学习笔记二:生成器 Generators
    es6学习笔记一:迭代器和for-of循环
  • 原文地址:https://www.cnblogs.com/bugzone/p/ServiceManager.html
Copyright © 2011-2022 走看看