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 本章小结