<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                1. 業務層的工作 再回到MS的main函數,下一個要分析的是MediaPlayerService,它的代碼如下所示: **MediaPlayerService.cpp** ~~~ void MediaPlayerService::instantiate() { defaultServiceManager()->addService( String16("media.player"), new MediaPlayerService()); } ~~~ 根據前面的分析,defaultServiceManager()實際返回的對象是BpServiceManager,它是IServiceManager的后代,代碼如下所示: **IServiceManager.cpp::BpServiceManager的addService()函數** ~~~ virtual status_t addService(const String16&name, const sp<IBinder>& service) { //Parcel:就把它當作是一個數據包。 Parceldata, reply; data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); data.writeString16(name); data.writeStrongBinder(service); //remote返回的是mRemote,也就是BpBinder對象 status_terr = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply); returnerr == NO_ERROR ? reply.readInt32() : err; } ~~~ 別急著往下走,應先思考以下兩個問題: - 調用BpServiceManager的addService是不是一個業務層的函數? - addService函數中把請求數據打包成data后,傳給了BpBinder的transact函數,這是不是把通信的工作交給了BpBinder? 兩個問題的答案都是肯定的。至此,業務層的工作原理應該是很清晰了,它的作用就是將請求信息打包后,再交給通信層去處理。 2. 通信層的工作 下面分析BpBinder的transact函數。前面說過,在BpBinder中確實找不到任何與Binder設備交互的地方嗎?那它是如何參與通信的呢?原來,秘密就在這個transact函數中,它的實現代碼如下所示: **BpBinder.cpp** ~~~ status_t BpBinder::transact(uint32_t code, constParcel& data, Parcel* reply, uint32_tflags) { if(mAlive) { //BpBinder果然是道具,它把transact工作交給了IPCThreadState status_t status = IPCThreadState::self()->transact( mHandle,code, data, reply, flags);//mHandle也是參數 if(status == DEAD_OBJECT) mAlive = 0; return status; } returnDEAD_OBJECT; } ~~~ 這里又遇見了IPCThreadState,之前也見過一次。看來,它確實與Binder通信有關,所以必須對其進行深入分析! (1)“勞者一份”的IPCThreadState 誰是“勞者”?線程,是進程中真正干活的伙計,所以它正是勞者。而“勞者一份”,就是每個伙計一份的意思。IPCThreadState的實現代碼在IPCThreadState.cpp中,如下所示: **IPCThreadState.cpp** ~~~ IPCThreadState* IPCThreadState::self() { if(gHaveTLS) {//第一次進來為false restart: constpthread_key_t k = gTLS; /* TLS是Thread Local Storage(線程本地存儲空間)的簡稱。 這里只需知曉:這種空間每個線程都有,而且線程間不共享這些空間。 通過pthread_getspecific/pthread_setspecific函數可以獲取/設置這些空間中的內容。 從線程本地存儲空間中獲得保存在其中的IPCThreadState對象。 有調用pthread_getspecific的地方,肯定也有調用pthread_setspecific的地方 */ IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k); if(st) return st; // new一個對象,構造函數中會調用pthread_setspecific return new IPCThreadState; } if(gShutdown) return NULL; pthread_mutex_lock(&gTLSMutex); if(!gHaveTLS) { if(pthread_key_create(&gTLS, threadDestructor) != 0) { pthread_mutex_unlock(&gTLSMutex); return NULL; } gHaveTLS = true; } pthread_mutex_unlock(&gTLSMutex); //其實goto沒有我們說的那么不好,匯編代碼也有很多跳轉語句(沒辦法,太低級的語言了),關鍵是要用好 goto restart; } ~~~ 接下來,有必要轉向分析它的構造函數IPCThreadState(),如下所示: **IPCThreadState.cpp** ~~~ IPCThreadState::IPCThreadState() :mProcess(ProcessState::self()), mMyThreadId(androidGetTid()) { //在構造函數中,把自己設置到線程本地存儲中去。 pthread_setspecific(gTLS, this); clearCaller(); //mIn和mOut是兩個Parcel。把它看成是發送和接收命令的緩沖區即可。 mIn.setDataCapacity(256); mOut.setDataCapacity(256); } ~~~ 每個線程都有一個IPCThreadState,每個IPCThreadState中都有一個mIn、一個mOut,其中mIn是用來接收來自Binder設備的數據的,而mOut則是用來存儲發往Binder設備的數據的。 (2)勤勞的transact 傳輸工作是很辛苦的。我們剛才看到BpBinder的transact調用了IPCThreadState的transact函數,這個函數實際完成了與Binder通信的工作,如下面的代碼所示: **IPCThreadState.cpp** ~~~ //注意,handle的值為0,代表了通信的目的端 status_t IPCThreadState::transact(int32_t handle, uint32_tcode, const Parcel& data, Parcel* reply, uint32_t flags) { status_terr = data.errorCheck(); flags |=TF_ACCEPT_FDS; ...... /* 注意這里的第一個參數BC_TRANSACTION,它是應用程序向binder設備發送消息的消息碼, 而binder設備向應用程序回復消息的消息碼以BR_開頭。消息碼的定義在binder_module.h中, 請求消息碼和回應消息碼的對應關系,需要查看Binder驅動的實現才能將其理清楚,我們這里暫時用不上。 */ err =writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL); ...... err = waitForResponse(reply); ...... returnerr; } ~~~ 多熟悉的流程:先發數據,然后等結果。再簡單不過了!不過,我們有必要確認一下handle這個參數到底起了什么作用。先來看writeTransactionData函數,它的實現如下所示: **IPCThreadState.cpp** ~~~ status_tIPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags, int32_thandle, uint32_t code, const Parcel& data, status_t* statusBuffer) { //binder_transaction_data 是和binder設備通信的數據結構。 binder_transaction_data tr; //果然,handle的值傳遞給了target,用來標識目的端,其中0是ServiceManager的標志。 tr.target.handle= handle; //code是消息碼,用來switch/case的! tr.code =code; tr.flags= binderFlags; conststatus_t err = data.errorCheck(); if (err== NO_ERROR) { tr.data_size = data.ipcDataSize(); tr.data.ptr.buffer = data.ipcData(); tr.offsets_size = data.ipcObjectsCount()*sizeof(size_t); tr.data.ptr.offsets = data.ipcObjects(); } else if(statusBuffer) { tr.flags |= TF_STATUS_CODE; *statusBuffer = err; tr.data_size = sizeof(status_t); tr.data.ptr.buffer = statusBuffer; tr.offsets_size = 0; tr.data.ptr.offsets = NULL; } else { return (mLastError = err); } //把命令寫到mOut中, 而不是直接發出去,可見這個函數有點名不副實。 mOut.writeInt32(cmd); mOut.write(&tr, sizeof(tr)); returnNO_ERROR; } ~~~ 現在,已經把addService的請求信息寫到mOut中了。接下來再看發送請求和接收回復部分的實現,代碼在waitForResponse函數中,如下所示: **IPCThreadState.cpp** ~~~ status_t IPCThreadState::waitForResponse(Parcel*reply, status_t *acquireResult) { int32_tcmd; int32_terr; while (1) { //好家伙,talkWithDriver! if((err=talkWithDriver()) < NO_ERROR) break; err =mIn.errorCheck(); if(err < NO_ERROR) break; if(mIn.dataAvail() == 0) continue; cmd =mIn.readInt32(); switch(cmd) { caseBR_TRANSACTION_COMPLETE: if (!reply && !acquireResult) goto finish; break; ...... 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; } returnerr; } ~~~ OK,我們已發送了請求數據,假設馬上就收到了回復,后續該怎么處理呢?來看executeCommand函數,如下所示: **IPCThreadState.cpp** ~~~ status_t IPCThreadState::executeCommand(int32_tcmd) { BBinder*obj; RefBase::weakref_type* refs; status_tresult = NO_ERROR; switch(cmd) { caseBR_ERROR: result = mIn.readInt32(); break; ...... caseBR_TRANSACTION: { binder_transaction_data tr; result = mIn.read(&tr, sizeof(tr)); if (result != NO_ERROR) break; Parcel buffer; Parcel reply; if (tr.target.ptr) { /* 看到了BBinder,想起圖6-3了嗎?BnServiceXXX從BBinder派生, 這里的b實際上就是實現BnServiceXXX的那個對象,關于它的作用,我們要在6.5節中講解。 */ 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 { /* the_context_object是IPCThreadState.cpp中定義的一個全局變量, 可通過setTheContextObject函數設置 */ const status_t error = the_context_object->transact(tr.code,buffer, &reply, 0); if (error < NO_ERROR) reply.setError(error); } break; ...... caseBR_DEAD_BINDER: { /* 收到binder驅動發來的service死掉的消息,看來只有Bp端能收到了, 后面,我們將會對此進行分析。 */ BpBinder *proxy = (BpBinder*)mIn.readInt32(); proxy->sendObituary(); mOut.writeInt32(BC_DEAD_BINDER_DONE); mOut.writeInt32((int32_t)proxy); }break; ...... case BR_SPAWN_LOOPER: //特別注意,這里將收到來自驅動的指示以創建一個新線程,用于和Binder通信。 mProcess->spawnPooledThread(false); break; default: result = UNKNOWN_ERROR; break; } ...... if(result != NO_ERROR) { mLastError = result; } returnresult; } ~~~ (3)打破砂鍋問到底 你一定想知道如何和Binder設備交互的吧?是通過write和read函數來發送和接收請求的嗎?來看talkwithDriver函數,如下所示: **IPCThreadState.cpp** ~~~ status_t IPCThreadState::talkWithDriver(booldoReceive) { // binder_write_read是用來與Binder設備交換數據的結構 binder_write_read bwr; constbool needRead = mIn.dataPosition() >= mIn.dataSize(); constsize_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0; //請求命令的填充 bwr.write_size = outAvail; bwr.write_buffer = (long unsigned int)mOut.data(); if(doReceive && needRead) { //接收數據緩沖區信息的填充。如果以后收到數據,就直接填在mIn中了。 bwr.read_size = mIn.dataCapacity(); bwr.read_buffer = (long unsigned int)mIn.data(); } else { bwr.read_size = 0; } if((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR; bwr.write_consumed = 0; bwr.read_consumed = 0; status_terr; do { #ifdefined(HAVE_ANDROID_OS) //看來不是read/write調用,而是ioctl方式。 if(ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0) err = NO_ERROR; else err = -errno; #else err =INVALID_OPERATION; #endif }while (err == -EINTR); if (err>= NO_ERROR) { if(bwr.write_consumed > 0) { if (bwr.write_consumed < (ssize_t)mOut.dataSize()) mOut.remove(0, bwr.write_consumed); else mOut.setDataSize(0); } if(bwr.read_consumed > 0) { mIn.setDataSize(bwr.read_consumed); mIn.setDataPosition(0); } return NO_ERROR; } returnerr; } ~~~ 較為深入地分析了MediaPlayerService的注冊過程后,下面還剩最后兩個函數了,就讓我們向它們發起進攻吧!
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看