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的注冊過程后,下面還剩最后兩個函數了,就讓我們向它們發起進攻吧!
- 前言
- 第1章 閱讀前的準備工作
- 1.1 系統架構
- 1.1.1 Android系統架構
- 1.1.2 本書的架構
- 1.2 搭建開發環境
- 1.2.1 下載源碼
- 1.2.2 編譯源碼
- 1.3 工具介紹
- 1.3.1 Source Insight介紹
- 1.3.2 Busybox的使用
- 1.4 本章小結
- 第2章 深入理解JNI
- 2.1 JNI概述
- 2.2 學習JNI的實例:MediaScanner
- 2.3 Java層的MediaScanner分析
- 2.3.1 加載JNI庫
- 2.3.2 Java的native函數和總結
- 2.4 JNI層MediaScanner的分析
- 2.4.1 注冊JNI函數
- 2.4.2 數據類型轉換
- 2.4.3 JNIEnv介紹
- 2.4.4 通過JNIEnv操作jobject
- 2.4.5 jstring介紹
- 2.4.6 JNI類型簽名介紹
- 2.4.7 垃圾回收
- 2.4.8 JNI中的異常處理
- 2.5 本章小結
- 第3章 深入理解init
- 3.1 概述
- 3.2 init分析
- 3.2.1 解析配置文件
- 3.2.2 解析service
- 3.2.3 init控制service
- 3.2.4 屬性服務
- 3.3 本章小結
- 第4章 深入理解zygote
- 4.1 概述
- 4.2 zygote分析
- 4.2.1 AppRuntime分析
- 4.2.2 Welcome to Java World
- 4.2.3 關于zygote的總結
- 4.3 SystemServer分析
- 4.3.1 SystemServer的誕生
- 4.3.2 SystemServer的重要使命
- 4.3.3 關于 SystemServer的總結
- 4.4 zygote的分裂
- 4.4.1 ActivityManagerService發送請求
- 4.4.2 有求必應之響應請求
- 4.4.3 關于zygote分裂的總結
- 4.5 拓展思考
- 4.5.1 虛擬機heapsize的限制
- 4.5.2 開機速度優化
- 4.5.3 Watchdog分析
- 4.6 本章小結
- 第5章 深入理解常見類
- 5.1 概述
- 5.2 以“三板斧”揭秘RefBase、sp和wp
- 5.2.1 第一板斧--初識影子對象
- 5.2.2 第二板斧--由弱生強
- 5.2.3 第三板斧--破解生死魔咒
- 5.2.4 輕量級的引用計數控制類LightRefBase
- 5.2.5 題外話-三板斧的來歷
- 5.3 Thread類及常用同步類分析
- 5.3.1 一個變量引發的思考
- 5.3.2 常用同步類
- 5.4 Looper和Handler類分析
- 5.4.1 Looper類分析
- 5.4.2 Handler分析
- 5.4.3 Looper和Handler的同步關系
- 5.4.4 HandlerThread介紹
- 5.5 本章小結
- 第6章 深入理解Binder
- 6.1 概述
- 6.2 庖丁解MediaServer
- 6.2.1 MediaServer的入口函數
- 6.2.2 獨一無二的ProcessState
- 6.2.3 時空穿越魔術-defaultServiceManager
- 6.2.4 注冊MediaPlayerService
- 6.2.5 秋風掃落葉-StartThread Pool和join Thread Pool分析
- 6.2.6 你徹底明白了嗎
- 6.3 服務總管ServiceManager
- 6.3.1 ServiceManager的原理
- 6.3.2 服務的注冊
- 6.3.3 ServiceManager存在的意義
- 6.4 MediaPlayerService和它的Client
- 6.4.1 查詢ServiceManager
- 6.4.2 子承父業
- 6.5 拓展思考
- 6.5.1 Binder和線程的關系
- 6.5.2 有人情味的訃告
- 6.5.3 匿名Service
- 6.6 學以致用
- 6.6.1 純Native的Service
- 6.6.2 扶得起的“阿斗”(aidl)
- 6.7 本章小結
- 第7章 深入理解Audio系統
- 7.1 概述
- 7.2 AudioTrack的破解
- 7.2.1 用例介紹
- 7.2.2 AudioTrack(Java空間)分析
- 7.2.3 AudioTrack(Native空間)分析
- 7.2.4 關于AudioTrack的總結
- 7.3 AudioFlinger的破解
- 7.3.1 AudioFlinger的誕生
- 7.3.2 通過流程分析AudioFlinger
- 7.3.3 audio_track_cblk_t分析
- 7.3.4 關于AudioFlinger的總結
- 7.4 AudioPolicyService的破解
- 7.4.1 AudioPolicyService的創建
- 7.4.2 重回AudioTrack
- 7.4.3 聲音路由切換實例分析
- 7.4.4 關于AudioPolicy的總結
- 7.5 拓展思考
- 7.5.1 DuplicatingThread破解
- 7.5.2 題外話
- 7.6 本章小結
- 第8章 深入理解Surface系統
- 8.1 概述
- 8.2 一個Activity的顯示
- 8.2.1 Activity的創建
- 8.2.2 Activity的UI繪制
- 8.2.3 關于Activity的總結
- 8.3 初識Surface
- 8.3.1 和Surface有關的流程總結
- 8.3.2 Surface之乾坤大挪移
- 8.3.3 乾坤大挪移的JNI層分析
- 8.3.4 Surface和畫圖
- 8.3.5 初識Surface小結
- 8.4 深入分析Surface
- 8.4.1 與Surface相關的基礎知識介紹
- 8.4.2 SurfaceComposerClient分析
- 8.4.3 SurfaceControl分析
- 8.4.4 writeToParcel和Surface對象的創建
- 8.4.5 lockCanvas和unlockCanvasAndPost分析
- 8.4.6 GraphicBuffer介紹
- 8.4.7 深入分析Surface的總結
- 8.5 SurfaceFlinger分析
- 8.5.1 SurfaceFlinger的誕生
- 8.5.2 SF工作線程分析
- 8.5.3 Transaction分析
- 8.5.4 關于SurfaceFlinger的總結
- 8.6 拓展思考
- 8.6.1 Surface系統的CB對象分析
- 8.6.2 ViewRoot的你問我答
- 8.6.3 LayerBuffer分析
- 8.7 本章小結
- 第9章 深入理解Vold和Rild
- 9.1 概述
- 9.2 Vold的原理與機制分析
- 9.2.1 Netlink和Uevent介紹
- 9.2.2 初識Vold
- 9.2.3 NetlinkManager模塊分析
- 9.2.4 VolumeManager模塊分析
- 9.2.5 CommandListener模塊分析
- 9.2.6 Vold實例分析
- 9.2.7 關于Vold的總結
- 9.3 Rild的原理與機制分析
- 9.3.1 初識Rild
- 9.3.2 RIL_startEventLoop分析
- 9.3.3 RIL_Init分析
- 9.3.4 RIL_register分析
- 9.3.5 關于Rild main函數的總結
- 9.3.6 Rild實例分析
- 9.3.7 關于Rild的總結
- 9.4 拓展思考
- 9.4.1 嵌入式系統的存儲知識介紹
- 9.4.2 Rild和Phone的改進探討
- 9.5 本章小結
- 第10章 深入理解MediaScanner
- 10.1 概述
- 10.2 android.process.media分析
- 10.2.1 MSR模塊分析
- 10.2.2 MSS模塊分析
- 10.2.3 android.process.media媒體掃描工作的流程總結
- 10.3 MediaScanner分析
- 10.3.1 Java層分析
- 10.3.2 JNI層分析
- 10.3.3 PVMediaScanner分析
- 10.3.4 關于MediaScanner的總結
- 10.4 拓展思考
- 10.4.1 MediaScannerConnection介紹
- 10.4.2 我問你答
- 10.5 本章小結