赞
踩
本文主要从分析 Java层 getService是怎么实现的,getService最终的返回值是什么,以及怎么使用的。
从Am.java的 onRun函数开始:
- @Override
- public void onRun() throws Exception {
- mAm = ActivityManager.getService();
- mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
- ...
- }
这里实际上有两个 getService,一个是ActivityManager.getService,另一个是获取PackageManagerService,比较显然的是直接通过 ServiceManager.getService("package"); 来获取。
先看下 ActivityManager.getService:
- public static IActivityManager getService() {
- return IActivityManagerSingleton.get();
- }
-
- private static final Singleton<IActivityManager> IActivityManagerSingleton =
- new Singleton<IActivityManager>() {
- @Override
- protected IActivityManager create() {
- final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
- final IActivityManager am = IActivityManager.Stub.asInterface(b);
- return am;
- }
- };
-
- public static final String ACTIVITY_SERVICE = "activity";
可以看到,最终也是通过 ServiceManager.getService("activity")获取的,只不过用了单例模式。
所以接下来看 ServiceManager.getService:
- public static IBinder getService(String name) {
- try {
- IBinder service = sCache.get(name);
- if (service != null) {
- return service;
- } else {
- return Binder.allowBlocking(rawGetService(name));
- }
- } catch (RemoteException e) {
- Log.e(TAG, "error in getService", e);
- }
- return null;
- }
如果有cache命中,则从cache中获取,否则从 rawGetService(name)来获取:
- private static IBinder rawGetService(String name) throws RemoteException {
- ..
- final IBinder binder = getIServiceManager().getService(name);
- ...
- return binder;
- }
所以其实现是通过 getIServiceManager().getService(name)获取的,从前面一篇 Binder学习[2]:用户进程与ServiceManger通信:addService实现 的末尾,我们知道:
- getIServiceManager返回的就是 new ServiceManagerProxy(new BinderProxy());
-
- 其中 BinderProxy对象中记录这 nativeData,而 nativeData的成员 mObject对应着 BpBinder(0);
-
- ---------------------
- 作者:大将军王虎剩
- 来源:CSDN
- 原文:https://blog.csdn.net/hl09083253cy/article/details/79234561
- 版权声明:本文为博主原创文章,转载请附上博文链接!
所以最终 ServiceManager.getService 就相当于 new ServiceManagerProxy(new BinderProxy()).getService;
所以我们看 ServiceManagerProxy.getService(name):
- public IBinder getService(String name) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IServiceManager.descriptor);
- data.writeString(name);
- mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
- IBinder binder = reply.readStrongBinder();
- reply.recycle();
- data.recycle();
- return binder;
- }
我们知道Java层的 Parcel是对应着一个Native层的 Parcel的,所以这些数据都会写入 Native层 Parcel 的 mData中,比如 writeInterfaceToken:
- public final void writeInterfaceToken(String interfaceName) {
- nativeWriteInterfaceToken(mNativePtr, interfaceName);
- }
其实现是:
- {"nativeWriteInterfaceToken", "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken},
-
- static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jclass clazz, jlong nativePtr,
- jstring name)
- {
- Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
- if (parcel != NULL) {
- // In the current implementation, the token is just the serialized interface name that
- // the caller expects to be invoking
- const jchar* str = env->GetStringCritical(name, 0);
- if (str != NULL) {
- parcel->writeInterfaceToken(String16(
- reinterpret_cast<const char16_t*>(str),
- env->GetStringLength(name)));
- env->ReleaseStringCritical(name, str);
- }
- }
- }
Native Parcel的 writeInterfaceToken如下:
- status_t Parcel::writeInterfaceToken(const String16& interface)
- {
- writeInt32(IPCThreadState::self()->getStrictModePolicy() |
- STRICT_MODE_PENALTY_GATHER);
- // currently the interface identification token is just its name as a string
- return writeString16(interface);
- }
里面调用的函数,我们在前面一篇已经分析过了,这函数执行完成之后,Native Parcel的 mData指向的buffer如下:
policy | len | "android.os.IServiceManager" |
接下来是 data.writeString(name);,即写入想要获取的 Service的 那么,比如 "package",写完之后数据如下:
policy | len0 | "android.os.IServiceManager" | len0 | "package" |
再接下来就是 :
- mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
- IBinder binder = reply.readStrongBinder();
显示进行通信,获取 reply,然后在从 reply.readStrongBinder获取对应的Service, return回去进行使用;
我们先说 mRemote.transact。看 ServiceManagerProxy的构造,
- public ServiceManagerProxy(IBinder remote) {
- mRemote = remote;
- }
我们知道 mRemote是BinderProxy对象,所以会调用 BinderProxy.transact,第一个参数是: “GET_SERVICE_TRANSACTION”
- public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
- ...
- return transactNative(code, data, reply, flags);
- }
实际的 transact 过程就到 Native层了:
- static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
- jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
- {
- Parcel* data = parcelForJavaObject(env, dataObj); //从java parcel中拿 data
-
- Parcel* reply = parcelForJavaObject(env, replyObj); //从java parcel中拿 reply
-
- IBinder* target = getBPNativeData(env, obj)->mObject.get(); // 从 BinderProxy获取 BpBinder(0)
-
- status_t err = target->transact(code, *data, reply, flags); // 调用 BpBinder.transact函数
-
- if (err == NO_ERROR) {
- return JNI_TRUE;
- } else if (err == UNKNOWN_TRANSACTION) {
- return JNI_FALSE;
- }
- }
接下来的调用关系如下:
- status_t BpBinder::transact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
- {
- ...
- // 这里 mHandle 是 0,对应着对端是 ServiceManager进程
- status_t status = IPCThreadState::self()->transact(
- mHandle, code, data, reply, flags);
- }
-
- status_t IPCThreadState::transact(int32_t handle,
- uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags)
- {
- ...
- // 这里会包装要传输的数据到一个 binder_transaction_data 数据结构中
- // 在 mOut的数据开头会一个 BC_TRANSACTION 命令
- // handle == 0 会写入 binder_transaction_data中
- err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
- ...
- if ((flags & TF_ONE_WAY) == 0) {
- // 可以看到不管是否需要 reply,只要不是 oneway,都需要传递一个 reply参数
- if (reply) {
- err = waitForResponse(reply);
- } else {
- Parcel fakeReply;
- err = waitForResponse(&fakeReply);
- }
- } else {
- err = waitForResponse(NULL, NULL);
- }
-
- return err;
- }
我们也知道是在 waitForResponse中进行与binder driver通信的:
- status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
- {
- ...
- while (1) {
- //
- if ((err=talkWithDriver()) < NO_ERROR) break;
-
- //
- cmd = (uint32_t)mIn.readInt32();
-
- switch (cmd) {
- ...
- case BR_REPLY: // 根据上一篇的分析推理,本次通信返回后,binder driver 写给我们的 cmd 是 BR_REPLY
- {
- binder_transaction_data tr;
- err = mIn.read(&tr, sizeof(tr));
-
- if (err != NO_ERROR) goto finish;
-
- if (reply) {
- if ((tr.flags & TF_STATUS_CODE) == 0) { // binder transaction没有错误
- 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,并 free buffer
- 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 { // 如果是 oneway的通信,这里进行 free buffer,实际上是写入一个 BC_FREE_BUFFER命令和 buffer地址到 mOut中,真正执行应该是随下一次的 binder 通信告知 binder driver,因为这个命令和 buffer在 mOut的前端,所以会先执行这个命令,再执行正常的 binder 命令
- 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); // 如果是其他一些 cmd,则在这执行,BR_SPAWN_LOOPEr就是在这执行的
- if (err != NO_ERROR) goto finish;
- break;
- }
- }
-
- finish:
- if (err != NO_ERROR) {
- if (acquireResult) *acquireResult = err;
- if (reply) reply->setError(err);
- mLastError = err;
- }
-
- return err;
- }
我们先不着急分析 talkWithDriver,在这里回忆一下上一篇中,在binder driver中,binder_thread_read函数返回之前有一段代码:
- if (proc->requested_threads == 0 &&
- list_empty(&thread->proc->waiting_threads) &&
- proc->requested_threads_started < proc->max_threads &&
- (thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
- BINDER_LOOPER_STATE_ENTERED)) /* the user-space code fails to */
- /*spawn a new thread if we leave this out */) {
- proc->requested_threads++;
- binder_inner_proc_unlock(proc);
-
- if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer))
- return -EFAULT;
- binder_stat_br(proc, thread, BR_SPAWN_LOOPER);
- }
这个代码是说如果当前 proc没有空闲的 binder thread,且其数量没有达到 max_threads,则想 buffer中写入 "BR_SPAWN_LOOPER" 命令,在返回用户空间后由用户空间执行。如果不满足条件时,buffer的第一个cmd是 "BR_NOOP",就是什么都不干,实际是个占位cmd,主要就是为了在需要的时候被 BR_SPAWN_LOOPER 覆盖的。
而这个 BR_SPAWN_LOOPER命令就是在 executeCommand中执行的,如下:
- status_t IPCThreadState::executeCommand(int32_t cmd)
- {
- ...
- case BR_SPAWN_LOOPER:
- mProcess->spawnPooledThread(false);
- break;
- return result;
- }
-
- void ProcessState::spawnPooledThread(bool isMain)
- {
- if (mThreadPoolStarted) {
- String8 name = makeBinderThreadName();
- ALOGV("Spawning new pooled thread, name=%s\n", name.string());
- sp<Thread> t = new PoolThread(isMain);
- t->run(name.string());
- }
- }
可以看到,从 ProcessState创建了一个新的 binder线程。
接下来我们继续讨论正题,从 talkWithDriver中把 GET_SERVICE_TRANSACTION 指令发出,并从 reply中获取Service。
- status_t IPCThreadState::talkWithDriver(bool doReceive)
- {
- ...
- bwr.write_buffer = (uintptr_t)mOut.data();
- bwr.read_buffer = (uintptr_t)mIn.data();
-
- if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
- err = NO_ERROR;
- else
- err = -errno;
- ...
- if (err >= NO_ERROR) {
- if (bwr.write_consumed > 0) {
- if (bwr.write_consumed < mOut.dataSize())
- mOut.remove(0, bwr.write_consumed);
- else {
- mOut.setDataSize(0);
- processPostWriteDerefs();
- }
- }
- if (bwr.read_consumed > 0) {
- mIn.setDataSize(bwr.read_consumed); // read_consumed是 read buffer中被写入的数据的size
- mIn.setDataPosition(0);
- }
-
- return NO_ERROR;
- }
-
- return err;
- }
接下来会通过 ioctl(fd, BINDER_WRITE_READ, &bwr) 陷入内核态,执行 binder_ioctl,接下来的调用过程有很多与上一篇基本相同,所以省略一些,总结性的过一下:
1.在 binder_ioctl中,由于 cmd是 BINDER_WRITE_READ,所以会执行 binder_ioctl_write_read,执行完毕后就return,返回用户态了
2.在 binder_ioctl_write_read,由于 write_size和 read_size都大于0,所以会先执行 binder_thread_write,再执行 binder_thread_read 等待回复
3.由于 bwr的 write buffer中命令是 BC_TRANSACTION,所以在binder_thread_write中会执行 binder_transaction函数
4.在 binder_transaction中,会从 binder_transaction_data中读出 handle == 0,确定了 target_proc是 service manager进程,然后会从svcmgr进程对应的binder buffer中 malloc一块合适大小的buffer,并把 transaction数据copy进去,数据中包含cmd: GET_SERVICE_TRANSACTION ,由于本次transaction没有binder object,所以不会再执行 binder_translate_binder;然后会创建一个 binder_transaction和与之关联的一个 binder_work,这个 binder work的 type是 BINDER_WORK_TRANSACTION,接下来通过调用 binder_proc_transaction在 target proc中选中一个合适的线程,把 binder work 插入其 todo队列,并 wakeup它;
5.target proc(即svcmgr进程)的主线程被wakeup后发现有一个 binder work,接下来就会进程处理,处理完成后,会在发送一个 reply 给对端
6.调用 getService的线程从 binder_thread_read 唤醒,读取 reply
我们这里主要看下 第5 和 第6 两点。
第5点:
ServiceManager进程一般是在 binder_thread_read中,可以查看其stack确认:
- ××××:/ # ps -e |grep servicemanager
- system 569 1 10248 1816 binder_thread_read 7c98f30e04 S servicemanager
-
- ××××:/ # cat /proc/569/task/569/stack
- [<0000000000000000>] __switch_to+0x88/0x94
- [<0000000000000000>] binder_thread_read+0x328/0xe60
- [<0000000000000000>] binder_ioctl_write_read+0x18c/0x2d0
- [<0000000000000000>] binder_ioctl+0x1c0/0x5fc
- [<0000000000000000>] do_vfs_ioctl+0x48c/0x564
- [<0000000000000000>] SyS_ioctl+0x60/0x88
- [<0000000000000000>] el0_svc_naked+0x24/0x28
- [<0000000000000000>] 0xffffffffffffffff
当其被wakeup后,会继续执行 binder_thread_read:
- static int binder_thread_read(struct binder_proc *proc,
- struct binder_thread *thread,
- binder_uintptr_t binder_buffer, size_t size,
- binder_size_t *consumed, int non_block)
- {
-
- ret = binder_wait_for_work(thread, wait_for_proc_work);// 一般是在这里等待,被唤醒后从这里接着往下执行
- thread->looper &= ~BINDER_LOOPER_STATE_WAITING;
- while (1) {
- uint32_t cmd;
-
- // 在这里获得非空的 todo list
- if (!binder_worklist_empty_ilocked(&thread->todo))
- list = &thread->todo;
- else if (!binder_worklist_empty_ilocked(&proc->todo) &&
- wait_for_proc_work)
- list = &proc->todo;
-
- w = binder_dequeue_work_head_ilocked(list); // 取出一个 binder work
-
- switch (w->type) {
- case BINDER_WORK_TRANSACTION: { // 前面我们已经知道 work type是这个
- binder_inner_proc_unlock(proc);
- t = container_of(w, struct binder_transaction, work);
- } break;
-
- if (t->buffer->target_node) {
- struct binder_node *target_node = t->buffer->target_node;
- struct binder_priority node_prio;
-
- tr.target.ptr = target_node->ptr;
- tr.cookie = target_node->cookie;
- node_prio.sched_policy = target_node->sched_policy;
- node_prio.prio = target_node->min_priority;
- binder_transaction_priority(current, t, node_prio,
- target_node->inherit_rt);
- cmd = BR_TRANSACTION;
- } else { }
- tr.code = t->code;
- tr.flags = t->flags;
- tr.sender_euid = from_kuid(current_user_ns(), t->sender_euid);
-
- t_from = binder_get_txn_from(t);
- if (t_from) {
- struct task_struct *sender = t_from->proc->tsk;
-
- tr.sender_pid = task_tgid_nr_ns(sender,
- task_active_pid_ns(current));
- } else {
- tr.sender_pid = 0;
- }
-
- tr.data_size = t->buffer->data_size;
- tr.offsets_size = t->buffer->offsets_size;
- tr.data.ptr.buffer = (binder_uintptr_t)
- ((uintptr_t)t->buffer->data +
- binder_alloc_get_user_buffer_offset(&proc->alloc));
- tr.data.ptr.offsets = tr.data.ptr.buffer +
- ALIGN(t->buffer->data_size,
- sizeof(void *));
-
- if (put_user(cmd, (uint32_t __user *)ptr)) {
- if (t_from)
- binder_thread_dec_tmpref(t_from);
-
- binder_cleanup_transaction(t, "put_user failed",
- BR_FAILED_REPLY);
-
- return -EFAULT;
- }
- ptr += sizeof(uint32_t);
- if (copy_to_user(ptr, &tr, sizeof(tr))) {
- if (t_from)
- binder_thread_dec_tmpref(t_from);
-
- binder_cleanup_transaction(t, "copy_to_user failed",
- BR_FAILED_REPLY);
-
- return -EFAULT;
- }
- ptr += sizeof(tr);
- ...
- }
binder_thread_read 获取到一个类型为 BINDER_WORK_TRANSACTION类型的 binder work后,会构造一个 binder_transaction_data,其数据取指向 binder_transaction的数据buffer;然后把一个 "BR_TRANSACTION" cmd和这个 binder_transaction_data数据写会 read buffer中,然后从 binder_thread_read中返回到 binder_ioctl_write_read,再返回到binder_ioctl,在返回到 svcmgr进程的 binder_loop函数:
- void binder_loop(struct binder_state *bs, binder_handler func)
- {
- ...
- for (;;) {
- bwr.read_size = sizeof(readbuf);
- bwr.read_consumed = 0;
- bwr.read_buffer = (uintptr_t) readbuf;
-
- res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
-
- res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
- }
-
- }
接下来通过 binder_parse来解析 read buffer中的数据:
- int binder_parse(struct binder_state *bs, struct binder_io *bio,
- uintptr_t ptr, size_t size, binder_handler func)
- {
- int r = 1;
- uintptr_t end = ptr + (uintptr_t) size;
-
- while (ptr < end) {
- uint32_t cmd = *(uint32_t *) ptr;
- ptr += sizeof(uint32_t);
-
- switch(cmd) {
- case BR_NOOP: // 我们知道,第一个 cmd 是 BR_NOOP,会break并执行第二个 cmd
- break;
- case BR_TRANSACTION: { // read buffer中第二个 cmd是 BR_TRANSACTION
- struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
-
- if (func) {
- unsigned rdata[256/4];
- struct binder_io msg;
- struct binder_io reply;
- int res;
-
- //初始化 reply,以便后续send
- bio_init(&reply, rdata, sizeof(rdata), 4);
-
- // 初始化 msg,数据指向 binder_transaction_data 的数据
- bio_init_from_txn(&msg, txn);
-
- // 调用 svcmgr_hander处理 msg 中的数据,并写好 reply
- res = func(bs, txn, &msg, &reply);
- if (txn->flags & TF_ONE_WAY) {
- binder_free_buffer(bs, txn->data.ptr.buffer);
- } else { // 非 oneway,需要 send reply
- binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
- }
- }
- ptr += sizeof(*txn);
- break;
- }
接下来,要进入 svcmgr_handler 处理 binder_transaction_data 中的数据:
- int svcmgr_handler(struct binder_state *bs,
- struct binder_transaction_data *txn,
- struct binder_io *msg,
- struct binder_io *reply)
- {
- uint32_t handle;
- ...
- strict_policy = bio_get_uint32(msg); // 读取 Policy
- s = bio_get_string16(msg, &len); // 获取名称
-
- //检查是否是 "android.os.IServiceManager"
- if ((len != (sizeof(svcmgr_id) / 2)) ||
- memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
- return -1;
- }
-
- //读取 binder_transaction_data 中记录的命令
- switch(txn->code) {
- case SVC_MGR_GET_SERVICE: // 这里是 get sevice的命令
- case SVC_MGR_CHECK_SERVICE:
- s = bio_get_string16(msg, &len); // 要get的service的名字
- if (s == NULL) {
- return -1;
- }
- // 查找 service,返回对应的 handle
- handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid);
- if (!handle)
- break;
- bio_put_ref(reply, handle); // 查询到的 handle 写入 reply
- return 0;
-
- case SVC_MGR_ADD_SERVICE:
- ...
- }
可以看到查询到 service 后实际是得到一个uint32_t 的 handle,包装到 flat_binder_object,然后写入 reply,最后 send_reply;
写入的操作如下:
- void bio_put_ref(struct binder_io *bio, uint32_t handle)
- {
- struct flat_binder_object *obj;
-
- if (handle)
- obj = bio_alloc_obj(bio);
- else
- obj = bio_alloc(bio, sizeof(*obj));
-
- if (!obj)
- return;
-
- obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
- obj->hdr.type = BINDER_TYPE_HANDLE;
- obj->handle = handle;
- obj->cookie = 0;
- }
需要注意的是,getService是 reply写入的是一个 BINDER_TYPE_HANDLE的 flat_binder_object;
接下来我们看 do_find_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);
- ...
- return si->handle;
- }
-
-
- 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;
- }
就是从 svclist中查找名称为 name的 Service,并返回其 handle,这个 handle 对应这svcmgr的 binder_proc的 refs_by_node和refs_by_desc中的一个ref,这个 ref 指向的 binder node 是其在通过 ServiceManager addService是 创建的binder node。
从上一篇addService的分析,可以知道,ServiceManager add 的每个 Service在 svcmgr 的 binder_proc都对应着一个单独的 handle,在 getService时把这个 handle写入reply,send到发起端进程。
接下来是 binder_send_reply 把 reply 通过 binder_ioctl send 到发起端进程,详细send过程在上一篇分析过,总的来讲就是,还会通过 binder_transaction,找到发起 binder 通信的线程,并在其对应的 binder_proc 分配 binder buffer,把reply copy过去,并创建一个 binder work 插入到发起通信的 binder thread 的 todo list, 并将其 wakeup。 这样 svcmgr 端的工作就完成了。
由于 binder_transaction数据中有个 BINDER_TYPE_HANDLE 类型的 flat_binder_object,在 binder_transaction时,会有下面这样的处理:
- case BINDER_TYPE_HANDLE:
- case BINDER_TYPE_WEAK_HANDLE: {
- struct flat_binder_object *fp;
-
- fp = to_flat_binder_object(hdr);
- ret = binder_translate_handle(fp, t, thread);
- if (ret < 0) {
- return_error = BR_FAILED_REPLY;
- return_error_param = ret;
- return_error_line = __LINE__;
- goto err_translate_failed;
- }
- } break;
这其中关键的点又是 binder_translate_handle:
- static int binder_translate_handle(struct flat_binder_object *fp,
- struct binder_transaction *t,
- struct binder_thread *thread)
- {
-
- struct binder_proc *proc = thread->proc; // svcmgr 的 binder_proc
- struct binder_proc *target_proc = t->to_proc;
- struct binder_node *node;
- struct binder_ref_data src_rdata;
- int ret = 0;
-
- // 在svcmgr的binder_proc中找到 handle对应的 binder ref,再找到 ref指向的 binder node
- node = binder_get_node_from_ref(proc, fp->handle,
- fp->hdr.type == BINDER_TYPE_HANDLE, &src_rdata);
-
- // 如果 binder node就在发起 getService的进程中,则转换成binder实体,
- // 因为 node->cookie实际就是 Service的地址,在同一进程中可直接访问
- // 如果不在同一进程,则不可能直接访问 node->cookie指向的 Service地址
- if (node->proc == target_proc) {
- if (fp->hdr.type == BINDER_TYPE_HANDLE)
- fp->hdr.type = BINDER_TYPE_BINDER;
- else
- fp->hdr.type = BINDER_TYPE_WEAK_BINDER;
- fp->binder = node->ptr; // 指向Service->mRefs
- fp->cookie = node->cookie; //指向 Service对象本身
- if (node->proc)
- binder_inner_proc_lock(node->proc);
- // node->local_strong_refs++
- binder_inc_node_nilocked(node,
- fp->hdr.type == BINDER_TYPE_BINDER,
- 0, NULL);
- if (node->proc)
- binder_inner_proc_unlock(node->proc);
- binder_node_unlock(node);
- } else { // getService的进程与Service不在同一进程,只能返回引用
- struct binder_ref_data dest_rdata;
-
- binder_node_unlock(node);
- // 根据 Service对应的 binder node 在 target_proc 查找 binder_ref
- // 如果找不到,则创建一个 binder_ref,指向 Service的node,handle是 target proc的
- // 如果 ref->data.strong == 0,node->local_strong_refs++
- // ref->data.strong++
- ret = binder_inc_ref_for_node(target_proc, node,
- fp->hdr.type == BINDER_TYPE_HANDLE,
- NULL, &dest_rdata);
- if (ret)
- goto done;
-
- fp->binder = 0;
- fp->handle = dest_rdata.desc; // handle 已经是发起 getService的进程的了
- fp->cookie = 0;
- }
- done:
- binder_put_node(node);
- return ret;
- }
意思就是根据要 get的 Service的实体和发起 getService的进程是否是同一个进程来区分对待。
我们需要记录一下 send_reply时的关键数据:
- 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));
- }
-
- int binder_write(struct binder_state *bs, void *data, size_t len)
- {
- struct binder_write_read bwr;
- int res;
-
- bwr.write_size = len;
- bwr.write_consumed = 0;
- bwr.write_buffer = (uintptr_t) data;
- bwr.read_size = 0;
- bwr.read_consumed = 0;
- bwr.read_buffer = 0;
- res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
- if (res < 0) {
- fprintf(stderr,"binder_write: ioctl failed (%s)\n",
- strerror(errno));
- }
- return res;
- }
总共两个 CMD,一个 BC_FREE_BUFFER,一个 BC_REPLY,还一点 data.txn.code = 0;,在binder_transaction函数中会将这个 code 赋值给 binder_transaction->code;
接下来就回到发起getService的进程一端了,前面我们提到其在 binder_ioctl_write_read中,由于 bwr.read_size > 0,从而在binder_thread_read中等待。binder_thread_read我们已经分析过多次,只不过此次reply中有我们要的关键数据。
在binder_thread_read中,会将 read buffer写入如下数据:
BR_NOOP | BR_REPLY | binder_transaction_data tr; |
其中 tr.data.ptr.buffer = (binder_uintptr_t)
((uintptr_t)t->buffer->data +
binder_alloc_get_user_buffer_offset(&proc->alloc));
指向的binder buffer中记录着的数据(数据中只有一个 flat_binder_object);
接下来就依次返回到 binder_ioctl_write_read,再返回到 binder_ioctl,再返回到用户空间 IPCThreadState::talkWithDriver,接着放回到 IPCThreadState::waitForResponse,进行读取 reply:
- status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
- {
- ...
- while (1) {
- //
- if ((err=talkWithDriver()) < NO_ERROR) break;
-
- //
- cmd = (uint32_t)mIn.readInt32();
-
- switch (cmd) {
- ...
- case BR_REPLY: // 根据上一篇的分析推理,本次通信返回后,binder driver 写给我们的 cmd 是 BR_REPLY
- {
- binder_transaction_data tr;
- // 从 mIn中读取 binder_transaction_data
- err = mIn.read(&tr, sizeof(tr));
-
- if (reply) {
- if ((tr.flags & TF_STATUS_CODE) == 0) { // binder transaction没有错误
- 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,并 free buffer
- 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 { // 如果是 oneway的通信,这里进行 free buffer,实际上是写入一个 BC_FREE_BUFFER命令和 buffer地址到 mOut中,真正执行应该是随下一次的 binder 通信告知 binder driver,因为这个命令和 buffer在 mOut的前端,所以会先执行这个命令,再执行正常的 binder 命令
- 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); // 如果是其他一些 cmd,则在这执行,BR_SPAWN_LOOPEr就是在这执行的
- if (err != NO_ERROR) goto finish;
- break;
- }
- }
-
- finish:
- if (err != NO_ERROR) {
- if (acquireResult) *acquireResult = err;
- if (reply) reply->setError(err);
- mLastError = err;
- }
-
- return err;
- }
我们知道 reply中是一个 flat_binder_obj,就存放在 tr.data.ptr.buffer中,我们主要关注 reply->ipcSetDataReference如何从buffer中读取 reply的:
- void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize,
- const binder_size_t* objects, size_t objectsCount, release_func relFunc, void* relCookie)
- {
- binder_size_t minOffset = 0;
- freeDataNoInit();
- mError = NO_ERROR;
- mData = const_cast<uint8_t*>(data);
- mDataSize = mDataCapacity = dataSize;
- mDataPos = 0;
- mObjects = const_cast<binder_size_t*>(objects);
- mObjectsSize = mObjectsCapacity = objectsCount;
- mNextObjectHint = 0;
- mObjectsSorted = false;
- mOwner = relFunc;
- mOwnerCookie = relCookie;
-
- scanForFds();
- }
函数设定了 reply的数据buffer,数据大小,和objects,以及最后通过 scanForFds 判断传递的objects中是否存在 FD类型的 object:
- void Parcel::scanForFds() const
- {
- bool hasFds = false;
- for (size_t i=0; i<mObjectsSize; i++) {
- const flat_binder_object* flat
- = reinterpret_cast<const flat_binder_object*>(mData + mObjects[i]);
- if (flat->hdr.type == BINDER_TYPE_FD) {
- hasFds = true;
- break;
- }
- }
- mHasFds = hasFds;
- mFdsKnown = true;
- }
OK,到这里,reply数据已经完全准备好了。可以从 IPCThreadState::waitForResponse 函数返回了,接下来会返回到 IPCThreadState::transact 函数,再返回到 BpBinder::transact函数,再返回到 android_os_BinderProxy_transact 函数,再返回到 BinderProxy.transactNative,再返回到 BinderProxy.transact,接下来返回到最开始 Java 层的 ServiceManagerProxy.getService(name):
- public IBinder getService(String name) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IServiceManager.descriptor);
- data.writeString(name);
- mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
-
- // transact 完毕,reply也准备好了,接下来读取
- IBinder binder = reply.readStrongBinder();
- reply.recycle();
- data.recycle();
- return binder;
- }
因为 reply中的数据已经读取好了,接下来我们看看如何读取Service对应的 IBinder的:
- public final IBinder readStrongBinder() {
- return nativeReadStrongBinder(mNativePtr);
- }
-
- {"nativeReadStrongBinder", "(J)Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder},
-
- static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
- {
- Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
- if (parcel != NULL) {
- return javaObjectForIBinder(env, parcel->readStrongBinder());
- }
- return NULL;
- }
可以看到,会返回一个 javaObjectForIBinder,我们先看参数 parcel->readStrongBinder():
- sp<IBinder> Parcel::readStrongBinder() const
- {
- sp<IBinder> val;
-
- readNullableStrongBinder(&val);
- return val;
- }
-
- status_t Parcel::readNullableStrongBinder(sp<IBinder>* val) const
- {
- return unflatten_binder(ProcessState::self(), *this, val);
- }
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->hdr.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;
- }
从上面 binder_translate_handle函数中,我们知道:
1.如果 getService发起者与 Service在同一进程,则 flat->hdr.type是 BINDER_TYPE_BINDER,会通过 *out = reinterpret_cast<IBinder*>(flat->cookie); 将其直接转换为 IBinder,其实就是 Service本身(因为此时 flat->cookie被指向了Service自己)
2.否则,flat->hdr.type 就是 BINDER_TYPE_HANDLE,就会通过 *out = proc->getStrongProxyForHandle(flat->handle); 创建一个 BpBinder(flat->handle),将其转换为 IBinder
所以 android_os_Parcel_readStrongBinder的返回值就有两种情况:
1.javaObjectForIBinder(env, Service);
2.javaObjectForIBinder(env, BpBinder(flat->handle));
这里需要说明下 Service:如果是Native层通过 defaultServiceManager->addService("drm", new DrmManagerService()) 类似这种形式添加的Service,那么这个 Service是 BBinder,但不是 JavaBBinder;
而如果是Java层通过ServicManager.addService(name, Service)添加的 Service,则Service是BBinder的同时也是 JavaBBinder;
所以我们看下 javaObjectForIBinder:
- jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
- {
- if (val == NULL) return NULL;
-
- if (val->checkSubclass(&gBinderOffsets)) { //如果 val 是 JavaBBinder 对象
- // It's a JavaBBinder created by ibinderForJavaObject. Already has Java object.
- // JavaBBinder中保存着 Java层 Service对象
- jobject object = static_cast<JavaBBinder*>(val.get())->object();
- return object; // 直接返回java Service对象
- }
-
- BinderProxyNativeData* nativeData = gNativeDataCache;
- if (nativeData == nullptr) {
- nativeData = new BinderProxyNativeData();
- }
- // gNativeDataCache is now logically empty.
- jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
- gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get());
-
- BinderProxyNativeData* actualNativeData = getBPNativeData(env, object);
- if (actualNativeData == nativeData) {
- // New BinderProxy; we still have exclusive access.
- nativeData->mOrgue = new DeathRecipientList;
- nativeData->mObject = val;
- gNativeDataCache = nullptr;
- ++gNumProxies;
- if (gNumProxies >= gProxiesWarned + PROXY_WARN_INTERVAL) {
- ALOGW("Unexpectedly many live BinderProxies: %d\n", gNumProxies);
- gProxiesWarned = gNumProxies;
- }
- } else {
- // nativeData wasn't used. Reuse it the next time.
- gNativeDataCache = nativeData;
- }
-
- return object;
- }
所以,对于从 java层add的Service:
1.getService发起者和Service在同一个进程时,getService返回的就是 Java层的 Service对象本身
2.如果不在同一个进程中,则getService返回的是一个 java BinderProxy对象,BinderProxy对象记录着一个 BinderProxyNativeData,这个BinderProxyNativeData中会记录着 Service的引用对应的BpBinder(handle);
getService获得的Service在使用之前,还需要调用 XXXInterface.Stub.asInterface(Service)进程转换:
- public static android.content.pm.IPackageManager asInterface(android.os.IBinder obj)
- {
- if ((obj==null)) {
- return null;
- }
- android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
- if (((iin!=null)&&(iin instanceof android.content.pm.IPackageManager))) {
- return ((android.content.pm.IPackageManager)iin);
- }
- return new android.content.pm.IPackageManager.Stub.Proxy(obj);
- }
比如,如果Service是Service对象本身,那么queryLocalInterface的时候就能够找到,asInterface 返回这个 Service自己进行使用,调用函数的时候,就不再需要binder Driver了,可以直接调用;
而如果Service是一个Java层BinderProxy对象,那么将会返回一个 XXXInterface.Stub.Proxy(BinderProxy),调用函数的时候,就需要通过 binder Driver了,比如:
- private static class Proxy implements android.content.pm.IPackageManager
- {
- private android.os.IBinder mRemote;
- Proxy(android.os.IBinder remote)
- {
- mRemote = remote;
- }
- @Override public void checkPackageStartable(java.lang.String packageName, int userId) throws android.os.RemoteException
- {
- android.os.Parcel _data = android.os.Parcel.obtain();
- android.os.Parcel _reply = android.os.Parcel.obtain();
- try {
- _data.writeInterfaceToken(DESCRIPTOR);
- _data.writeString(packageName);
- _data.writeInt(userId);
- mRemote.transact(Stub.TRANSACTION_checkPackageStartable, _data, _reply, 0);
- _reply.readException();
- }
- finally {
- _reply.recycle();
- _data.recycle();
- }
- }
可以看到,如果通过 XXXInterface.Stub.Proxy(BinderProxy)调用 checkPackageStartable这个函数,实际是调用了 BinderProxy的transact函数,然后读取 reply,从而获得结果的。
TODO:需要分析
如果是Native层通过 defaultServiceManager->addService("drm", new DrmManagerService()) 类似这种形式添加的Service,那么这个 Service是 BBinder,但不是 JavaBBinder;
那么 Native层的 defaultServiceManager()->getService返回的是个什么对象 ?
从上一篇可以知道:
gDefaultServiceManager = new BpServiceManager(new BpBinder(0));
所以defaultServiceManager()->getService对应的实现是 BpServiceManager::getService :
- virtual sp<IBinder> getService(const String16& name) const
- {
- sp<IBinder> svc = checkService(name);
- if (svc != NULL) return svc;
- }
- 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::readdStrongBinder实现,
对于 Native层的 getService:
1.如果发起者与Service服务在同一个进程,那么返回的是 Service本身,它是一个 BBinder的实例;
2.如果不在同一个进程,那么返回的是 getStrongProxyForHandler(handle),实际就是一个 BpBInder(handle)
在使用之前,与Java类似,需要先经过一个 interface_cast<INTERFACE>(service):
-
- template<typename INTERFACE>
- inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
- {
- return INTERFACE::asInterface(obj);
- }
实际也是有一个 asInterface:
-
- #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
- const ::android::String16 I##INTERFACE::descriptor(NAME); \
- const ::android::String16& \
- I##INTERFACE::getInterfaceDescriptor() const { \
- return I##INTERFACE::descriptor; \
- } \
- ::android::sp<I##INTERFACE> I##INTERFACE::asInterface( \
- const ::android::sp<::android::IBinder>& obj) \
- { \
- ::android::sp<I##INTERFACE> intr; \
- if (obj != NULL) { \
- //如果在同一个进程,能够 query到,会返回Service对象本身地址
- intr = static_cast<I##INTERFACE*>( \
- obj->queryLocalInterface( \
- I##INTERFACE::descriptor).get()); \
- if (intr == NULL) { \
- // 如果不在同一个进程,query到 NULL,obj是BpBinder,
- // 会返回一个Bp##Interface(BpBinder(handle))
- intr = new Bp##INTERFACE(obj); \
- } \
- } \
- return intr; \
- } \
- I##INTERFACE::I##INTERFACE() { } \
- I##INTERFACE::~I##INTERFACE() { } \
与 Java层类似的,如果Service是Service对象本身,那么queryLocalInterface的时候就能够找到,asInterface 返回这个 Service自己进行使用,调用函数的时候,就不再需要binder Driver了,可以直接调用;
而如果Service是一个Native层BpBinder对象,那么将会返回一个 Bp##Interface.(BpBinder(handle)),调用函数的时候,就需要通过 binder Driver了,会通过 BpBinder的 transact调用。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。