android IPC及原理簡介

什麼是Android操做系統,所謂的Android:是基於Linux內核的軟件平臺和操做系統,早期由Google開發,後由開放手機聯盟Open Handset Alliance)開發。java

Linux系統中進程間通訊的方式有:socket, named pipe,message queque, signal,share memory。Java系統中的進程間通訊方式有socket, named pipe等。android應用程序理所固然能夠應用JAVA的IPC機制實現進程間的通訊,node

取而代之的是Binder通訊。Google爲何要採用這種方式呢,這取決於Binder通訊方式的高效率。 Binder通訊是經過linux的binder driver來實現的。Binder通訊操做相似線程遷移(thread migration),兩個進程間IPC看起來就象是一個進程進入另外一個進程執行代碼而後帶着執行的結果返回。linux

Binder的用戶空間爲每個進程維護着一個可用的線程池,線程池用於處理到來的IPC以及執行進程本地消息,Binder通訊是同步而不是異步。Android中的Binder通訊是基於Service與Client的,全部須要IBinder通訊的進程都必須建立一個IBinder接口。android

系統中有一個進程管理全部的system service,Android虛擬機不容許用戶添加非受權的System service,固然如今源碼開發了,咱們能夠修改一些代碼來實現添加底層system Service的目的。服務器

對用戶程序來講,咱們也要建立server,或者Service用於進程間通訊,這裏有一ActivityManagerService管理JAVA應用層全部的service建立與鏈接(connect)。disconnect,全部的 Activity也是經過這個service來啓動,加載的。ActivityManagerService也是加載在Systems Servcie中的。cookie

Android虛擬機啓動以前系統會先啓動service Manager進程,service Manager打開binder驅動,並通知binder kernel驅動程序這個進程將做爲System Service Manager。而後該進程將進入一個循環,等待處理來自其餘進程的數據。用戶建立一個System service後,經過defaultServiceManager獲得一個遠程ServiceManager的接口。架構

經過這個接口咱們能夠調用 addService函數將System service添加到Service Manager進程中,而後client能夠經過getService獲取到須要鏈接的目的Service的IBinder對象。這個IBinder是 Service的BBinder在binder kernel的一個參考,因此service IBinder 在binder kernel中不會存在相同的兩個IBinder對象。app

每個Client進程一樣須要打開Binder驅動程序。對用戶程序而言,咱們得到這個對象就能夠經過binder kernel訪問service對象中的方法。Client與Service在不一樣的進程中,經過這種方式實現了相似線程間的遷移的通訊方式,對用戶程序而言當調用Service返回的IBinder接口後,訪問Service中的方法就如同調用本身的函數。異步

實現接口時有幾個原則:socket

拋出的異常不要返回給調用者. 跨進程拋異常處理是不可取的。IPC調用是同步的。若是你知道一個IPC服務須要超過幾毫秒的時間才能完成地話,你應該避免在Activity的主線程中調用。

也就是IPC調用會掛起應用程序致使界面失去響應. 這種狀況應該考慮單起一個線程來處理,能在AIDL接口中聲明靜態屬性。IPC的調用步驟:

1. 聲明一個接口類型的變量,該接口類型在.aidl文件中定義。

2. 實現ServiceConnection。

3. 調用ApplicationContext.bindService(),並在ServiceConnection實現中進行傳遞. 

4. 在ServiceConnection.onServiceConnected()實現中,你會接收一個IBinder實例(被調用的Service). 調用    YourInterfaceName.Stub.asInterface((IBinder)service)將參數轉換YourInterface類型。

5. 調用接口中定義的方法。 你總要檢測到DeadObjectException異常,該異常在鏈接斷開時被拋出。它只會被遠程方法拋出。

6. 斷開鏈接,調用接口實例中的ApplicationContext.unbindService()

IPC 及原理

IBinder接口

IBinder接口是對跨進程的對象的抽象。普通對象在當前進程能夠訪問,若是但願對象能被其它進程訪問,那就必須實現IBinder接口。IBinder接口能夠指向本地對象,也能夠指向遠程對象,調用者不須要關心指向的對象是本地的仍是遠程。

transact是IBinder接口中一個比較重要的函數,它的函數原型以下:

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則提供了實際的服務。

o 客戶端

BpBinder是遠程對象在當前進程的代理,它實現了IBinder接口。它的transact函數實現以下:

status_t BpBinder::transact(

    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

{

    // Once a binder has died, it will never come back to life.

    if (mAlive) {

        status_t status = IPCThreadState::self()->transact(

            mHandle, code, data, reply, flags);

        if (status == DEAD_OBJECT) mAlive = 0;

        return status;

    }

 

    return DEAD_OBJECT;

}

參數說明:

?  code 是請求的ID號。

?  data 是請求的參數。

?  reply 是返回的結果。

?  flags 一些額外的標識,如FLAG_ONEWAY。一般爲0。

transact只是簡單的調用了IPCThreadState::self()的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_LOG_TRANSACTIONS() {

        TextOutput::Bundle _b(alog);

        alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand "

            << handle << " / code " << TypeCode(code) << ": "

            << indent << data << dedent << endl;

    }

 

    if (err == NO_ERROR) {

        LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),

            (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");

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

        }

 

        IF_LOG_TRANSACTIONS() {

            TextOutput::Bundle _b(alog);

            alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand "

                << handle << ": ";

            if (reply) alog << indent << *reply << dedent << endl;

            else alog << "(none requested)" << endl;

        }

    } else {

        err = waitForResponse(NULL, NULL);

    }

 

    return err;

}

 

status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)

{

    int32_t cmd;

    int32_t err;

 

    while (1) {

        if ((err=talkWithDriver()) < NO_ERROR) break;

        err = mIn.errorCheck();

        if (err < NO_ERROR) break;

        if (mIn.dataAvail() == 0) continue;

 

        cmd = mIn.readInt32();

 

        IF_LOG_COMMANDS() {

            alog << "Processing waitForResponse Command: "

                << getReturnString(cmd) << endl;

        }

 

        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:

            {

                LOG_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));

                LOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY");

                if (err != NO_ERROR) goto finish;

 

                if (reply) {

                    if ((tr.flags & TF_STATUS_CODE) == 0) {

                        reply->ipcSetDataReference(

                            reinterpret_cast(tr.data.ptr.buffer),

                            tr.data_size,

                            reinterpret_cast(tr.data.ptr.offsets),

                            tr.offsets_size/sizeof(size_t),

                            freeBuffer, this);

                    } else {

                        err = *static_cast(tr.data.ptr.buffer);

                        freeBuffer(NULL,

                            reinterpret_cast(tr.data.ptr.buffer),

                            tr.data_size,

                            reinterpret_cast(tr.data.ptr.offsets),

                            tr.offsets_size/sizeof(size_t), this);

                    }

                } else {

                    freeBuffer(NULL,

                        reinterpret_cast(tr.data.ptr.buffer),

                        tr.data_size,

                        reinterpret_cast(tr.data.ptr.offsets),

                        tr.offsets_size/sizeof(size_t), this);

                    continue;

                }

            }

            goto finish;

 

        default:

            err = executeCommand(cmd);

            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;

}

這裏transact把請求經內核模塊發送了給服務端,服務端處理完請求以後,沿原路返回結果給調用者。這裏也能夠看出請求是同步操做,它會等待直到結果返回爲止。

在BpBinder之上進行簡單包裝,咱們能夠獲得與服務對象相同的接口,調用者無須要關心調用的對象是遠程的仍是本地的。拿ServiceManager來講:
(frameworks/base/libs/utils/IServiceManager.cpp)

class BpServiceManager : public BpInterface

{

public:

    BpServiceManager(const sp& impl)

        : BpInterface(impl)

    {

    }

...

    virtual status_t addService(const String16& name, const sp& service)

    {

        Parcel data, reply;

        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());

        data.writeString16(name);

        data.writeStrongBinder(service);

        status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);

        return err == NO_ERROR ? reply.readInt32() : err;

    }

...

};

BpServiceManager實現了 IServiceManager和IBinder兩個接口,調用者能夠把BpServiceManager的對象看做是一個IServiceManager對象或者IBinder對象。當調用者把BpServiceManager對象看成IServiceManager對象使用時,全部的請求只是對BpBinder::transact的封裝。這樣的封裝使得調用者不須要關心IServiceManager對象是本地的仍是遠程的了。

客戶經過defaultServiceManager函數來建立BpServiceManager對象:
(frameworks/base/libs/utils/IServiceManager.cpp)

sp<IServiceManager> defaultServiceManager()

{

    if (gDefaultServiceManager != NULL) return gDefaultServiceManager;

 

    {

        AutoMutex _l(gDefaultServiceManagerLock);

        if (gDefaultServiceManager == NULL) {

            gDefaultServiceManager = interface_cast<IServiceManager>(

                ProcessState::self()->getContextObject(NULL));

        }

    }

 

    return gDefaultServiceManager;

}

先經過ProcessState::self()->getContextObject(NULL)建立一個Binder對象,而後經過interface_cast和IMPLEMENT_META_INTERFACE(ServiceManager, 「android.os.IServiceManager」)把Binder對象包裝成 IServiceManager對象。原理上等同於建立了一個BpServiceManager對象。

ProcessState::self()->getContextObject調用ProcessState::getStrongProxyForHandle建立代理對象:

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)

{

    sp<IBinder> result;

 

    AutoMutex _l(mLock);

 

    handle_entry* e = lookupHandleLocked(handle);

 

    if (e != NULL) {

        // We need to create a new BpBinder if there isn't currently one, OR we

        // are unable to acquire a weak reference on this current one.  See comment

        // in getWeakProxyForHandle() for more info about this.

        IBinder* b = e->binder;

        if (b == NULL || !e->refs->attemptIncWeak(this)) {

            b = new BpBinder(handle);

            e->binder = b;

            if (b) e->refs = b->getWeakRefs();

            result = b;

        } else {

            // This little bit of nastyness is to allow us to add a primary

            // reference to the remote proxy when this team doesn't have one

            // but another team is sending the handle to us.

            result.force_set(b);

            e->refs->decWeak(this);

        }

    }

 

    return result;

}

若是handle爲空,默認爲context_manager對象,context_manager實際上就是ServiceManager。
o 服務端
服務端也要實現IBinder接口,BBinder類對IBinder接口提供了部分默認實現,其中transact的實現以下:

status_t BBinder::transact(

    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

{

    data.setDataPosition(0);

 

    status_t err = NO_ERROR;

    switch (code) {

        case PING_TRANSACTION:

            reply->writeInt32(pingBinder());

            break;

        default:

            err = onTransact(code, data, reply, flags);

            break;

    }

 

    if (reply != NULL) {

        reply->setDataPosition(0);

    }

 

    return err;

}

PING_TRANSACTION請求用來檢查對象是否還存在,這裏簡單的把 pingBinder的返回值返回給調用者。其它的請求交給onTransact處理。onTransact是BBinder裏聲明的一個protected類型的虛函數,這個要求它的子類去實現。好比CameraService裏的實現以下:

status_t CameraService::onTransact(

    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

{

    // permission checks...

    switch (code) {

        case BnCameraService::CONNECT:

            IPCThreadState* ipc = IPCThreadState::self();

            const int pid = ipc->getCallingPid();

            const int self_pid = getpid();

            if (pid != self_pid) {

                // we're called from a different process, do the real check

                if (!checkCallingPermission(

                        String16("android.permission.CAMERA")))

                {

                    const int uid = ipc->getCallingUid();

                    LOGE("Permission Denial: "

                            "can't use the camera pid=%d, uid=%d", pid, uid);

                    return PERMISSION_DENIED;

                }

            }

            break;

    }

 

    status_t err = BnCameraService::onTransact(code, data, reply, flags);

 

    LOGD("+++ onTransact err %d code %d", err, code);

 

    if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {

        // the 'service' command interrogates this binder for its name, and then supplies it

        // even for the debugging commands.  that means we need to check for it here, using

        // ISurfaceComposer (since we delegated the INTERFACE_TRANSACTION handling to

        // BnSurfaceComposer before falling through to this code).

 

        LOGD("+++ onTransact code %d", code);

 

        CHECK_INTERFACE(ICameraService, data, reply);

 

        switch(code) {

        case 1000:

        {

            if (gWeakHeap != 0) {

                sp h = gWeakHeap.promote();

                IMemoryHeap *p = gWeakHeap.unsafe_get();

                LOGD("CHECKING WEAK REFERENCE %p (%p)", h.get(), p);

                if (h != 0)

                    h->printRefs();

                bool attempt_to_delete = data.readInt32() == 1;

                if (attempt_to_delete) {

                    // NOT SAFE!

                    LOGD("DELETING WEAK REFERENCE %p (%p)", h.get(), p);

                    if (p) delete p;

                }

                return NO_ERROR;

            }

        }

        break;

        default:

            break;

        }

    }

    return err;

}

因而可知,服務端的onTransact是一個請求分發函數,它根據請求碼(code)作相應的處理。

o 消息循環

服務端(任何進程均可以做爲服務端)有一個線程監聽來自客戶端的請求,並循環處理這些請求。

若是在主線程中處理請求,能夠直接調用下面的函數:

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

若是想在非主線程中處理請求,能夠按下列方式:

        sp

 proc = ProcessState::self();

        if (proc->supportsProcesses()) {

            LOGV("App process: starting thread pool.\n");

            proc->startThreadPool();

        }

startThreadPool的實現原理:

void ProcessState::startThreadPool()

{

    AutoMutex _l(mLock);

    if (!mThreadPoolStarted) {

        mThreadPoolStarted = true;

        spawnPooledThread(true);

    }

}

 

void ProcessState::spawnPooledThread(bool isMain)

{

    if (mThreadPoolStarted) {

        int32_t s = android_atomic_add(1, &mThreadPoolSeq);

        char buf[32];

        sprintf(buf, "Binder Thread #%d", s);

        LOGV("Spawning new pooled thread, name=%s\n", buf);

        sp

 t = new PoolThread(isMain);

        t->run(buf);

    }

}

這裏建立了PoolThread的對象,實現上就是建立了一個線程。全部的線程類都要實現threadLoop虛函數。PoolThread的threadLoop的實現以下:

    virtual bool threadLoop()

    {

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

        return false;

    }

上述代碼,簡而言之就是建立了一個線程,而後在線程裏調用 IPCThreadState::self()->joinThreadPool函數。

下面再看joinThreadPool的實現:

do

{

...

        result = talkWithDriver();

        if (result >= NO_ERROR) {

            size_t IN = mIn.dataAvail();

            if (IN < sizeof(int32_t)) continue;

            cmd = mIn.readInt32();

            IF_LOG_COMMANDS() {

                alog << "Processing top-level Command: "

                    << getReturnString(cmd) << endl;

            }

            result = executeCommand(cmd);

        }

...

while(...);

這個函數在循環中重複執行下列動做:

talkWithDriver 經過ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)讀取請求和寫回結果。

executeCommand 執行相應的請求

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

對於控制對象生命週期的請求,像BR_ACQUIRE/BR_RELEASE直接作了處理。

對於BR_TRANSACTION請求,它調用被請求對象的transact函數。

按下列方式調用實際的對象:

if (tr.target.ptr) {

    sp<BBinder> b((BBinder*)tr.cookie);

    const status_t error = b->transact(tr.code, buffer, &reply, 0);

    if (error < NO_ERROR) reply.setError(error);

 

} else {

    const status_t error = the_context_object->transact(tr.code, buffer, &reply, 0);

    if (error < NO_ERROR) reply.setError(error);

}

若是tr.target.ptr不爲空,就把tr.cookie轉換成一個Binder對象,並調用它的transact函數。若是沒有目標對象,就調用 the_context_object對象的transact函數。奇怪的是,根本沒有誰對the_context_object進行初始化,the_context_object是空指針。緣由是context_mgr的請求發給了ServiceManager,因此根本不會走到else語句裏來。

o 內核模塊

android使用了一個內核模塊binder來中轉各個進程之間的消息。模塊源代碼放在binder.c裏,它是一個字符驅動程序,主要經過binder_ioctl與用戶空間的進程交換數據。其中BINDER_WRITE_READ用來讀寫數據,數據包中有一個cmd域用於區分不一樣的請求:

binder_thread_write用於發送請求或返回結果。

binder_thread_read用於讀取結果。

從binder_thread_write中調用binder_transaction中轉請求和返回結果,binder_transaction的實現以下:

對請求的處理:

經過對象的handle找到對象所在的進程,若是handle爲空就認爲對象是context_mgr,把請求發給context_mgr所在的進程。

把請求中全部的binder對象所有放到一個RB樹中。

把請求放到目標進程的隊列中,等待目標進程讀取。

如何成爲context_mgr呢?內核模塊提供了BINDER_SET_CONTEXT_MGR調用:

static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)

{

         ...

         case BINDER_SET_CONTEXT_MGR:

                 if (binder_context_mgr_node != NULL) {

                          printk(KERN_ERR "binder: BINDER_SET_CONTEXT_MGR already set\n");

                          ret = -EBUSY;

                          goto err;

                 }

                 if (binder_context_mgr_uid != -1) {

                          if (binder_context_mgr_uid != current->euid) {

                                   printk(KERN_ERR "binder: BINDER_SET_"

                                          "CONTEXT_MGR bad uid %d != %d\n",

                                          current->euid,

                                          binder_context_mgr_uid);

                                   ret = -EPERM;

                                   goto err;

                          }

                 } else

                          binder_context_mgr_uid = current->euid;

                 binder_context_mgr_node = binder_new_node(proc, NULL, NULL);

                 if (binder_context_mgr_node == NULL) {

                          ret = -ENOMEM;

                          goto err;

                 }

                 binder_context_mgr_node->local_weak_refs++;

                 binder_context_mgr_node->local_strong_refs++;

                 binder_context_mgr_node->has_strong_ref = 1;

                 binder_context_mgr_node->has_weak_ref = 1;

                 break;

ServiceManager(frameworks/base/cmds/servicemanager)經過下列方式成爲了context_mgr進程:

int binder_become_context_manager(struct binder_state *bs)

{

    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);

}

 

int main(int argc, char **argv)

{

    struct binder_state *bs;

    void *svcmgr = BINDER_SERVICE_MANAGER;

 

    bs = binder_open(128*1024);

 

    if (binder_become_context_manager(bs)) {

        LOGE("cannot become context manager (%s)\n", strerror(errno));

        return -1;

    }

 

    svcmgr_handle = svcmgr;

    binder_loop(bs, svcmgr_handler);

    return 0;

}

o 如何獲得服務對象的handle

服務提供者經過defaultServiceManager獲得ServiceManager對象,而後調用addService向服務管理器註冊。

服務使用者經過defaultServiceManager獲得ServiceManager對象,而後調用getService經過服務名稱查找到服務對象的handle。

o 如何經過服務對象的handle找到服務所在的進程

0表示服務管理器的handle,getService能夠查找到系統服務的handle。這個handle只是表明了服務對象,內核模塊是如何經過handle找到服務所在的進程的呢?

對於ServiceManager: ServiceManager調用了binder_become_context_manager使用本身成爲context_mgr,全部handle爲0的請求都會被轉發給ServiceManager。

對於系統服務和應用程序的Listener,在第一次請求內核模塊時(好比調用addService),內核模塊在一個RB樹中創建了服務對象和進程的對應關係。

         off_end = (void *)offp + tr->offsets_size;

         for (; offp < off_end; offp++) {

                 struct flat_binder_object *fp;

                 if (*offp > t->buffer->data_size - sizeof(*fp)) {

                          binder_user_error("binder: %d:%d got transaction with "

                                   "invalid offset, %d\n",

                                   proc->pid, thread->pid, *offp);

                          return_error = BR_FAILED_REPLY;

                          goto err_bad_offset;

                 }

                 fp = (struct flat_binder_object *)(t->buffer->data + *offp);

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

                          if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)

                                   printk(KERN_INFO "        node %d u%p -> ref %d desc %d\n",

                                          node->debug_id, node->ptr, ref->debug_id, ref->desc);

                 } break;

請求服務時,內核先經過handle找到對應的進程,而後把請求放到服務進程的隊列中。

o C調用JAVA

前面咱們分析的是C代碼的處理。對於JAVA代碼,JAVA調用C的函數經過JNI調用便可。從內核時讀取請求是在C代碼(executeCommand)裏進行了,那如何在C代碼中調用那些用JAVA實現的服務呢?

android_os_Binder_init裏的JavaBBinder對Java裏的Binder對象進行包裝。

JavaBBinder::onTransact調用Java裏的execTransact函數:

        jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,

            code, (int32_t)&data, (int32_t)reply, flags);

        jthrowable excep = env->ExceptionOccurred();

        if (excep) {

            report_exception(env, excep,

                "*** Uncaught remote exception!  "

                "(Exceptions are not yet supported across processes.)");

            res = JNI_FALSE;

 

            /* clean up JNI local ref -- we don't return to Java code */

            env->DeleteLocalRef(excep);

        }

o 廣播消息

binder不提供廣播消息,不過能夠ActivityManagerService服務來實現廣播。
(frameworks/base/core/java/android/app/ActivityManagerNative.java)

接收廣播消息須要實現接口BroadcastReceiver,而後調用ActivityManagerProxy::registerReceiver註冊。

觸發廣播調用ActivityManagerProxy::broadcastIntent。(應用程序並不直接調用它,而是調用Context對它的包裝)

相關文章
相關標籤/搜索