结合源码9、10、深入理解Android卷一
以MediaServer为例,一个可执行函数,入口函数是main
Main_MediaService.cpp
binder是Android系统提供的一种进程间通讯机制(IPC),Android系统可以看作是一个基于Binder通信的C/S框架
a、server进程要注册一些service到serviceManager中,所以server是serviceManager的客户端, serviceManager就是服务端
b、某个client要使用service,必须先到serviceManager中获取该service的相关信息,所以client是 serviceManager的客户端
c、client根据得到的service信息与service所在的server进程建立通信的通路,然后就可以直接与 service交互,client是service的客户端
d、三者的交互都是基于binder通信的
Binder只是为C/S架构提供了一种通信的方式
在defaultServiceManager中创建了BpBinder
最后还是回到interface_cast<IServiceManager>
在IServiceManager.h文件中,使用宏业务和通讯挂钩
宏定义在IInterface.h文件中
宏替换后的实际代码
DECLEAR宏声明了一些函数和一个变量
IMPLEMENT宏的作用就是定义
IMPLEMENT宏替换如下
interface_cast就是在IMPLEMTN宏中,将BpBinder指针转换成一个IServiceManager
intr = new BpServiceManager(obj)
::android::sp<I##INTERFACE> I##INTERFACE::asInterface( \
const ::android::sp<::android::IBinder>& obj) \
{ \
::android::sp<I##INTERFACE> intr; \
if (obj != nullptr) { \
intr = static_cast<I##INTERFACE*>( \
obj->queryLocalInterface( \
I##INTERFACE::descriptor).get()); \
if (intr == nullptr) { \
intr = new Bp##INTERFACE(obj); //在这里做的转换 \
} \
} \
return intr; \
}
interface_cast不是指针的转换,而是利用BpBinder作为参数新建了一个BpServiceManager对象
回到IserviceManager
a、IServiceManager、BpServiceManager和BnServiceManager都与业务逻辑相关
b、BnServiceManager同时从IServiceManager BBinder派生,表示它可以直接参与Binder通讯
c、BpServiceManager从BpInterface派生,支线上看与BpBinder没有联系
d、BnServiceManager是一个虚类,业务最终需要子类来实现
BeRefBase中的mRemote就是BpBinder
IserviceManager中包含有BpServiceManager,在BpServiceManager继承自BpInterface<IServiceManager>(impl),BpInterface又继承自BpRefBase
跟踪到BpRefBase
在构造函数中,mRemote(o.get())就是new BpBinder(0)
BpServiceManager的一个变量mRemote指向了BpBinder
defaultServiceManager有两个关键对象:
有一个BpBinder对象,它的handle的值是0
有一个BpServiceManager对象,它的mRemote值是BpBinder
BpServiceManager对象实现了IserviceManager的业务函数,又有BpBinder作为通信代表
MediaPlayerService注册,调用了defaultServiceManager的addService(),上面有分析到defaultServiceManager实际返回的对象是BpServiceManager
addService中
remote就是BpBinder
Parcel当作数据包
addService是一个业务层的函数,把请求数据打包成data后,传递给BpBinder的transact函数,就是把通信工作交给了BpBinder
在BpBinder的transact方法中,将数据直接交给了IPCThreadState的transact方法
第一次进入的时候gHaveTLS一定是false
注:TLS是Thread Local Storage线程本地存储空间的简称,这种空间每个线程都有,线程间不会共享
会new一个IPCThreadState对象,构造函数中会调用pthread_setspecific
pthread_setspecific把自己设置到线程本地存储中去
mIn和mOut是两个Parcel,发送和接收命令的缓冲区
每个线程都有一个IPCThreadState,每个IPCThreadState中都有一个mIn,mOut,mIn是用来接收来自Binder设备的数据,mOut是用来存储发往Binder设备的数据
再到IPCThreadState的transact,这个函数实际完成了与Binder通信的工作
先发数据,再等结果
先看发送方法writeTransactionData
binder_transaction_data是和binder设备通信的数据结构
code是消息码
mOut将命令写入,但没有发送出去,到这里,将addService的请求信息已经写到mOut中
等待回复waitForResponse
收到回复后的处理executeCommand(cmd)
case BR_TRANSACTION:
{
binder_transaction_data_secctx tr_secctx;
binder_transaction_data& tr = tr_secctx.transaction_data;
if (cmd == (int) BR_TRANSACTION_SEC_CTX) {
result = mIn.read(&tr_secctx, sizeof(tr_secctx));
} else {
result = mIn.read(&tr, sizeof(tr));
tr_secctx.secctx = 0;
}
ALOG_ASSERT(result == NO_ERROR,
"Not enough command data for brTRANSACTION");
if (result != NO_ERROR) break;
//Record the fact that we're in a binder call.
mIPCThreadStateBase->pushCurrentState(
IPCThreadStateBase::CallState::BINDER);
Parcel buffer;
buffer.ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), freeBuffer, this);
const pid_t origPid = mCallingPid;
const char* origSid = mCallingSid;
const uid_t origUid = mCallingUid;
const int32_t origStrictModePolicy = mStrictModePolicy;
const int32_t origTransactionBinderFlags = mLastTransactionBinderFlags;
const int32_t origWorkSource = mWorkSource;
const bool origPropagateWorkSet = mPropagateWorkSource;
// Calling work source will be set by Parcel#enforceInterface. Parcel#enforceInterface
// is only guaranteed to be called for AIDL-generated stubs so we reset the work source
// here to never propagate it.
clearCallingWorkSource();
clearPropagateWorkSource();
mCallingPid = tr.sender_pid;
mCallingSid = reinterpret_cast<const char*>(tr_secctx.secctx);
mCallingUid = tr.sender_euid;
mLastTransactionBinderFlags = tr.flags;
// ALOGI(">>>> TRANSACT from pid %d sid %s uid %d\n", mCallingPid,
// (mCallingSid ? mCallingSid : "<N/A>"), mCallingUid);
Parcel reply;
status_t error;
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BR_TRANSACTION thr " << (void*)pthread_self()
<< " / obj " << tr.target.ptr << " / code "
<< TypeCode(tr.code) << ": " << indent << buffer
<< dedent << endl
<< "Data addr = "
<< reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer)
<< ", offsets addr="
<< reinterpret_cast<const size_t*>(tr.data.ptr.offsets) << endl;
}
if (tr.target.ptr) {
// We only have a weak reference on the target object, so we must first try to
// safely acquire a strong reference before doing anything else with it.
if (reinterpret_cast<RefBase::weakref_type*>(
tr.target.ptr)->attemptIncStrong(this)) {
error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,
&reply, tr.flags);
reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this);
} else {
error = UNKNOWN_TRANSACTION;
}
} else {
error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
}
mIPCThreadStateBase->popCurrentState();
//ALOGI("<<<< TRANSACT from pid %d restore pid %d sid %s uid %d\n",
// mCallingPid, origPid, (origSid ? origSid : "<N/A>"), origUid);
if ((tr.flags & TF_ONE_WAY) == 0) {
LOG_ONEWAY("Sending reply to %d!", mCallingPid);
if (error < NO_ERROR) reply.setError(error);
sendReply(reply, 0);
} else {
LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);
}
mCallingPid = origPid;
mCallingSid = origSid;
mCallingUid = origUid;
mStrictModePolicy = origStrictModePolicy;
mLastTransactionBinderFlags = origTransactionBinderFlags;
mWorkSource = origWorkSource;
mPropagateWorkSource = origPropagateWorkSet;
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BC_REPLY thr " << (void*)pthread_self() << " / obj "
<< tr.target.ptr << ": " << indent << reply << dedent << endl;
}
}
break;
the_context_object是IPCThreadState.cpp中定义的一个全局变量
可通过setTheContextObject函数设置
收到binder驱动发来的service死掉的消息
这里收到来自驱动的指示,创建一个新的线程,用于和binder通信
talkWithDriver()
startThreadPool()
如果已经mThreadPoolStarted,函数没有下一步
调用spawnPooledThread(true)
在PoolThread中创建一个IPCThreadState,每个线程都有一个,但线程不共享,调用joinThreadPool(true)
来到joinThreadPool(true)
isMain为true,需要循环处理,把请求信息写到mOut中,后续会发送出去
getAndExecuteCommand处理消息
组装请求信息到mOut中,最后调用talkWithDriver(false)
有两个线程在为service服务:
startThreadPool中新启动的线程通过joinThreadPool读取Binder设备,查看是否有请求
主线程也调用joinThreadPool读取binder设备,查看是否有请求
Binder设备是支持多线程操作的
Binder是通信机制,业务可以基于Binder通信,也可以使用别的IPC通信
defultServiceManager返回的是一个BpServiceManager,通过它可以把命令请求发送给handle值为0的目的端
应该有一个类从BnServiceManager中派生出来,并处理来自远方的请求,源码中并没有,是ServiceManager完成了BnServiceManager的工作
篇幅有限,下篇继续