Android开发:IBinder对象在进程间传递的形式(2)

 

status_t flatten_binder(const sp<ProcessState>& proc,       const sp<IBinder>& binder, Parcel* out)   {       flat_binder_object obj;              obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;       if (binder != NULL) {           IBinder *local = binder->localBinder();           if (!local) {               BpBinder *proxy = binder->remoteBinder();               if (proxy == NULL) {                   LOGE("null proxy");               }               const int32_t handle = proxy ? proxy->handle() : 0;               obj.type = BINDER_TYPE_HANDLE;               obj.handle = handle;               obj.cookie = NULL;           } else {               obj.type = BINDER_TYPE_BINDER;               obj.binder = local->getWeakRefs();               obj.cookie = local;           }       } else {           obj.type = BINDER_TYPE_BINDER;           obj.binder = NULL;           obj.cookie = NULL;       }              return finish_flatten_binder(binder, obj, out);   }  

上面代码分下面2种情况
1. 如果传递的IBinder为service的本地IBinder对象,那么该IBinder对象为BBinder类型的,因此上面的local不为NULL,故binder type为BINDER_TYPE_BINDER。
2. 如果传递的IBinder对象代理IBinder对象,那么binder type则为BINDER_TYPE_HANDLE。

client端将方法调用参数打包成Parcel之后,会发送到内核的Binder模块,因此下面我们将分析一下内核的Binder模块的处理。

kernel/drivers/staging/android/Binder.c中的函数binder_transaction()

 

switch (fp->type) {           case BINDER_TYPE_BINDER:           case BINDER_TYPE_WEAK_BINDER: {               struct binder_ref *ref;               struct binder_node *node = binder_get_node(proc, fp->binder);               if (node == NULL) {                   node = binder_new_node(proc, fp->binder, fp->cookie);                   if (node == NULL) {                       return_error = BR_FAILED_REPLY;                       goto err_binder_new_node_failed;                   }                   node->min_priority = fp->flags & FLAT_BINDER_FLAG_PRIORITY_MASK;                   node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);               }               if (fp->cookie != node->cookie) {                   binder_user_error("binder: %d:%d sending u%p "                       "node %d, cookie mismatch %p != %p\n",                       proc->pid, thread->pid,                       fp->binder, node->debug_id,                       fp->cookie, node->cookie);                   goto err_binder_get_ref_for_node_failed;               }               ref = binder_get_ref_for_node(target_proc, node);               if (ref == NULL) {                   return_error = BR_FAILED_REPLY;                   goto err_binder_get_ref_for_node_failed;               }               if (fp->type == BINDER_TYPE_BINDER)                   fp->type = BINDER_TYPE_HANDLE;               else                   fp->type = BINDER_TYPE_WEAK_HANDLE;               fp->handle = ref->desc;               binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE,                          &thread->todo);                  binder_debug(BINDER_DEBUG_TRANSACTION,                        "        node %d u%p -> ref %d desc %d\n",                        node->debug_id, node->ptr, ref->debug_id,                        ref->desc);           } break;           case BINDER_TYPE_HANDLE:           case BINDER_TYPE_WEAK_HANDLE: {               struct binder_ref *ref = binder_get_ref(proc, fp->handle);               if (ref == NULL) {                   binder_user_error("binder: %d:%d got "                       "transaction with invalid "                       "handle, %ld\n", proc->pid,                       thread->pid, fp->handle);                   return_error = BR_FAILED_REPLY;                   goto err_binder_get_ref_failed;               }               if (ref->node->proc == target_proc) {                   if (fp->type == BINDER_TYPE_HANDLE)                       fp->type = BINDER_TYPE_BINDER;                   else                       fp->type = BINDER_TYPE_WEAK_BINDER;                   fp->binder = ref->node->ptr;                   fp->cookie = ref->node->cookie;                   binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL);                   binder_debug(BINDER_DEBUG_TRANSACTION,                            "        ref %d desc %d -> node %d u%p\n",                            ref->debug_id, ref->desc, ref->node->debug_id,                            ref->node->ptr);               } else {                   struct binder_ref *new_ref;                   new_ref = binder_get_ref_for_node(target_proc, ref->node);                   if (new_ref == NULL) {                       return_error = BR_FAILED_REPLY;                       goto err_binder_get_ref_for_node_failed;                   }                   fp->handle = new_ref->desc;                   binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL);                   binder_debug(BINDER_DEBUG_TRANSACTION,                            "        ref %d desc %d -> ref %d desc %d (node %d)\n",                            ref->debug_id, ref->desc, new_ref->debug_id,                            new_ref->desc, ref->node->debug_id);               }           } break;  

    上面代码也分为了2种不同的分支:
    1. 传来的IBinder类型为BINDER_TYPE_BINDER时,会将binder type值为BINDER_TYPE_HANDLE;
    2. 传来的IBinder类型为BINDER_TYPE_HANDLE时,会判断该IBinder的实体被定义的进程(也就是该IBinder代表的server被定义的进程)与目标进程(也即IBinder被传递的目标进程)是否相同,如果相同,则将该IBinder type转化为BINDER_TYPE_BINDER,同时使其变为IBinder本地对象的引用。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwddpf.html