服務的註冊

Server獲得了Service Manager遠程接口之後,就要把自己的Service添加到Service Manager中去,然後把自己啓動起來,等待Client的請求。本文將通過分析說明Server的啓動過程是怎麼樣的。我們通過Android Binder實列篇中的實列來說明下服務啓動的整個過程。
類的繼承關係圖:
這裏寫圖片描述
從上圖可以明顯看出BnShareBuffer實際是繼承了IShareBuffer和BBinder類。IShareBuffer和BBinder類又分別繼承了IInterface和IBinder類,IInterface和IBinder類又同時繼承了RefBase類。
實際上,BnShareBuffer並不是直接接收到Client處發送過來的請求,而是使用了IPCThreadState接收Client處發送過來的請求,而IPCThreadState又藉助了ProcessState類來與Binder驅動程序交互。IPCThreadState接收到了Client處的請求後,就會調用BBinder類的transact函數,並傳入相關參數,BBinder類的transact函數最終調用BnShareBuffer類的onTransact函數,於是,就開始真正地處理Client的請求了。
源碼中通過:

SharedBufferService::instantiate();//add to the systemServer
static void instantiate()
    {
        defaultServiceManager()->addService(String16(SHARED_BUFFER), new SharedBufferService());
    }

前面分析過defaultServiceManager()是如何獲取systemServices遠程代理的。本文主要分析addService這個過程是如何一步一步在系統中添加服務的。
BpServiceManger::addService的實現在framworks/native/libs/binder/IServiceManager.cpp中。

class BpServiceManager : public BpInterface<IServiceManager>
{
public:
    BpServiceManager(const sp<IBinder>& impl)
        : BpInterface<IServiceManager>(impl)
    {
    }

   ....
    virtual status_t addService(const String16& name, const sp<IBinder>& service,
            bool allowIsolated)
    {
        Parcel data, reply;
    unsigned n;
        status_t err;
        /*
        *寫入數據到parcel中,序列化數據
        */
        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
        data.writeString16(name);
        //寫入一個binder引用
        data.writeStrongBinder(service);
        data.writeInt32(allowIsolated ? 1 : 0);
        for (n = 1; n <= 5; n++) {
            err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
            if (err == -EPIPE) {
                ALOGI("%s is waiting for serviceManager... (retry %d)\n",
                    String8(name).string(), n);
                sleep(1);
            } else {
                break;
            }
        }
        return err == NO_ERROR ? reply.readExceptionCode() : err;
    }

   ....
};

下面我們看看data.writeStrongBinder(service); 這個是服務註冊的關鍵之所在!

status_t Parcel::writeStrongBinder(const sp<IBinder>& val)  
{  
    return flatten_binder(ProcessState::self(), val, this);  
}
status_t flatten_binder(const sp<ProcessState>& proc,  
    const sp<IBinder>& binder, Parcel* out)  
{  
    flat_binder_object obj;  //內核中傳輸binder的結構
    /*
    *0x7f表示處理本Binder實體請求數據包的線程的最低優先級,FLAT_BINDER_FLAG_ACCEPTS_FDS
    *表示這個Binder實體可以接受文件描述符,Binder實體在收到文件描述符時,就會在本進程中打開這個文件。
    */  
    obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;  
    if (binder != NULL) {  //binder爲 新建立的SharedBufferService一定不爲空
        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);  //將binder寫入Parcel中
}  
inline static status_t finish_flatten_binder(  
    const sp<IBinder>& binder, const flat_binder_object& flat, Parcel* out)  
{  
    return out->writeObject(flat, false);  //最終調用writeObject寫入一個對像
}  

接下來status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
這裏的remote成員函數來自於BpRefBase類,它返回一個BpBinder指針。

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

最終調用IPCThreadState::transact進執行實際的操作。這裏的mHandle一定爲0,因爲這裏表示的是Service Manager遠程接口,它的句柄值一定是0,code爲ADD_SERVICE_TRANSACTION。

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 0  
        if (code == 4) { // relayout  
            LOGI(">>>>>> CALLING transaction 4");  
        } else {  
            LOGI(">>>>>> CALLING transaction %d", code);  
        }  
        #endif  
        if (reply) {  
            err = waitForResponse(reply);  
        } else {  
            Parcel fakeReply;  
            err = waitForResponse(&fakeReply);  
        }  
        #if 0  
        if (code == 4) { // relayout  
            LOGI("<<<<<< RETURNING transaction 4");  
        } else {  
            LOGI("<<<<<< RETURNING transaction %d", code);  
        }  
        #endif  

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

最終通過waitForResponse ==>talkWithDriver將註冊信息寫入驅動。最終會喚醒在等待數據的serviceManager線程,serviceManager線程接收到數據後,會對其進行解析並添加服務到管理的服務列表中!整個過程比較複雜,在老羅的博客中有較詳細的講述!
Android系統進程間通信(IPC)機制Binder中的Server啓動過程源代碼分析

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章