分析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;}
- 分析BatteryService服务的获取过程
- BatteryService服务分析
- 电池及充电相干的服务BatteryService的实现
- BatteryService分析
- BatteryService分析
- Android 6.0 BatteryService分析
- BatteryService分析与实例 [轉載]
- BatteryService分析与实例 [轉載]
- android5.1BatteryService深入分析
- Android SurfaceFlinger服务代理对象获取过程源码分析
- android 4.4 batteryservice 电池电量显示分析
- android 4.4 batteryservice 电池电量显示分析
- Android 获取系统服务的源代码分析
- 服务发现过程分析
- Android 获取资源的过程分析
- Binder驱动服务获取过程
- Android应用程序绑定服务(bindService)的过程源代码分析
- Android应用程序与SurfaceFlinger服务的连接过程分析
- CSS3 transform:rotate(deg) 2D旋转效果
- chrome 插件
- Java容器浅谈
- 使用ViewPager来加载图片和轮播视频
- [数据库] Navicat for MySQL换种思维解决插入同时更新数据
- 分析BatteryService服务的获取过程
- 将算术表达式由中序表达式转为后序表达式
- Java IO流
- Java的错误类型
- 配置Spark standalone集群启动
- 一段解析字符串中单词的C语言小程序
- 可变参数之auto-boxing
- C#.NET系列(一):入门,关于C#.NET以及类与命名空间的简介
- 内核对新板子的支持