分析BatteryService服务的获取过程

来源:互联网 发布:avmoo最新域名2016 3 编辑:程序博客网 时间:2024/06/03 22:39

让我们从BatteryService入手查看这个Service的查询过程,因为Android系统的系统服务都是在加载的时候创建并且添加的,所以此时要想使用服务就得从service_manager中获取,所以我们今天就看看如何获取这些服务。

BatteryService.cpp

BatteryService::BatteryService() {    const sp<IServiceManager> sm(defaultServiceManager());    if (sm != NULL) {        const String16 name("batterystats");        mBatteryStatService = interface_cast<IBatteryStats>(sm->getService(name));//[1]    }}

我们上一节已经知道了defaultServiceManager这个返回的是BpServiceManager对象那么调用getService之后我们看下是什么东东

BpServiceManager.getService()

    inline 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;        };    inline 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();        };

在其中我们知道remote是BpBinder对象,然后调用BpBinder的transact方法

BpBinder::transact()

status_t BpBinder::transact(uint32_t code,             const Parcel& data, Parcel* reply, uint32_t flags){    if (mAlive) {        status_t status = IPCThreadState::self()->transact(            mHandle, code, data, reply, flags);        if (status == DEAD_OBJECT) mAlive = 0;        return status;    }    return DEAD_OBJECT;}

继续调用IPCThreadState对象的transact方法

IPCThreadState::transact()

status_t IPCThreadState::transact(int32_t handle,                                  uint32_t code, const Parcel& data,                                  Parcel* reply, uint32_t flags){    status_t err = data.errorCheck();    flags |= TF_ACCEPT_FDS;    ...    if (err == NO_ERROR) {        //传输数据        err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);    }    if (err != NO_ERROR) {        if (reply) reply->setError(err);        return (mLastError = err);    }    if ((flags & TF_ONE_WAY) == 0) {        if (reply) {             //等待响应            err = waitForResponse(reply);        } else {            Parcel fakeReply;            err = waitForResponse(&fakeReply);        }    } else {      //不需要响应消息的binder则进入该分支        err = waitForResponse(NULL, NULL);    }    return err;}

在这里我们需要理一理传进来的参数,我们上节说过此时的mHandle为0
code=CHECK_SERVICE_TRANSACTION然后调用writeTransactionData()方法写入数据

IPCThreadState::writeTransactionData()

status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,    int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer){    binder_transaction_data tr;    tr.target.ptr = 0;     tr.target.handle = handle;    tr.code = code;    tr.flags = binderFlags;    tr.cookie = 0;    tr.sender_pid = 0;    tr.sender_euid = 0;    const status_t err = data.errorCheck();    if (err == NO_ERROR) {        tr.data_size = data.ipcDataSize();        tr.data.ptr.buffer = data.ipcData();        tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t);        tr.data.ptr.offsets = data.ipcObjects();    } else if (statusBuffer) {        tr.flags |= TF_STATUS_CODE;        *statusBuffer = err;        tr.data_size = sizeof(status_t);        tr.data.ptr.buffer = reinterpret_cast<uintptr_t>(statusBuffer);        tr.offsets_size = 0;        tr.data.ptr.offsets = 0;    } else {        return (mLastError = err);    }    mOut.writeInt32(cmd);    mOut.write(&tr, sizeof(tr));    return NO_ERROR;}

上面将数据封装成了binder_transaction_data然后写入到了 Parcel mOut;中

IPCThreadState::waitForResponse()

status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult){    uint32_t cmd;    int32_t err;    while (1) {        if ((err=talkWithDriver()) < NO_ERROR) break;        cmd = (uint32_t)mIn.readInt32();        switch (cmd) {        case BR_TRANSACTION_COMPLETE:            if (!reply && !acquireResult) goto finish;            break;        case BR_DEAD_REPLY:            err = DEAD_OBJECT;            goto finish;        case BR_FAILED_REPLY:            err = FAILED_TRANSACTION;            goto finish;        case BR_ACQUIRE_RESULT:            {                ALOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT");                const int32_t result = mIn.readInt32();                if (!acquireResult) continue;                *acquireResult = result ? NO_ERROR : INVALID_OPERATION;            }            goto finish;        case BR_REPLY:            {                binder_transaction_data tr;                err = mIn.read(&tr, sizeof(tr));                ALOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY");                if (reply) {                    if ((tr.flags & TF_STATUS_CODE) == 0) {                        reply->ipcSetDataReference(                            reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),                            tr.data_size,                            reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),                            tr.offsets_size/sizeof(binder_size_t),                            freeBuffer, this);                    } else {                        err = *reinterpret_cast<const status_t*>(tr.data.ptr.buffer);                        freeBuffer(NULL,                            reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),                            tr.data_size,                            reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),                            tr.offsets_size/sizeof(binder_size_t), this);                    }                } else {                    freeBuffer(NULL,                        reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),                        tr.data_size,                        reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),                        tr.offsets_size/sizeof(binder_size_t), this);                    continue;                }            }            goto finish;        default:            err = executeCommand(cmd);            if (err != NO_ERROR) goto finish;            break;        }    }    return err;}

在这里有一个循环在talkWithDriver()方法中不断的调用ioctl,传递的数据是mOut的数据,这个数据发到什么地方呢?
其中BpBinder(0),使得handle为0,然后通过ioctl传递的应该是给service_manager.c的main方法启动的loop,然后通过一个回调函数查找对应的服务。

所以此时进入service_manager.c中binder_loop(bs, svcmgr_handler);

然后回调到:

svcmgr_handler()

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;    if (txn->target.ptr != BINDER_SERVICE_MANAGER)        return -1;    if (txn->code == PING_TRANSACTION)        return 0;    strict_policy = bio_get_uint32(msg);    s = bio_get_string16(msg, &len);    if (s == NULL) {        return -1;    }    if ((len != (sizeof(svcmgr_id) / 2)) ||        memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {        fprintf(stderr,"invalid id %s\n", 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:    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;    bio_put_uint32(reply, 0);    return 0;}

然后调用do_find_service方法,这个方法内部进行查找对应到Binder服务

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) {        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;}

在svclist列表找出svcinfo

find_svc()

struct svcinfo *find_svc(const uint16_t *s16, size_t len){    struct svcinfo *si;    for (si = svclist; si; si = si->next) {        if ((len == si->len) &&            !memcmp(s16, si->name, len * sizeof(uint16_t))) {            return si;        }    }    return NULL;}
0 0
原创粉丝点击