Android IPC 机制详解:IBinder

转载 2012年03月26日 09:10:51

http://www.linuxgraphics.cn/android/ipc_ibinder.html

 

 

IBinder 接口

IBinder接口是对跨进程的对象的抽象。普通对象在当前进程可以访问,如果希望对象能被其它进程访问,那就必须实现IBinder接口。IBinder接口可以指向本地对象,也可以指向远程对象,调用者不需要关心指向的对象是本地的还是远程。

transact是IBinder接口中一个比较重要的函数,它的函数原型如下:

  1. virtual status_t transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) = 0;  
 

 

android中的IPC的基本模型是基于客户/服务器(C/S)架构的。

客户端 请求通过内核模块中转 服务端

如果IBinder指向的是一个客户端代理,那transact只是把请求发送给服务器。服务端的IBinder的transact则提供了实际的服务。

客户端

BpBinder是远程对象在当前进程的代理,它实现了IBinder接口。它的transact 函数实现如下:

  1. status_t BpBinder::transact(  
  2.     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)  
  3. {  
  4.     // Once a binder has died, it will never come back to life.  
  5.     if (mAlive) {  
  6.         status_t status = IPCThreadState::self()->transact(  
  7.             mHandle, code, data, reply, flags);  
  8.         if (status == DEAD_OBJECT) mAlive = 0;  
  9.         return status;  
  10.     }  
  11.     return DEAD_OBJECT;  
  12. }  
 

 

参数说明:

  • code 是请求的ID号;
  • data 是请求的参数;
  • reply 是返回的结果;
  • flags 一些额外的标识,如FLAG_ONEWAY。通常为0。

transact只是简单的调用了IPCThreadState::self()的transact,在 IPCThreadState::transact中:

  1. status_t IPCThreadState::transact(int32_t handle,  
  2.                                   uint32_t code, const Parcel& data,  
  3.                                   Parcel* reply, uint32_t flags)  
  4. {  
  5.     status_t err = data.errorCheck();  
  6.     flags |= TF_ACCEPT_FDS;  
  7.     IF_LOG_TRANSACTIONS() {  
  8.         TextOutput::Bundle _b(alog);  
  9.         alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand "  
  10.             << handle << " / code " << TypeCode(code) << ": "  
  11.             << indent << data << dedent << endl;  
  12.     }  
  13.     if (err == NO_ERROR) {  
  14.         LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),  
  15.             (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");  
  16.         err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);  
  17.     }  
  18.     if (err != NO_ERROR) {  
  19.         if (reply) reply->setError(err);  
  20.         return (mLastError = err);  
  21.     }  
  22.     if ((flags & TF_ONE_WAY) == 0) {  
  23.         if (reply) {  
  24.             err = waitForResponse(reply);  
  25.         } else {  
  26.             Parcel fakeReply;  
  27.             err = waitForResponse(&fakeReply);  
  28.         }  
  29.         IF_LOG_TRANSACTIONS() {  
  30.             TextOutput::Bundle _b(alog);  
  31.             alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand "  
  32.                 << handle << ": ";  
  33.             if (reply) alog << indent << *reply << dedent << endl;  
  34.             else alog << "(none requested)" << endl;  
  35.         }  
  36.     } else {  
  37.         err = waitForResponse(NULL, NULL);  
  38.     }  
  39.     return err;  
  40. }  
  41. status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)  
  42. {  
  43.     int32_t cmd;  
  44.     int32_t err;  
  45.     while (1) {  
  46.         if ((err=talkWithDriver()) < NO_ERROR) break;  
  47.         err = mIn.errorCheck();  
  48.         if (err < NO_ERROR) break;  
  49.         if (mIn.dataAvail() == 0) continue;  
  50.         cmd = mIn.readInt32();  
  51.         IF_LOG_COMMANDS() {  
  52.             alog << "Processing waitForResponse Command: "  
  53.                 << getReturnString(cmd) << endl;  
  54.         }  
  55.         switch (cmd) {  
  56.         case BR_TRANSACTION_COMPLETE:  
  57.             if (!reply && !acquireResult) goto finish;  
  58.             break;  
  59.         case BR_DEAD_REPLY:  
  60.             err = DEAD_OBJECT;  
  61.             goto finish;  
  62.         case BR_FAILED_REPLY:  
  63.             err = FAILED_TRANSACTION;  
  64.             goto finish;  
  65.         case BR_ACQUIRE_RESULT:  
  66.             {  
  67.                 LOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT");  
  68.                 const int32_t result = mIn.readInt32();  
  69.                 if (!acquireResult) continue;  
  70.                 *acquireResult = result ? NO_ERROR : INVALID_OPERATION;  
  71.             }  
  72.             goto finish;  
  73.         case BR_REPLY:  
  74.             {  
  75.                 binder_transaction_data tr;  
  76.                 err = mIn.read(&tr, sizeof(tr));  
  77.                 LOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY");  
  78.                 if (err != NO_ERROR) goto finish;  
  79.                 if (reply) {  
  80.                     if ((tr.flags & TF_STATUS_CODE) == 0) {  
  81.                         reply->ipcSetDataReference(  
  82.                             reinterpret_cast(tr.data.ptr.buffer),  
  83.                             tr.data_size,  
  84.                             reinterpret_cast(tr.data.ptr.offsets),  
  85.                             tr.offsets_size/sizeof(size_t),  
  86.                             freeBuffer, this);  
  87.                     } else {  
  88.                         err = *static_cast(tr.data.ptr.buffer);  
  89.                         freeBuffer(NULL,  
  90.                             reinterpret_cast(tr.data.ptr.buffer),  
  91.                             tr.data_size,  
  92.                             reinterpret_cast(tr.data.ptr.offsets),  
  93.                             tr.offsets_size/sizeof(size_t), this);  
  94.                     }  
  95.                 } else {  
  96.                     freeBuffer(NULL,  
  97.                         reinterpret_cast(tr.data.ptr.buffer),  
  98.                         tr.data_size,  
  99.                         reinterpret_cast(tr.data.ptr.offsets),  
  100.                         tr.offsets_size/sizeof(size_t), this);  
  101.                     continue;  
  102.                 }  
  103.             }  
  104.             goto finish;  
  105.         default:  
  106.             err = executeCommand(cmd);  
  107.             if (err != NO_ERROR) goto finish;  
  108.             break;  
  109.         }  
  110.     }  
  111. finish:  
  112.     if (err != NO_ERROR) {  
  113.         if (acquireResult) *acquireResult = err;  
  114.         if (reply) reply->setError(err);  
  115.         mLastError = err;  
  116.     }  
  117.     return err;  
  118. }  
 

 

这里transact把请求经内核模块发送了给服务端,服务端处理完请求之后,沿原路返回结果给调用者。这里也可以看出请求是同步操作,它会等待直到结果返回为止。

在BpBinder之上进行简单包装,我们可以得到与服务对象相同的接口,调用者无需要关心调用的对象是远程的还是本地的。拿ServiceManager来说: (frameworks/base/libs/utils/IServiceManager.cpp)

  1. class BpServiceManager : public BpInterface  
  2. {  
  3. public:  
  4.     BpServiceManager(const sp& impl)  
  5.         : BpInterface(impl)  
  6.     {  
  7.     }  
  8. ...  
  9.     virtual status_t addService(const String16& name, const sp& service)  
  10.     {  
  11.         Parcel data, reply;  
  12.         data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());  
  13.         data.writeString16(name);  
  14.         data.writeStrongBinder(service);  
  15.         status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);  
  16.         return err == NO_ERROR ? reply.readInt32() : err;  
  17.     }  
  18. ...  
  19. };  
 

 

BpServiceManager实现了 IServiceManager和IBinder两个接口,调用者可以把BpServiceManager的对象看作是一个 IServiceManager对象或者IBinder对象。当调用者把BpServiceManager对象当作IServiceManager对象使用时,所有的请求只是对BpBinder::transact的封装。这样的封装使得调用者不需要关心IServiceManager对象是本地的还是远程的了。

客户通过defaultServiceManager函数来创建BpServiceManager对象: (frameworks/base/libs/utils/IServiceManager.cpp)

 

  1. sp<IServiceManager> defaultServiceManager()  
  2. {  
  3.     if (gDefaultServiceManager != NULL) return gDefaultServiceManager;  
  4.     {  
  5.         AutoMutex _l(gDefaultServiceManagerLock);  
  6.         if (gDefaultServiceManager == NULL) {  
  7.             gDefaultServiceManager = interface_cast<IServiceManager>(  
  8.                 ProcessState::self()->getContextObject(NULL));  
  9.         }  
  10.     }  
  11.     return gDefaultServiceManager;  
  12. }  
 

 

先通过ProcessState::self()->getContextObject(NULL)创建一个Binder对象,然后通过 interface_cast和IMPLEMENT_META_INTERFACE(ServiceManager, “android.os.IServiceManager”)把Binder对象包装成 IServiceManager对象。原理上等同于创建了一个BpServiceManager对象。

ProcessState::self()->getContextObject调用ProcessState::getStrongProxyForHandle创建代理对象:

  1. sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)  
  2. {  
  3.     sp<IBinder> result;  
  4.     AutoMutex _l(mLock);  
  5.     handle_entry* e = lookupHandleLocked(handle);  
  6.     if (e != NULL) {  
  7.         // We need to create a new BpBinder if there isn't currently one, OR we  
  8.         // are unable to acquire a weak reference on this current one.  See comment  
  9.         // in getWeakProxyForHandle() for more info about this.  
  10.         IBinder* b = e->binder;  
  11.         if (b == NULL || !e->refs->attemptIncWeak(this)) {  
  12.             b = new BpBinder(handle);  
  13.             e->binder = b;  
  14.             if (b) e->refs = b->getWeakRefs();  
  15.             result = b;  
  16.         } else {  
  17.             // This little bit of nastyness is to allow us to add a primary  
  18.             // reference to the remote proxy when this team doesn't have one  
  19.             // but another team is sending the handle to us.  
  20.             result.force_set(b);  
  21.             e->refs->decWeak(this);  
  22.         }  
  23.     }  
  24.     return result;  
  25. }  
 

 

如果handle为空,默认为context_manager对象,context_manager实际上就是 ServiceManager。

服务端

服务端也要实现IBinder接口,BBinder类对IBinder接口提供了部分默认实现,其中transact的实现如下:

  1. status_t BBinder::transact(  
  2.     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)  
  3. {  
  4.     data.setDataPosition(0);  
  5.     status_t err = NO_ERROR;  
  6.     switch (code) {  
  7.         case PING_TRANSACTION:  
  8.             reply->writeInt32(pingBinder());  
  9.             break;  
  10.         default:  
  11.             err = onTransact(code, data, reply, flags);  
  12.             break;  
  13.     }  
  14.     if (reply != NULL) {  
  15.         reply->setDataPosition(0);  
  16.     }  
  17.     return err;  
  18. }  
 

PING_TRANSACTION请求用来检查对象是否还存在,这里简单的把 pingBinder的返回值返回给调用者。其它的请求交给onTransact处理。onTransact是BBinder里声明的一个 protected类型的虚函数,这个要求它的子类去实现。比如CameraService里的实现如下:

  1. status_t CameraService::onTransact(  
  2.     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)  
  3. {  
  4.     // permission checks...  
  5.     switch (code) {  
  6.         case BnCameraService::CONNECT:  
  7.             IPCThreadState* ipc = IPCThreadState::self();  
  8.             const int pid = ipc->getCallingPid();  
  9.             const int self_pid = getpid();  
  10.             if (pid != self_pid) {  
  11.                 // we're called from a different process, do the real check  
  12.                 if (!checkCallingPermission(  
  13.                         String16("android.permission.CAMERA")))  
  14.                 {  
  15.                     const int uid = ipc->getCallingUid();  
  16.                     LOGE("Permission Denial: "  
  17.                             "can't use the camera pid=%d, uid=%d", pid, uid);  
  18.                     return PERMISSION_DENIED;  
  19.                 }  
  20.             }  
  21.             break;  
  22.     }  
  23.     status_t err = BnCameraService::onTransact(code, data, reply, flags);  
  24.     LOGD("+++ onTransact err %d code %d", err, code);  
  25.     if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {  
  26.         // the 'service' command interrogates this binder for its name, and then supplies it  
  27.         // even for the debugging commands.  that means we need to check for it here, using  
  28.         // ISurfaceComposer (since we delegated the INTERFACE_TRANSACTION handling to  
  29.         // BnSurfaceComposer before falling through to this code).  
  30.         LOGD("+++ onTransact code %d", code);  
  31.         CHECK_INTERFACE(ICameraService, data, reply);  
  32.         switch(code) {  
  33.         case 1000:  
  34.         {  
  35.             if (gWeakHeap != 0) {  
  36.                 sp h = gWeakHeap.promote();  
  37.                 IMemoryHeap *p = gWeakHeap.unsafe_get();  
  38.                 LOGD("CHECKING WEAK REFERENCE %p (%p)", h.get(), p);  
  39.                 if (h != 0)  
  40.                     h->printRefs();  
  41.                 bool attempt_to_delete = data.readInt32() == 1;  
  42.                 if (attempt_to_delete) {  
  43.                     // NOT SAFE!  
  44.                     LOGD("DELETING WEAK REFERENCE %p (%p)", h.get(), p);  
  45.                     if (p) delete p;  
  46.                 }  
  47.                 return NO_ERROR;  
  48.             }  
  49.         }  
  50.         break;  
  51.         default:  
  52.             break;  
  53.         }  
  54.     }  
  55.     return err;  
  56. }  
 

 

由此可见,服务端的onTransact是一个请求分发函数,它根据请求码(code)做相应的处理。

消息循环

服务端(任何进程都可以作为服务端)有一个线程监听来自客户端的请求,并循环处理这些请求。

如果在主线程中处理请求,可以直接调用下面的函数:

  1. IPCThreadState::self()->joinThreadPool(mIsMain);  
 

如果想在非主线程中处理请求,可以按下列方式:

  1. sp  
  2. ProcessState::self();  
  3. if (proc->supportsProcesses()) {  
  4.     LOGV("App process: starting thread pool./n");  
  5.     proc->startThreadPool();  
  6. }  
 

startThreadPool的实现原理:

  1. void ProcessState::startThreadPool()  
  2. {  
  3.     AutoMutex _l(mLock);  
  4.     if (!mThreadPoolStarted) {  
  5.         mThreadPoolStarted = true;  
  6.         spawnPooledThread(true);  
  7.     }  
  8. }  
  9. void ProcessState::spawnPooledThread(bool isMain)  
  10. {  
  11.     if (mThreadPoolStarted) {  
  12.         int32_t s = android_atomic_add(1, &mThreadPoolSeq);  
  13.         char buf[32];  
  14.         sprintf(buf, "Binder Thread #%d", s);  
  15.         LOGV("Spawning new pooled thread, name=%s/n", buf);  
  16.         sp  
  17.  t = new PoolThread(isMain);  
  18.         t->run(buf);  
  19.     }  
  20. }  
 

这里创建了PoolThread的对象,实现上就是创建了一个线程。所有的线程类都要实现threadLoop虚函数。PoolThread的threadLoop的实现如下:

  1. virtual bool threadLoop()  
  2. {  
  3.     IPCThreadState::self()->joinThreadPool(mIsMain);  
  4.     return false;  
  5. }  
 

 

上述代码,简而言之就是创建了一个线程,然后在线程里调用 IPCThreadState::self()->joinThreadPool函数。

下面再看joinThreadPool的实现:

  1. do  
  2. {  
  3. ...  
  4.         result = talkWithDriver();  
  5.         if (result >= NO_ERROR) {  
  6.             size_t IN = mIn.dataAvail();  
  7.             if (IN < sizeof(int32_t)) continue;  
  8.             cmd = mIn.readInt32();  
  9.             IF_LOG_COMMANDS() {  
  10.                 alog << "Processing top-level Command: "  
  11.                     << getReturnString(cmd) << endl;  
  12.             }  
  13.             result = executeCommand(cmd);  
  14.         }  
  15. ...  
  16. while(...);  
 

 

这个函数在循环中重复执行下列动作:

  1. talkWithDriver 通过ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)读取请求和写回结果。
  2. executeCommand 执行相应的请求

在IPCThreadState::executeCommand(int32_t cmd)函数中:

  1. 对于控制对象生命周期的请求,像BR_ACQUIRE/BR_RELEASE直接做了处理。
  2. 对于BR_TRANSACTION请求,它调用被请求对象的transact函数。

按下列方式调用实际的对象:

  1. if (tr.target.ptr) {  
  2.     sp<BBinder> b((BBinder*)tr.cookie);  
  3.     const status_t error = b->transact(tr.code, buffer, &reply, 0);  
  4.     if (error < NO_ERROR) reply.setError(error);  
  5. else {  
  6.     const status_t error = the_context_object->transact(tr.code, buffer, &reply, 0);  
  7.     if (error < NO_ERROR) reply.setError(error);  
  8. }  
 

 

如果tr.target.ptr不为空,就把tr.cookie转换成一个Binder对象,并调用它的 transact函数。如果没有目标对象,就调用 the_context_object对象的 transact函数。奇怪的是,根本没有谁对the_context_object进行初始化, the_context_object是空指针。原因是context_mgr的请求发给了 ServiceManager,所以根本不会走到else 语句里来。

内核模块

android使用了一个内核模块binder来中转各个进程之间的消息。模块源代码放在binder.c里,它是一个字符驱动程序,主要通过 binder_ioctl与用户空间的进程交换数据。其中BINDER_WRITE_READ用来读写数据,数据包中有一个cmd域用于区分不同的请求:

  1. binder_thread_write用于发送请求或返回结果。
  2. binder_thread_read用于读取结果。

从binder_thread_write中调用binder_transaction中转请求和返回结果,binder_transaction的实现如下:

对请求的处理:

  1. 通过对象的handle找到对象所在的进程,如果handle为空就认为对象是context_mgr,把请求发给context_mgr所在的进程。
  2. 把请求中所有的binder对象全部放到一个RB树中。
  3. 把请求放到目标进程的队列中,等待目标进程读取。

如何成为context_mgr呢?内核模块提供了BINDER_SET_CONTEXT_MGR调用:

  1. static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  
  2. {  
  3.     ...  
  4.     case BINDER_SET_CONTEXT_MGR:  
  5.         if (binder_context_mgr_node != NULL) {  
  6.             printk(KERN_ERR "binder: BINDER_SET_CONTEXT_MGR already set/n");  
  7.             ret = -EBUSY;  
  8.             goto err;  
  9.         }  
  10.         if (binder_context_mgr_uid != -1) {  
  11.             if (binder_context_mgr_uid != current->euid) {  
  12.                 printk(KERN_ERR "binder: BINDER_SET_"  
  13.                        "CONTEXT_MGR bad uid %d != %d/n",  
  14.                        current->euid,  
  15.                        binder_context_mgr_uid);  
  16.                 ret = -EPERM;  
  17.                 goto err;  
  18.             }  
  19.         } else  
  20.             binder_context_mgr_uid = current->euid;  
  21.         binder_context_mgr_node = binder_new_node(proc, NULL, NULL);  
  22.         if (binder_context_mgr_node == NULL) {  
  23.             ret = -ENOMEM;  
  24.             goto err;  
  25.         }  
  26.         binder_context_mgr_node->local_weak_refs++;  
  27.         binder_context_mgr_node->local_strong_refs++;  
  28.         binder_context_mgr_node->has_strong_ref = 1;  
  29.         binder_context_mgr_node->has_weak_ref = 1;  
  30.         break;  
 

 

ServiceManager(frameworks/base/cmds/servicemanager)通过下列方式成为了 context_mgr进程:

  1. int binder_become_context_manager(struct binder_state *bs)  
  2. {  
  3.     return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);  
  4. }  
  5. int main(int argc, char **argv)  
  6. {  
  7.     struct binder_state *bs;  
  8.     void *svcmgr = BINDER_SERVICE_MANAGER;  
  9.     bs = binder_open(128*1024);  
  10.     if (binder_become_context_manager(bs)) {  
  11.         LOGE("cannot become context manager (%s)/n", strerror(errno));  
  12.         return -1;  
  13.     }  
  14.     svcmgr_handle = svcmgr;  
  15.     binder_loop(bs, svcmgr_handler);  
  16.     return 0;  
  17. }  
 

如何得到服务对象的handle

  1. 服务提供者通过defaultServiceManager得到ServiceManager对象,然后调用addService向服务管理器注册。
  2. 服务使用者通过defaultServiceManager得到ServiceManager对象,然后调用getService通过服务名称查找到服务对象的handle。

如何通过服务对象的handle找到服务所在的进程

表示服务管理器的handle,getService可以查找到系统服务的handle。这个handle只是代表了服务对象,内核模块是如何通过handle找到服务所在的进程的呢?

  1. 对于ServiceManager: ServiceManager调用了binder_become_context_manager使用自己成为context_mgr,所有handle为0的请求都会被转发给ServiceManager。
  2. 对于系统服务和应用程序的Listener,在第一次请求内核模块时(比如调用 addService),内核模块在一个RB树中建立了服务对象和进程的对应关系。
  3. 请求服务时,内核先通过handle找到对应的进程,然后把请求放到服务进程的队列中。 

  1. off_end = (void *)offp + tr->offsets_size;  
  2. for (; offp < off_end; offp++) {  
  3.     struct flat_binder_object *fp;  
  4.     if (*offp > t->buffer->data_size - sizeof(*fp)) {  
  5.         binder_user_error("binder: %d:%d got transaction with "  
  6.             "invalid offset, %d/n",  
  7.             proc->pid, thread->pid, *offp);  
  8.         return_error = BR_FAILED_REPLY;  
  9.         goto err_bad_offset;  
  10.     }  
  11.     fp = (struct flat_binder_object *)(t->buffer->data + *offp);  
  12.     switch (fp->type) {  
  13.     case BINDER_TYPE_BINDER:  
  14.     case BINDER_TYPE_WEAK_BINDER: {  
  15.         struct binder_ref *ref;  
  16.         struct binder_node *node = binder_get_node(proc, fp->binder);  
  17.         if (node == NULL) {  
  18.             node = binder_new_node(proc, fp->binder, fp->cookie);  
  19.             if (node == NULL) {  
  20.                 return_error = BR_FAILED_REPLY;  
  21.                 goto err_binder_new_node_failed;  
  22.             }  
  23.             node->min_priority = fp->flags & FLAT_BINDER_FLAG_PRIORITY_MASK;  
  24.             node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);  
  25.         }  
  26.         if (fp->cookie != node->cookie) {  
  27.             binder_user_error("binder: %d:%d sending u%p "  
  28.                 "node %d, cookie mismatch %p != %p/n",  
  29.                 proc->pid, thread->pid,  
  30.                 fp->binder, node->debug_id,  
  31.                 fp->cookie, node->cookie);  
  32.             goto err_binder_get_ref_for_node_failed;  
  33.         }  
  34.         ref = binder_get_ref_for_node(target_proc, node);  
  35.         if (ref == NULL) {  
  36.             return_error = BR_FAILED_REPLY;  
  37.             goto err_binder_get_ref_for_node_failed;  
  38.         }  
  39.         if (fp->type == BINDER_TYPE_BINDER)  
  40.             fp->type = BINDER_TYPE_HANDLE;  
  41.         else  
  42.             fp->type = BINDER_TYPE_WEAK_HANDLE;  
  43.         fp->handle = ref->desc;  
  44.         binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE, &thread->todo);  
  45.         if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)  
  46.             printk(KERN_INFO "        node %d u%p -> ref %d desc %d/n",  
  47.                    node->debug_id, node->ptr, ref->debug_id, ref->desc);  
  48.     } break;  
 

 

C调用JAVA

前面我们分析的是C代码的处理。对于JAVA代码,JAVA调用C的函数通过JNI调用即可。从内核时读取请求是在C代码(executeCommand)里进行了,那如何在C代码中调用那些用JAVA实现的服务呢?

android_os_Binder_init里的JavaBBinder对Java里的Binder对象进行包装。

JavaBBinder::onTransact调用Java里的execTransact函数:

  1. jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,  
  2.     code, (int32_t)&data, (int32_t)reply, flags);  
  3. jthrowable excep = env->ExceptionOccurred();  
  4. if (excep) {  
  5.     report_exception(env, excep,  
  6.         "*** Uncaught remote exception!  "  
  7.         "(Exceptions are not yet supported across processes.)");  
  8.     res = JNI_FALSE;  
  9.     /* clean up JNI local ref -- we don't return to Java code */  
  10.     env->DeleteLocalRef(excep);  
  11. }  
 

广播消息

binder不提供广播消息,不过可以ActivityManagerService服务来实现广播。 (frameworks/base/core/java/android/app/ActivityManagerNative.java)

接收广播消息需要实现接口BroadcastReceiver,然后调用ActivityManagerProxy::registerReceiver注册。

触发广播调用ActivityManagerProxy::broadcastIntent。(应用程序并不直接调用它,而是调用Context对它的包装)

Reference

文章出处:http://www.limodev.cn/blog

作者联系方式:李先静 <xianjimli at hotmail dot com>

相关文章推荐

Android IPC 机制详解:IBinder

http://www.linuxgraphics.cn/android/ipc_ibinder.html  IBinder 接口IBinder接口是对跨进程的对象的抽象。普通对象在当前进程可以访问,如...

深入理解android之ibinder机制.pdf

  • 2012年10月18日 14:28
  • 2.27MB
  • 下载

Android IPC机制详解

  • 2011年12月31日 00:16
  • 148KB
  • 下载

Android IBinder机制简单介绍

原理简介 我们都知道android 是通过IBinder来实现IPC(Inter Process Communication)进程间通信的。。。 参考:Android进程间通信(IPC)机制Bind...

Android中RemoteService的使用详解(Aidl、IPC机制)

前面说好更完LocalService就更RemoteService的哈~今天就来说说强大的RemoteService啦~~~      Remoteservice的运作要用到Aidl文件来构建IPC...

Android中的IPC机制详解

声明: IPC机制没有怎么系统化的接触,主要是AIDL接触过,结合>这本书,系统的学习一下子这一块知识点,作为自己的一个学习笔记.分享给大家,有什么理解不到位望大家指明,我非常感谢你的指导. 一.什...

Android的IPC机制Binder的详解(转发)

第一部分 Binder的组成 1.1 驱动程序部分驱动程序的部分在以下的文件夹中:Java代码  kernel/include/linux/binder.h    kernel/drive...
  • sdhjob
  • sdhjob
  • 2011年01月04日 19:19
  • 1399

Android的IPC机制Binder的详解汇总

转:http://java-admin.iteye.com/blog/717888 第一部分 Binder的组成  1.1 驱动程序部分驱动程序的部分在以下的文件夹中: ...
  • javalfx
  • javalfx
  • 2015年10月12日 16:36
  • 248

Android IPC机制——Binder详解

IPC是指Android中的进程间通信,即在不同进程之间传递消息数据,Android中可实现进程通信的方法有很多,比如Intent、ContentProvider、Messenger、Binder或是...
  • Mr_Sk
  • Mr_Sk
  • 2016年02月25日 22:33
  • 683

android进程通信IPC机制之Binder详解

Android Binder机制原理(史上最强理解,没有之一) 2015-07-23 14:07 37876人阅读 评论(10) 收藏 举报 本文章已收录于: ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android IPC 机制详解:IBinder
举报原因:
原因补充:

(最多只允许输入30个字)