从MediaServer看Binder的使用方式(一)
theme: channing-cyan
一 概述
Binder是Android中的一种IPC机制,在Binder中,Binder是基于C/S架构的,但是除了C/S架构中的Client和Server,Android中还有一个ServiceManager,它的作用就是管理各种服务,我们在Service的启动中已经见识过它了。
接下来,在我们深入学习Binder之前,我们先通过Android系统自己对于Binder的使用,来了解Binder,在这里,我们选择的目标是MediaServer
源码目录
```
frameworks/av/media/mediaserver/main_mediaserver.cpp frameworks/native/libs/binder/ProcessState.cpp frameworks/native/libs/binder/IServiceManager.cpp frameworks/native/libs/binder/BpBinder.cpp frameworks/native/libs/binder/include/binder/IInterface.h frameworks/native/libs/binder/IServiceManager.cpp frameworks/native/libs/binder/Binder.cpp frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp frameworks/native/libs/binder/BpBinder.cpp frameworks/native/libs/binder/IPCThreadState.cpp ```
二 MediaServer的入口
MediaServer的入口函数如下,这是一个非常标准的Binder使用流程
```cpp [main_mediaserver.cpp]
int main(int argc __unused, char **argv __unused)
{
signal(SIGPIPE, SIG_IGN);
//1 获得一个ProcessState的实例
sp
在上述代码中,我们看到了大致6个步骤,接下来,我们就对这6个步骤进行一一分析
三 ProcessState
看步骤1的代码,我们也能大致猜测出来,它是一个单例,这个self方法具体如下
```cpp [ProcessState.cpp]
sp
3.1 ProcessState的构造函数
```cpp [ProcessState.cpp]
ProcessState::ProcessState(const char *driver) : mDriverName(String8(driver)) //这里是关键点 , mDriverFD(open_driver(driver)) , ... { if (mDriverFD >= 0) { //调用一个mmap,拿到起始地址 mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0); if (mVMStart == MAP_FAILED) { // 如果mmap映射失败,一般不会执行 ALOGE("Using %s failed: unable to mmap transaction memory.\n", mDriverName.c_str()); close(mDriverFD); mDriverFD = -1; mDriverName.clear(); } }
LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating.");
} ```
3.2 open_driver
```cpp [ProcessState.cpp]
static int open_driver(const char *driver)
{
//打开binder驱动
int fd = open(driver, O_RDWR | O_CLOEXEC);
if (fd >= 0) {
int vers = 0;
//通过ioctl的方式与binder驱动进行交互
//版本
status_t result = ioctl(fd, BINDER_VERSION, &vers);
if (result == -1) {
ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
close(fd);
fd = -1;
}
if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
ALOGE("Binder driver protocol(%d) does not match user space protocol(%d)! ioctl() return value: %d",
vers, BINDER_CURRENT_PROTOCOL_VERSION, result);
close(fd);
fd = -1;
}
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
//最大线程数,默认是15
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
if (result == -1) {
ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
}
} else {
ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno));
}
return fd;
}
```
到这里,Process的构造函数就算是结束了,它主要的工作如下
- 打开binder驱动(默认是/dev/binder),获得一个fd
- 对于返回的fd使用mmap,这样Binder驱动就会分配一块内存来接收数据
- Process是单例的
四 defaultServiceManager
defaultServiceManager是IServiceManager中的一个函数,它返回了一个IServiceManager对象,它也是一个单例
```cpp [IServiceManager.cpp ]
sp
{
AutoMutex _l(gDefaultServiceManagerLock);
while (gDefaultServiceManager == nullptr) {
//创建一个gDefaultServiceManager对象
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(nullptr));
//如果为空,就循环等待
if (gDefaultServiceManager == nullptr)
sleep(1);
}
}
return gDefaultServiceManager;
} ```
在defaultServiceManager中,首先会通过getContextObject来获取一个gDefaultServiceManager对象,如果没有获取到,那么就会循环等待,这里我们有两个问题
- getContextObject是如何获取的gDefaultServiceManager
- 什么情况下会获取不到
首先我们思考第一个问题,getContextObject做了什么
4.1 getContextObject
getContextObject是ProcessState中的函数,具体如下
```cpp [ProcessState.cpp]
sp
[ProcessState.cpp]
//通过一个int的handle值,来获得一个IBinder
sp
AutoMutex _l(mLock);
//根据handle值来查找
handle_entry* e = lookupHandleLocked(handle);
if (e != nullptr) {
//拿到查找对象中的IBinder
IBinder* b = e->binder;
if (b == nullptr || !e->refs->attemptIncWeak(this)) {
//如果IBinder为空
if (handle == 0) {
//handle值为0
Parcel data;
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, nullptr, 0);
if (status == DEAD_OBJECT)
return nullptr;
}
//根据handle值创建一个BpBinder
b = BpBinder::create(handle);
//填充entry
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
} ```
4.2 BpBinder
在getStrongProxyForHandle函数中,我们看到了一个对象叫BpBinder,关于BpBinder,这里简单说明一下
- 在Android中,使用BInder通信时,一般都会有两个对象BpBinder和BBinder
- 它们都是继承自IBinder而来的,BpBinder代表客户端,BBinder代表服务端
- 这里创建时传入的handle值0就是它们用来对应的标识
关于BpBinder的构造函数如下
```cpp [BpBinder.cpp]
BpBinder::BpBinder(int32_t handle, int32_t trackedUid) : mHandle(handle) , mAlive(1) , mObitsSent(0) , mObituaries(nullptr) , mTrackedUid(trackedUid) { ALOGV("Creating BpBinder %p handle %d\n", this, mHandle);
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
IPCThreadState::self()->incWeakHandle(handle, this);
} ```
这个构造函数很简单,接下来我们再看拿到了这个BpBInder对象之后又做了什么
4.3
经过BpBInder对象的构造,我们可以将之前代码简化
```cpp
gDefaultServiceManager = interface_cast
然后通过interface_cast将这个对象转化成IServiceManager,关于interface_cast,它是模板函数
[IInterface.h]
//模板函数
template
//宏定义如下 #define DECLARE_META_INTERFACE(INTERFACE) \ public: \ static const ::android::String16 descriptor; \ static ::android::sp asInterface( \ const ::android::sp<::android::IBinder>& obj); \ ...
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
...
::android::sp I##INTERFACE::asInterface( \
const ::android::sp<::android::IBinder>& obj) \
{ \
::android::sp intr; \
if (obj != nullptr) { \
intr = static_cast( \
obj->queryLocalInterface( \
I##INTERFACE::descriptor).get()); \
if (intr == nullptr) { \
intr = new Bp##INTERFACE(obj); \
} \
} \
return intr; \
}
```
然后通过两个宏定义DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE,就将它们关联起来了
```cpp [IServiceManager.h]
class IServiceManager : public IInterface { public: DECLARE_META_INTERFACE(ServiceManager) ... } ```
并且在IServiceManager.cpp
中,有一行IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager")
所以上述的interface_cast(new BpBInder(0));
最后其实是创建了一个BpServiceManager
4.3 BpServiceManager
接下来,我们看看这个创建过程发生了哪些事情,首先我们先看BpServiceManager的继承关系
首先是BpServiceManager的构造函数,它是IServiceManager.cpp的一个内部类
```cpp [IServiceManager.cpp]
class BpServiceManager : public BpInterface
然后是BpInterface,它是IInterface.h的一个内部类
```cpp [IInterface.h]
template
接下来是BpRefBase,它是Binder.cpp的一个内部类
```cpp [Binder.cpp]
BpRefBase::BpRefBase(const sp
通过 BpServiceManager -> BpInterface -> BpRefBase,最后将我们传入的一个BpBinder和一个mRemote关联了起来,到这里,我们的准备工作就算是完成了
五 IPCThreadState
5.1 服务的注册
在main_mediaserver.cpp的第三步MediaPlayerService::instantiate();
,就是服务的注册
```cpp [MediaPlayerService.cpp]
void MediaPlayerService::instantiate() { defaultServiceManager()->addService( String16("media.player"), new MediaPlayerService()); } ```
如果看过SystemServer的源码,就会发现里面有很多这样addService注册服务的逻辑,这里的defaultServiceManager在前面我们已经说了,它是一个BpServiceManager对象,它继承自IServiceManager,它的addService方法如下
```cpp [IServiceManager::BpServiceManager]
virtual status_t addService(const String16& name, const sp
这里我们看到了一个transact,这个方法我们以后会经常看见,它就是和Binder交互的重要函数
5.2 IPCThreadState的创建
刚才我们说到了Binder的具体交互函数transact,它是定义在BpBinder中的,接下来我们就看看BpBinder中的具体逻辑
``` [BpBinder.cpp]
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) { //关键点,IPCThreadState status_t status = IPCThreadState::self()->transact( mHandle, code, data, reply, flags); if (status == DEAD_OBJECT) mAlive = 0; return status; }
return DEAD_OBJECT;
} ```
这里我们看到了一个IPCThreadState,这个类也是Binder通信中非常重要的类,我们先看它的self方法
```cpp [IPCThreadState.cpp]
IPCThreadState IPCThreadState::self() { //第一次是false if (gHaveTLS) { restart: //在restart中创建IPCThreadState对象 const pthread_key_t k = gTLS; IPCThreadState st = (IPCThreadState*)pthread_getspecific(k); if (st) return st; return new IPCThreadState; }
//第一次是false
if (gShutdown) {
ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n");
return nullptr;
}
//线程锁
pthread_mutex_lock(&gTLSMutex);
if (!gHaveTLS) {
int key_create_value = pthread_key_create(&gTLS, threadDestructor);
if (key_create_value != 0) {
pthread_mutex_unlock(&gTLSMutex);
ALOGW("IPCThreadState::self() unable to create TLS key, expect a crash: %s\n",
strerror(key_create_value));
return nullptr;
}
gHaveTLS = true;
}
pthread_mutex_unlock(&gTLSMutex);
//跳转到restart
goto restart;
} ```
可以看出这个是一个和线程相关的单例,在同一个线程下它只有一个对象,接下来我们再看它的构造函数
```cpp [IPCThreadState.cpp]
IPCThreadState::IPCThreadState() : mProcess(ProcessState::self()), mWorkSource(kUnsetWorkSource), mPropagateWorkSource(false), mStrictModePolicy(0), mLastTransactionBinderFlags(0), mCallRestriction(mProcess->mCallRestriction) { //和线程相关联 pthread_setspecific(gTLS, this); clearCaller(); //和Binder驱动交互的两个缓冲区 mIn.setDataCapacity(256); mOut.setDataCapacity(256); mIPCThreadStateBase = IPCThreadStateBase::self(); } ```
然后在构造函数中,初始化了两个缓冲区mIn和mOut,这个mIn是从Binder设备读数据的,而mOut则是向Binder设备写数据的
5.3 transact
接下来我们就要看最关键的transact
```cpp [IPCThreadState.cpp]
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
...
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, nullptr);
...
if ((flags & TF_ONE_WAY) == 0) {
...
if (reply) {
err = waitForResponse(reply);
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
...
} else {
err = waitForResponse(nullptr, nullptr);
}
return err;
}
```
transact中的逻辑非常长,并且里面还有很多判断,不过这里不论是哪个分支,都会调用到两个方法,分别是writeTransactionData和waitForResponse,接下来我们就看看这个waitForResponse里面具体做了什么事
5.4 writeTransactionData
```cpp [IPCThreadState.cpp]
status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags, int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer) { binder_transaction_data tr;
tr.target.ptr = 0;
tr.target.handle = handle;
tr.code = code;
tr.flags = binderFlags;
tr.cookie = 0;
tr.sender_pid = 0;
tr.sender_euid = 0;
//将数据用tr进行封装
...
//将数据写到mOut
mOut.writeInt32(cmd);
mOut.write(&tr, sizeof(tr));
return NO_ERROR;
} ```
显然,writeTransactionData主要的作用就是将要传递的参数写到mOut中去
5.5 waitForResponse
```cpp [IPCThreadState.cpp]
status_t IPCThreadState::waitForResponse(Parcel reply, status_t acquireResult) { uint32_t cmd; int32_t err;
while (1) {
if ((err=talkWithDriver()) < NO_ERROR) break;
...
//从Binder中读出数据
cmd = (uint32_t)mIn.readInt32();
//死循环加上switch,说明一次Binder交互会读出多次数据
switch (cmd) {
...
default:
//执行拿到的cmd
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; }
return err;
} ```
在waitForResponse中,会不断的从mIn中读出数据,然后根据这个读出的数据,执行不同的逻辑
六 总结
到此,我们基本知道了,MediaServer在使用Binder时,是如何注册的,不过对于IPCThreadState的细节,本篇还没完全说明白,关于后续的部分在下一篇说明
- Activity启动源码解析(Android12)
- 从MediaServer看Binder的使用方式(一)
- 从MediaServer看Binder的使用方式(二)
- [Android禅修之路] 解读Layer
- [Android禅修之路] Android图形系统,从Activity到Surface
- [Android禅修之路] 解读 GraphicBuffer 之 Framework 层
- [Android禅修之路] 解读SurfaceFlinger中的BufferQueue
- [Android禅修之路] SurfaceFlinger 合成中的工作
- [Android禅修之路] SurfaceFlinger 中的一些对象
- [Android禅修之路] SurfaceFlinger 合成前的预处理
- [Android禅修之路] SurfaceFlinger合成总览
- [Android禅修之路] SurfaceFlinger的启动过程
- [Android禅修之路] Android 图形系统开篇