本文基于Android 10.0源码分析
1.摘要
本节主要来讲解Android10.0 Binder的Native层实例流程。
2.概述
在上一节中,我们知道了ServiceManager的启动过程,注册、获取服务的细节处理。服务的信息都存在于一个全局变量svclist的链表中。svclist对应的结构为svcinfo,其中有两个成员很重要:handle和name,handle代表了service的句柄,我们也可以理解为service的实体, name为service的名称。
那么这个service的Binder句柄handle是怎么来的?在Native层,我们是如何进行注册、获取服务的,还不清楚。这一节,我们用一个Native层的实例来进行分析。遵循了不少网络大神的路线,也通过media的服务来进行分析。media的Binder服务注册,是一个很典型的Binder服务注册流程。
3.Native层的Binder架构
(1)服务端存在一个Binder实体--BBinder,以及对应的实体接口--BnInterface;
(2)客户端存在一个Binder代理--BpBinder,以及对应的代理接口--BpInterface;
(3)服务端通过Binder驱动向ServiceManager进行注册,把BBinder的实体对象存入ServiceManager,对应svcinfo的handle;
(4)客户端通过Binder驱动向ServiceManager发起查询请求,获取到service的Binder句柄--handle,进行一层转换变成BpBinder;
(5)客户端拿到了服务的代理后,就可以调用服务的代理接口来实现相应的功能。
![](https://img.haomeiwen.com/i18565088/de599bac32adeb8e.png)
4.看源码前的思考
假如是你,该如何来注册、获取一个服务?
按照我们正常的设计方法,服务注册该走下面几步:
(1)定义一个服务的名字;
(2)生成一个服务本身的实体BBinder;
(3)通过ServiceManager的代理接口,调用addService()这种接口实现服务注册,传入“服务名称”和“服务对象实体”,用来和ServiceManager的name-handle进行对应;
(4)开启一个线程池,把当前的线程加入线程池,方便管理,防止主线程的阻塞
服务获取该走下面几步:
(1)获取ServiceManager的代理对象,用于和ServiceManager进行通信;
(2)通过ServiceManager的代理接口,调用getService()这种接口来获取指向服务实体的代理接口;
(3)客户端通过调用已得到的service代理的成员函数,把自己的binder实体作为参数,传递到目标service进程;
(4)获得合法的服务代理对象。
5.概念理解
在真正看代码前,需要先了解两个类:ProcessState和IPCThreadState这两个很重要类的概念。
5.1 ProcessState
ProcessState从字面意思可以理解,表示是“进程状态”,代表了这个进程的行为,Android中,每个进程都是独立的,所以每个进程都要有一个“进程状态”--ProcessState。
在Binder通信机制中,ProcessState使用了单例模式,即一个进程只有个ProcessState对象,一个进程中有很多个线程,不能每个线程都来new一个新的ProcessState(),采用单例模式后,每个线程都可以使用同一个ProcessState来和Binder驱动通信。
ProcessState作为进程状态的记录器,主要用来打开Binder驱动获取句柄,mmap申请一块(1M-8K)的内存空间,设置Binder线程最大个数。
5.2 IPCThreadState
IPCThreadState从字面意思可以理解,表示是“进程间通信的线程状态”,有了进程状态后,自然需要有线程状态。
ProcessState代表了进程,IPCThreadState代表了线程。Android系统中有很多进程,进程间相互隔离,每个进程内部又有很多线程,线程之间也是相互独立的。所以说一个进程会存在很多个线程,每个线程都有自己的“线程状态”--IPCThreadState对象。这个对象存储在线程的本地存储区(TLS:Thread local storage)中,每个线程都拥有自己的TLS,并且是私有空间,线程之间不会共享。
IPCThreadState对象根据key:gTLS去进行存储。通过pthread_getspecific/pthread_setspecific函数可以获取/设置这些空间中的内容。
IPCThreadState负责与Binder驱动进行数据交互。
![](https://img.haomeiwen.com/i18565088/5dfa9261228a11a4.png)
5.3 BpBinder
BpBinder展开后就是Binder Proxy,也就是Binder代理的含义。BpBinder是客户端用来与服务交互的代理类,负责实现跨进程传输的传输机制,不关心具体的传输内容。通信功能由其它类和函数实现,但由于这些类和函数被BpBinder代理,所以客户端需要通过BpBinder来发送Binder通信数据。
5.4 BBinder
BBinder代表服务端,可以理解为服务的Binder实体,当服务端从Binder驱动中读取到数据后,由BBinder类进行处理。
6.Media的服务注册
![](https://img.haomeiwen.com/i18565088/3f518d5509390ea0.png)
6.1 main()
// frameworks/av/media/mediaserver/main_mediaserver.cpp
int main(int argc __unused, char **argv __unused)
{
signal(SIGPIPE, SIG_IGN);
sp<ProcessState> proc(ProcessState::self()); //获得ProcessState实例对象
sp<IServiceManager> sm(defaultServiceManager()); //获取BpServiceManager对象
ALOGI("ServiceManager: %p", sm.get());
AIcu_initializeIcuOrDie();
MediaPlayerService::instantiate(); //注册多媒体服务
ResourceManagerService::instantiate();
registerExtensions();
ProcessState::self()->startThreadPool(); //启动Binder线程池
IPCThreadState::self()->joinThreadPool(); //当前线程加入到线程池
}
media的服务注册流程分为以下几步:
(1)获得ProcessState实例对象;
(2)获取ServiceManager的代理对象--BpServiceManager;
(3)注册media服务;
(4)启动Binder线程池;
(5)把当前线程加入到线程池。
6.2 ProcessState::self()
前面我们已经知道了ProcessState代表了进程状态,一个进程只有一个ProcessState对象。ProcessState采用了单例的模式保存了一个ProcessState全局对象--gProcess,供每个线程使用。
从下面的文件可以猜到ProcessState.cpp 存在于一个so库中,即libbinder.so,service进程调用libbinder.so进行Binder通信。
// frameworks/native/libs/binder/ProcessState.cpp
#ifdef __ANDROID_VNDK__
const char* kDefaultDriver = "/dev/vndbinder";
#else
const char* kDefaultDriver = "/dev/binder";
#endif
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
//ProcessState的实例存在,直接返回该实例对象--单例模式
if (gProcess != nullptr) {
return gProcess;
}
//实例化ProcessState,kDefaultDriver 根据VNDK的宏定义来决定当前进程使用"/dev/binder" 还是"/dev/vndbinder"
gProcess = new ProcessState(kDefaultDriver);
return gProcess;
}
//--------------------------------------------
ProcessState::ProcessState(const char *driver)
: mDriverName(String8(driver))
, mDriverFD(open_driver(driver)) //打开驱动,根据VNDK的宏定义来决定当前进程使用"/dev/binder" 还是"/dev/vndbinder",假设为"/dev/binder"
, mVMStart(MAP_FAILED)
, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
, mExecutingThreadsCount(0)
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS) //Binder线程的最大个数16
, mStarvationStartTimeMs(0)
, mManagesContexts(false)
, mBinderContextCheckFunc(nullptr)
, mBinderContextUserData(nullptr)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
, mCallRestriction(CallRestriction::NONE)
{
if (mDriverFD >= 0) {
// 向Binder驱动申请一块(1M-8K)的虚拟地址空间来接收事务。
mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
// *sigh*
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.");
}
ProcessState的对象创建也比较简单,根据VNDK的宏定义来决定当前进程使用"/dev/binder" 还是"/dev/vndbinder"来打开了binder驱动,这里假设为"/dev/binder"。向Binder驱动申请一块(1M-8K)的虚拟地址空间来接收事务。(1M-8K)在前面的入门篇已经讲解原因,这里不重复说明。变量说明:
- mDriverFD:Binder驱动打开后,记录的句柄,用于访问Binder设备;
- mMaxThreads:最大Binder线程个数;
- BINDER_VM_SIZE:((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2),其中_SC_PAGE_SIZE为4K,即一个物理页的大小为4K,最终为(1M-8K)。
6.3 获取ServiceManager代理对象
defaultServiceManager()
当服务进程获取到了ProcessState对象后,接下来要拿到ServiceManager的代理对象--BpServiceManager。
// frameworks/native/libs/binder/IServiceManager.cpp
sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager != nullptr) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
//当ServiceManager还未准备好,等待1秒后重新获取ServiceManager对象
while (gDefaultServiceManager == nullptr) {
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(nullptr));
if (gDefaultServiceManager == nullptr)
sleep(1);
}
}
return gDefaultServiceManager;
}
ServiceManager的对象获取也采用了一个单例模式,一个进程中只要获取一次即可,对象存储在gDefaultServiceManager中。主要流程如下:
(1)获取ProcessState对象---ProcessState::self(),在上面的流程中可知ProcessState已获取,存入了全局变量中;
(2)获取BpBinder对象---ProcessState::getContextObject(nullptr);
(3)获取BpServiceManager对象---interface_cast<IServiceManager>。
6.3.1 ProcessState::getContextObject()
getContextObject()调用getStrongProxyForHandle()进行处理,传入handle=0,在前面ServiceManager那一节我们知道,系统中约定了ServiceManager的handle=0。
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
return getStrongProxyForHandle(0);
}
//---------------------------------------------------
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
//查找handle对应的资源项
handle_entry* e = lookupHandleLocked(handle);
if (e != nullptr) {
IBinder* b = e->binder;
if (b == nullptr || !e->refs->attemptIncWeak(this)) {
if (handle == 0) {
Parcel data;
//通过ping操作测试binder是否准备就绪
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, nullptr, 0);
if (status == DEAD_OBJECT)
return nullptr;
}
//当handle值所对应的IBinder不存在或弱引用无效时,创建一个BpBinder,handle=0
//create的实现其实就是new BpBinder(0,trackedUid)
b = BpBinder::create(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
getStrongProxyForHandle()的过程也很简单,当handle=0所对应的IBinder不存在或弱引用无效时,先看下Binder是否已经准备就绪,即ServiceManager是否已经就绪,准备好后,创建一个BpBinder(0,trackedUid),创建BpBinder对象中会将handle相对应Binder的弱引用增加1,最终返回一个BpBiner的对象。
即当Service向ServiceManager进行注册时,Service变成了Client,ServiceManager变成了Server,需要先把Service 转换成一个BpBinder对象,作为Binder代理进行通信。所以 ProcessState::getContextObject() 就相当于 new BpBinder(0,trackedUid)
6.3.2 interface_cast<IServiceManager>
真正获取ServiceManager的代理对象的是interface_cast<IServiceManager>方法。
// frameworks/native/libs/binder/include/binder/IInterface.h
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj); // 这里INTERFACE对应为IServiceManager
}
这里采用了C++的模板函数,interface_cast<IServiceManager>其实就是调用了IServiceManager::asInterface(obj); 这里的obj 就是new BpBinder(0)。但是IServiceManager中没有看到asInterface()的实现,我们就在IInterface.h进行查找,找到了asInterface()实现,分别在申明DECLARE_META_INTERFACE和实现IMPLEMENT_META_INTERFACE中。
// frameworks/native/libs/binder/include/binder/IInterface.h
#define DECLARE_META_INTERFACE(INTERFACE) \
public: \
static const ::android::String16 descriptor; \
static ::android::sp<I##INTERFACE> asInterface( \
const ::android::sp<::android::IBinder>& obj); \
virtual const ::android::String16& getInterfaceDescriptor() const; \
I##INTERFACE(); \
virtual ~I##INTERFACE(); \
static bool setDefaultImpl(std::unique_ptr<I##INTERFACE> impl); \
static const std::unique_ptr<I##INTERFACE>& getDefaultImpl(); \
private: \
static std::unique_ptr<I##INTERFACE> default_impl; \
public: \
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
const ::android::String16 I##INTERFACE::descriptor(NAME); \
const ::android::String16& \
I##INTERFACE::getInterfaceDescriptor() const { \
return I##INTERFACE::descriptor; \
} \
::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; \
} \
std::unique_ptr<I##INTERFACE> I##INTERFACE::default_impl; \
bool I##INTERFACE::setDefaultImpl(std::unique_ptr<I##INTERFACE> impl)\
{ \
if (!I##INTERFACE::default_impl && impl) { \
I##INTERFACE::default_impl = std::move(impl); \
return true; \
} \
return false; \
} \
const std::unique_ptr<I##INTERFACE>& I##INTERFACE::getDefaultImpl() \
{ \
return I##INTERFACE::default_impl; \
} \
I##INTERFACE::I##INTERFACE() { } \
I##INTERFACE::~I##INTERFACE() { } \
#define CHECK_INTERFACE(interface, data, reply) \
do { \
if (!(data).checkInterface(this)) { return PERMISSION_DENIED; } \
} while (false)
IServiceManager中的使用方法:
DECLARE_META_INTERFACE(ServiceManager)
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
我这里就不进行展开了,有兴趣的可以尝试一下,最终IServiceManager::asInterface() 等价于new Bp##INTERFACE(obj),即 new BpServiceManager(obj)。所以:
gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(nullptr));
转换后变成:
gDefaultServiceManager = new BpServiceManager(new BpBinder(0,trackedUid));
BpServiceManager()的继承有必要展开下,方便后面的分析:
(1)class BpServiceManager : public BpInterface<IServiceManager>
(2)class BpInterface : public INTERFACE, public BpRefBase
(3)class BpRefBase : public virtual RefBase
下面的mRemote(o.get()) ,其实就是拿到传入的obj,即为new BpBinder(0,trackedUid)
BpRefBase::BpRefBase(const sp<IBinder>& o)
: mRemote(o.get()), mRefs(nullptr), mState(0)
{
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
if (mRemote) {
mRemote->incStrong(this); // Removed on first IncStrong().
mRefs = mRemote->createWeak(this); // Held for our entire lifetime.
}
}
6.4 MediaPlayerService::instantiate()
//frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
void MediaPlayerService::instantiate() {
defaultServiceManager()->addService(
String16("media.player"), new MediaPlayerService());
}
defaultServiceManager()->addService()等价调用BpServiceManager::addService(),其中service的name是“media.player”,service的对象是“new MediaPlayerService()”。
MediaPlayerService继承自BnMediaPlayerService,BnMediaPlayerService继承自BnInterface,BnInterface继承自BBinder,最终转换为一个Binder实体--BBinder对象。
类的继承关系如下:
![](https://img.haomeiwen.com/i18565088/01bf609b89d72e29.png)
继续往下看BpServiceManager::addService()是如何工作的:
// frameworks/native/libs/binder/IServiceManager.cpp
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated, int dumpsysPriority) {
Parcel data, reply;//定义data和reply的Parcel数据包
//写入RPC头信息"android.os.IServiceManager"
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);//服务名为 "media.player"
data.writeStrongBinder(service);//把一个binder实体“打扁”并写入parcel, 服务的实体对象:new MediaPlayerService()
data.writeInt32(allowIsolated ? 1 : 0);//allowIsolated= false
data.writeInt32(dumpsysPriority);//dumpsysFlags = DUMP_FLAG_PRIORITY_DEFAULT
//remote()函数返回的是mRemote,就是BpRefBase中的mRemote,即BpBinder对象。这里调用了BpBinder的transact()方法
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
主要流程:
(1)准备两个Parcel结构:data,reply;
(2)组装Parcel数据;
(3)写入头信息:android.os.IServiceManager;
(4)写入服务名:media.player;
(5)写入服务的实体对象:new MediaPlayerService();
(6)调用remote的transact,发送ADD_SERVICE_TRANSACTION的命令进行服务的注册;
(7)得到返回的reply数据。
最核心的就是 remote()->transact(ADD_SERVICE_TRANSACTION, XXX),这里的remote()函数返回的是mRemote,在上面我们理解到mRemote其实就是new BpBinder(0,trackedUid),最终转换为BpBinder->transact(ADD_SERVICE_TRANSACTION, XXX)。
上面有一个要注意的地方data.writeStrongBinder(service); 最终调用的是flatten_binder(),目的是把一个Binder实体“压扁”并写入Parcel。这里"压扁"的含义,其实就是把Binder对象整理成flat_binder_object变量。如果压扁的是Binder实体,那么flat_binder_object用cookie域记录binder实体的指针,即BBinder指针,而如果打扁的是Binder代理,那么flat_binder_object用handle域记录的binder代理的句柄值。
// frameworks/native/libs/binder/Parcel.cpp
status_t flatten_binder(const sp<ProcessState>& /*proc*/,
const sp<IBinder>& binder, Parcel* out)
{
flat_binder_object obj;
if (IPCThreadState::self()->backgroundSchedulingDisabled()) {
/* minimum priority for all nodes is nice 0 */
obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;
} else {
/* minimum priority for all nodes is MAX_NICE(19) */
obj.flags = 0x13 | FLAT_BINDER_FLAG_ACCEPTS_FDS;
}
if (binder != nullptr) {
BBinder *local = binder->localBinder(); //是否是Binder实体
if (!local) {
//是binder代理
BpBinder *proxy = binder->remoteBinder();
if (proxy == nullptr) {
ALOGE("null proxy");
}
const int32_t handle = proxy ? proxy->handle() : 0;//记录Binder代理的句柄
obj.hdr.type = BINDER_TYPE_HANDLE;
obj.binder = 0;
obj.handle = handle; // handle域记录句柄
obj.cookie = 0;
} else {
//是binder实体
if (local->isRequestingSid()) {
obj.flags |= FLAT_BINDER_FLAG_TXN_SECURITY_CTX;
}
obj.hdr.type = BINDER_TYPE_BINDER;
obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
obj.cookie = reinterpret_cast<uintptr_t>(local); //cookie记录Binder实体的指针
}
} else {
obj.hdr.type = BINDER_TYPE_BINDER;
obj.binder = 0;
obj.cookie = 0;
}
return finish_flatten_binder(binder, obj, out);
}
接着flatten_binder()调用了一个关键的finish_flatten_binder()函数。这个函数内部会记录下刚刚被扁平化的flat_binder_object在parcel中的位置。说得更详细点儿就是,parcel对象内部会有一个buffer,记录着parcel中所有扁平化的数据,有些扁平数据是普通数据,而另一些扁平数据则记录着binder对象。所以parcel中会构造另一个mObjects数组,专门记录那些binder扁平数据所在的位置,示意图如下:
![](https://img.haomeiwen.com/i18565088/c823d5c994870af7.png)
接下来看看传输过程BpBinder->transact(ADD_SERVICE_TRANSACTION,XXX)。
6.4.1 BpBinder::transact()
// frameworks/native/libs/binder/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) {
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}
return DEAD_OBJECT;
}
BpBinder::transact()就是调用IPCThreadState::self()->transact() 进行处理。
6.4.2 IPCThreadState::transact()
// frameworks/native/libs/binder/IPCThreadState.cpp
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
status_t err;
flags |= TF_ACCEPT_FDS;
...
// 传输数据
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, nullptr);
if (err != NO_ERROR) {
if (reply) reply->setError(err);
return (mLastError = err);
}
if ((flags & TF_ONE_WAY) == 0) {
if (UNLIKELY(mCallRestriction != ProcessState::CallRestriction::NONE)) {
if (mCallRestriction == ProcessState::CallRestriction::ERROR_IF_NOT_ONEWAY) {
ALOGE("Process making non-oneway call but is restricted.");
CallStack::logStack("non-oneway call", CallStack::getCurrent(10).get(),
ANDROID_LOG_ERROR);
} else /* FATAL_IF_NOT_ONEWAY */ {
LOG_ALWAYS_FATAL("Process may not make oneway calls.");
}
}
//等待响应
if (reply) {
err = waitForResponse(reply);
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
...
} else {
//oneway,则不需要等待reply的场景
err = waitForResponse(nullptr, nullptr);
}
return err;
}
writeTransactionData代码如下:
// frameworks/native/libs/binder/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; //申请一个binder_transaction_data的结构
tr.target.ptr = 0; /* Don't pass uninitialized stack data to a remote process */
tr.target.handle = handle;
tr.code = code;
tr.flags = binderFlags;
tr.cookie = 0;
tr.sender_pid = 0;
tr.sender_euid = 0;
const status_t err = data.errorCheck(); //错误检查
if (err == NO_ERROR) {
// 把Parcel的数据转换到binder_transaction_data中
tr.data_size = data.ipcDataSize();
// 这部分是待传递数据
tr.data.ptr.buffer = data.ipcData();
// 这部分是扁平化的binder对象在数据中的具体位置
tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_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 = reinterpret_cast<uintptr_t>(statusBuffer);
tr.offsets_size = 0;
tr.data.ptr.offsets = 0;
} else {
return (mLastError = err);
}
mOut.writeInt32(cmd);
mOut.write(&tr, sizeof(tr));
return NO_ERROR;
}
writeTransactionData()主要就是把传入的Parcel数据,转换成binder_transaction_data,写入mOut,用来与Binder驱动交互。其中tr.data.ptr.buffer记录了Parcel传输的数据,tr.data.ptr.offsets记录下“待传数据”中所有binder对象的具体位置,如下图所示:
![](https://img.haomeiwen.com/i18565088/2267e52f728d5489.png)
当binder_transaction_data传递到binder驱动层后,驱动层可以准确地分析出数据中到底有多少binder对象,并分别进行处理,从而产生出合适的红黑树节点(Binder驱动层再分析,这里了解即可)。
此时,如果产生的红黑树节点是binder_node的话,binder_node的cookie域会被赋值成flat_binder_object所携带的cookie值,也就是用户态的BBinder地址值。
这个新生成的binder_node节点被插入红黑树后,会一直严阵以待,以后当它成为另外某次传输动作的目标节点时,它的cookie域就派上用场了,此时cookie值会被反映到用户态,于是用户态就拿到了BBinder对象。
waitForResponse()先调用talkWithDriver()把mOut的数据发给Binder驱动,Binder驱动再和ServiceManager进行交互,进行服务注册,然后ServiceManager解析完成后,调用binder_send_reply()把返回的数据发送出来,其中的cmd为BR_XXX 响应码,请求的数据存入到IPCThreadState mIn的Parcel结构中.
waitForResponse()根据 Binder驱动发来的BR_XXX请求码,进行相应的处理。mOut里面的BC_XXX请求码为BC_TRANSACTION, 根据Binder驱动中的交互流程,会先发一个 BR_TRANSACTION_COMPLETE响应码,目标进程收到事务后,处理BR_TRANSACTION事务,然后发送给当前进程,再执行BR_REPLY命令。
waitForResponse()里面是一个while(1)循环,可以处理多个命令,只有进入goto finish后,循环才退出。协议码转换的流程,到下一节的Binder 驱动一节进行详细分析,这里只要了解一个大概即可,不要陷入死胡同。
// frameworks/native/libs/binder/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;
...
cmd = (uint32_t)mIn.readInt32();
switch (cmd) {
case BR_TRANSACTION_COMPLETE: ...
break;
case BR_DEAD_REPLY: ...
goto finish;
case BR_FAILED_REPLY: ...
goto finish;
case BR_ACQUIRE_RESULT: ...
goto finish;
case BR_REPLY: ...
goto finish;
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;
}
...
return err;
}
talkWithDriver()用来不停的和Binder驱动进行通信,ioctl()函数在传递BINDER_WRITE_READ语义时,既会使用“输入buffer”,也会使用“输出buffer”,所以IPCThreadState专门搞了两个Parcel类型的成员变量:mIn和mOut。mOut中的内容发出去,发送后的回复写进mIn。
BINDER_WRITE_READ的命令发给Binder驱动后,ServiceManager有个循环不停的解析Binder驱动的BINDER_WRITE_READ信息,调用binder_parse()进行解析,我们前面addService()时,传入的code为ADD_SERVICE_TRANSACTION,在ServiceManager中解析后,对应的值为SVC_MGR_ADD_SERVICE,最终把服务的name和handle(对象) 存入到svclist中,ServiceManager再通过binder_send_reply()把返回的数据发送出来,在talkWithDriver()中填入mIn中,waitForResponse()进行最终的语义处理,发送出去。
// frameworks/native/libs/binder/IPCThreadState.cpp
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
if (mProcess->mDriverFD <= 0) {
return -EBADF;
}
binder_write_read bwr;
...
//如果仍在读取输入缓冲区中剩余的数据,并且调用方已请求读取下一个数据,则不希望写入任何内容。
const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
bwr.write_size = outAvail;
bwr.write_buffer = (uintptr_t)mOut.data(); //把mOut的数据存入write_buffer中,
// This is what we'll read.
if (doReceive && needRead) {
//接收数据缓冲区信息的填充。如果以后收到数据,就直接填在mIn中了
bwr.read_size = mIn.dataCapacity();
bwr.read_buffer = (uintptr_t)mIn.data();
} else {
//没有收到数据时,把read置空,binder只进行write处理
bwr.read_size = 0;
bwr.read_buffer = 0;
}
...
//当读缓冲和写缓冲都为空,则直接返回
if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;
bwr.write_consumed = 0;
bwr.read_consumed = 0;
status_t err;
do {
...
#if defined(__ANDROID__)
//通过ioctl不停的读写操作,跟Binder Driver进行通信
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
err = NO_ERROR;
else
err = -errno;
#else
err = INVALID_OPERATION;
#endif
if (mProcess->mDriverFD <= 0) {
err = -EBADF;
}
...
} while (err == -EINTR);//当被中断,则继续执行
if (err >= NO_ERROR) {
if (bwr.write_consumed > 0) {
if (bwr.write_consumed < mOut.dataSize())
mOut.remove(0, bwr.write_consumed);
else {
mOut.setDataSize(0);
processPostWriteDerefs();
}
}
if (bwr.read_consumed > 0) {
mIn.setDataSize(bwr.read_consumed);
mIn.setDataPosition(0);
}
...
return NO_ERROR;
}
return err;
}
mIn和mOut的data会先整理进一个binder_write_read结构,然后再传给ioctl()函数。此时使用的文件描述符就是前文我们说的ProcessState中记录的mDriverFD,说明是向binder驱动传递语义。BINDER_WRITE_READ表示我们希望读写一些数据。这样就完成了BpBinder向远端--ServiceManager发起的传输流程。
waitForResponse()收到BR_TRANSACTION响应码后,调用BBinder的transact()进行处理。
// frameworks/native/libs/binder/IPCThreadState.cpp
status_t IPCThreadState::executeCommand(int32_t cmd)
{
...
case BR_TRANSACTION:
if (tr.target.ptr) {
if (reinterpret_cast<RefBase::weakref_type*>(
tr.target.ptr)->attemptIncStrong(this)) {
//这里的cookie就是驱动层binder_node节点的cookie发挥作用,
//拿到了一个合法的BBinder
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);
}
...
}
BBinder->transact() 中最重要的就是onTransact(),binder实体在本质上都是继承于BBinder的,而且我们一般都会重载onTransact()函数,所以上面这句onTransact()实际上调用的是具体binder实体的onTransact()成员函数。
// frameworks/native/libs/binder/Binder.cpp
status_t BBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
data.setDataPosition(0);
status_t err = NO_ERROR;
switch (code) {
case PING_TRANSACTION:
reply->writeInt32(pingBinder());
break;
default:
err = onTransact(code, data, reply, flags);
break;
}
if (reply != nullptr) {
reply->setDataPosition(0);
}
return err;
}
MediaPlayerService继承自BnMediaPlayerService,最终继承自BBinder,上面执行onTransact时,其实对应的BBinder实体,也会执行该函数,就进入了BnMediaPlayerService::onTransact。
status_t BnMediaPlayerService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
....
}
注册服务的流程简单的总结一下:
(1)服务进程先获得一个 ProcessState()的对象;
(2)获取ServiceManager的代理对象BpServiceManager,主要通过new BpBinder(0,xxx)得到;
(3)调用BpServiceManager的addService,组装一个Parce数据,传入服务名称、服务实体对象--BBinder、执行code-ADD_SERVICE_TRANSACTION;
(4)先通过IPCThreadThread的writeTransactionData()把上面的Parcel数据写入mOut,用来进行发送;
(5)通过IPCThreadThread的talkWithDriver()与Binder驱动通信,传递语义BINDER_WRITE_READ;
(6)ServiceManager有个循环不停的解析Binder驱动的BINDER_WRITE_READ信息,调用binder_parse()进行解;
(7)ServiceManager中解析后,ADD_SERVICE_TRANSACTION对应的值为SVC_MGR_ADD_SERVICE,最终把服务的name和handle存入到svclist中,ServiceManager再通过binder_send_reply()把返回的数据发送出来,在talkWithDriver()中填入mIn中,waitForResponse()进行最终的语义处理;
(8)waitForResponse()收到BR_TRANSACTION响应码后,最终后调用executeCommand()进行命令执行,根据逻辑处理,最终会调用到Binder实体的onTransact(),例如这里的BnMediaPlayerService::onTransact();
(9)最终完成服务的注册流程。
7.获取media的服务
在第6节中,我们了解了media服务的注册流程,接下来我们一起看看,其他进程是如何获取media的服务来进行通信。
在ServiceManager一节,我们知道了注册、获取服务我们都要通过ServiceManager进行处理,所以获取服务,大体还是分为下面几步:
(1)获取ServiceManager的代理对象BpServiceManager,用于和ServiceManager进行通信;
(2)通过ServiceManager的代理接口,调用getService()这种接口来获取指向服务实体的代理接口;
(3)客户端通过调用已得到的service代理的成员函数,把自己的binder实体作为参数,传递到目标service进程获得合法的服务代理对象。
获取media服务序列图:
![](https://img.haomeiwen.com/i18565088/dd12d5379fae077e.png)
7.1 IMediaDeathNotifier::getMediaPlayerService()
// frameworks/av/media/libmedia/IMediaDeathNotifier.cpp
IMediaDeathNotifier::getMediaPlayerService()
{
ALOGV("getMediaPlayerService");
Mutex::Autolock _l(sServiceLock);
if (sMediaPlayerService == 0) {
//获取ServiceManager的代理对象BpServiceManager
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder;
do {
//调用BpServiceManager的getService接口,来获取服务名称为“media.player”的Binder服务对象
binder = sm->getService(String16("media.player"));
if (binder != 0) {
break;
}
ALOGW("Media player service not published, waiting...");
usleep(500000); // 如果media的服务还没有准备好,休眠0.5秒进行等待
} while (true);
if (sDeathNotifier == NULL) {
sDeathNotifier = new DeathNotifier(); //创建死亡通知对象
}
binder->linkToDeath(sDeathNotifier);//将死亡通知连接到binder
// 转换得到服务对象
sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
}
ALOGE_IF(sMediaPlayerService == 0, "no media player service!?");
return sMediaPlayerService;
}
流程如下:
(1)获取ServiceManager的代理对象BpServiceManager;
(2)调用BpServiceManager的getService接口,来获取服务名称为“media.player”的Binder 服务对象;
(3)创建死亡通知对象;
(4)将死亡通知连接到binder;
(5)得到服务对象。
通过defaultServiceManager()来获取ServiceManager的对象,我们接下来主要来看getService的流程。
7.2 BpServiceManager::getService()
// frameworks/native/libs/binder/IServiceManager.cpp
// defaultServiceManager->getService()其实就是BpServiceManager->getService。
virtual sp<IBinder> getService(const String16& name) const
{
//检索指定服务是否存在
sp<IBinder> svc = checkService(name);
if (svc != nullptr) return svc;
//如果ProcessState和Binder驱动交互的是"/dev/vndbinder",那么isVendorService为True,表明Vendor进程之间可以进行Binder通信
const bool isVendorService =
strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder") == 0;
const long timeout = uptimeMillis() + 5000;
if (!gSystemBootCompleted && !isVendorService) {
//vendor分区的代码不能访问system的属性
char bootCompleted[PROPERTY_VALUE_MAX];
property_get("sys.boot_completed", bootCompleted, "0");
gSystemBootCompleted = strcmp(bootCompleted, "1") == 0 ? true : false;
}
//vendor分区的服务sleepTime 为100ms, system为1000ms
const long sleepTime = gSystemBootCompleted ? 1000 : 100;
int n = 0;
while (uptimeMillis() < timeout) {
n++;
ALOGI("Waiting for service '%s' on '%s'...", String8(name).string(),
ProcessState::self()->getDriverName().c_str());
usleep(1000*sleepTime);
sp<IBinder> svc = checkService(name);
if (svc != nullptr) return svc;
}
ALOGW("Service %s didn't start. Returning NULL", String8(name).string());
return nullptr;
}
getService()的核心就是调用checkService()来检查服务是否存在,如果不存在,继续等待查找。注意:vendor分区的服务等待时间为100ms,system分区的为1000ms.
7.3 BpServiceManager::checkService()
checkService()和前面的addService类似,都是组织一个Parcel结构,然后调用BpBinder的transact()方法,把服务信息和传输code--CHECK_SERVICE_TRANSACTION发给Binder驱动。
// frameworks/native/libs/binder/IServiceManager.cpp#checkService
virtual sp<IBinder> checkService( const String16& name) const
{
Parcel data, reply;
//写入RPC头信息"android.os.IServiceManager"
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name); //写入服务的名称
//remote()函数返回的是mRemote,就是BpRefBase中的mRemote,即BpBinder对象。这里调用了BpBinder的transact()方法
remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
return reply.readStrongBinder();
}
BpBinder的transact()的流程这里就不展开,上面addService()已经有了详细的说明。CHECK_SERVICE_TRANSACTION在ServiceManager中对应的是SVC_MGR_CHECK_SERVICE(),从svclist中,根据服务的name查到对应的handle,最终得到服务的对象。
和addService类似,ServiceManager查到对应的handle后,把handle存入reply,addService的reply没有数据getService的reply有数据,返回BR_REPLY相应码。
// frameworks/native/libs/binder/IPCThreadState.cpp
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
...
case BR_REPLY:
{
binder_transaction_data tr;
err = mIn.read(&tr, sizeof(tr));
ALOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY");
if (err != NO_ERROR) goto finish;
if (reply) {
if ((tr.flags & TF_STATUS_CODE) == 0) {
reply->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);
} else {
err = *reinterpret_cast<const status_t*>(tr.data.ptr.buffer);
freeBuffer(nullptr,
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), this);
}
} else {
freeBuffer(nullptr,
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), this);
continue;
}
}
goto finish;
...
}
7.4 Parcel::readStrongBinder()
checkservice()收到ServiceManager发来的reply后,调用readStrongBinder()来获取服务的对象。主要在unflatten_binder中,根据flat的type是handle还是实体,从而返回BpBinder对象或者BBinder实体。
// frameworks/native/libs/binder/Parcel.cpp
sp<IBinder> Parcel::readStrongBinder() const
{
sp<IBinder> val;
readNullableStrongBinder(&val);
return val;
}
//----------------------------
status_t Parcel::readNullableStrongBinder(sp<IBinder>* val) const
{
return unflatten_binder(ProcessState::self(), *this, val);
}
//----------------------------
status_t unflatten_binder(const sp<ProcessState>& proc,
const Parcel& in, sp<IBinder>* out)
{
const flat_binder_object* flat = in.readObject(false);
if (flat) {
switch (flat->hdr.type) {
case BINDER_TYPE_BINDER:
*out = reinterpret_cast<IBinder*>(flat->cookie);
return finish_unflatten_binder(nullptr, *flat, in); //返回BBinder实体
case BINDER_TYPE_HANDLE:
*out = proc->getStrongProxyForHandle(flat->handle);
return finish_unflatten_binder(
static_cast<BpBinder*>(out->get()), *flat, in); //返回BpBinder代理对象
}
}
return BAD_TYPE;
}
获取服务的流程简单的总结一下:
(1)客户端进程获取ServiceManager的代理对象BpServiceManager,主要通过new BpBinder(0,xxx)得到;
(2)调用BpServiceManager的getService,再到checkService(),然后组装一个Parce数据,传入服务名称、传输code-CHECK_SERVICE_TRANSACTION;
(3)先通过IPCThreadThread的writeTransactionData()把上面的Parcel数据写入mOut,用来进行发送;
(4)通过IPCThreadThread的talkWithDriver()与Binder驱动通信,传递语义BINDER_WRITE_READ;
(5)ServiceManager有个循环不停的解析Binder驱动的BINDER_WRITE_READ信息,调用binder_parse()进行解析;
(6)ServiceManager中解析后,CHECK_SERVICE_TRANSACTION对应的值为SVC_MGR_CHECK_SERVICE,从svclist中,根据服务的name查到对应的handle,ServiceManager再通过binder_send_reply()把返回的数据发送出来,在talkWithDriver()中填入mIn中,waitForResponse()进行最终的语义处理,发送出去。
注意:
-
当请求服务的进程与服务属于不同进程,则为请求服务所在进程创建binder_ref对象,指向服务进程中的binder_node,最终readStrongBinder()时,返回的是BpBinder对象;
-
当请求服务的进程与服务属于同一进程,则不再创建新对象,只是引用计数加1,并且修改type为BINDER_TYPE_BINDER或BINDER_TYPE_WEAK_BINDER。最终readStrongBinder()时,返回的是BBinder对象的真实子类。
8.协议码的转换流程及不同Android版本的变化
Binder通信协议是基于Command-Reply的方式的。
Android9.0之前的协议码流程:
![](https://img.haomeiwen.com/i18565088/f2b794e266644714.png)
Android9.0及之后的协议码流程:
上面第5步的BR_TRANSACTION_COMPLETE被延迟到第10步 ,Android做deferred_thread_work,延迟 TRANSACTION_COMPLETE,因此不会立即返回到用户空间;这允许目标进程立即开始处理此事务,从而减少延迟。然后,当目标回复(或出现错误)时,我们将返回TRANSACTION_COMPLETE。
![](https://img.haomeiwen.com/i18565088/9c0497501e199dc2.png)
注册服务的详细代码流程,kernel细节的代码这里就不贴了,后面在内核章节进行详细解析:
-
BpServiceManager::addService()时,调用writeStrongBinder(service),把服务对象写入BBinder,作为Binder实体,调用remote()->transact()处理,code:ADD_SERVICE_TRANSACTION,最终到IPCThreadState::transact();
-
IPCThreadState::transact()调用writeTransactionData(),组装CMD:BC_TRANSACTION进入 binder_transaction_data tr,tr写入mOut;
-
IPCThreadState::transact()再调用waitForRespose和Binder驱动进行交互,第一次mOut里面存的是BC_TRANSACTION及binder_transaction_data的值,mIn没有值;
-
talkWithDriver()中,此时,bwr.write_size >0 ; bwr.read_size = 0,调用ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)和binder驱动进行交互;
-
binder_ioctl()->binder_ioctl_write_read()先从用户空间读到上面的bwr的内容,根据此时的bwr.write_size >0 ; bwr.read_size = 0, 只进入binder_thread_write();
-
binder_thread_write()根据前面的CMD:BC_TRANSACTION从而进入binder_transaction();
-
binder_transaction()是个重要的流程,主要用来进行事务处理;首先创建一个binder_transaction结构的对象t,并插入到自己的binder_transaction堆栈中;
-
分配一块buffer:t->buffer,用于保存上面mOut中的data和mObjects 中的offset数据;
-
从data中解析出所有的binder实体并为其创建binder_node和binder_ref ,data解析的数据存在结构 flat_binder_object中;
-
transaction事务处理完成后,tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE, t->work.type = BINDER_WORK_TRANSACTION;
-
接下来,延迟TRANSACTION_COMPLETE,因此我们不会立即返回到用户空间,这允许目标进程立即开始处理此事务,从而减少延迟。然后,当目标(ServiceManager)回复reply(或出现错误)时,我们将返回TRANSACTION_COMPLETE。主要通过thread->process_todo = false;来促成;
-
binder_transaction()调用binder_proc_transaction() 将transaction发送到进程(ServiceManager)并将其唤醒,调用wake_up_interruptible()进行唤醒;
-
唤醒ServiceManager后,回到binder_ioctl_write_read(),调用copy_to_user(),把binder_write_read的数据传到用户空间;
-
ServiceManager的binder_loop()中,不同循环通过 ioctl(,BINDER_WRITE_READ,XXX)从用户空间获取数据, 此时bwr.write_size = 0,bwr.read_size> 0;
-
又进入进入到了Binder驱动,binder_ioctl()->binder_ioctl_write_read() ->binder_thread_read()
-
binder_thread_read()中,前面的 type=BINDER_WORK_TRANSACTION,且tr有数据,将会发送cmd:BR_TRANSACTION到ServiceManager, 调用copy_to_user()把数据发给用户空间ServiceManager;
-
ServiceManager的binder_parse()解析内核传来的binder_write_read数据,根据cmd:BR_TRANSACTION, 调用svcmgr_handler处理,code=SVC_MGR_ADD_SERVICE, 然后调用binder_send_reply() cmd_reply=BC_REPLY,cmd_free=BC_FREE_BUFFER, 发给Binder驱动,其中write_size > 0;
-
Binder驱动,binder_ioctl()->binder_ioctl_write_read()->binder_thread_write(),读取ServiceManager传来的数据,进入binder_transaction(),cmd=BC_REPLY,唤醒Client进程,把BR_TRANSACTION_COMPLETE分别发给ServiceManager 和Client进程;
-
IPCThreadState收到BR_TRANSACTION_COMPLETE后,把数据写入mIn,mOut移除内容,继续调用talkWithDriver(),向Binder驱动发起BINDER_WRITE_READ请求,此时mOut无值,mIn有内容;
-
Binder驱动进入binder_thread_read(),根据ServiceManager发来的reply数据,发送BR_REPLY给client;
-
IPCThreadState waitForResponse()收到BR_REPLY后,释放内存空间。
9.Media Client\Server交互流程
![](https://img.haomeiwen.com/i18565088/f1db86fb65abcd21.png)
10.代码路径
/frameworks/av/media/mediaserver/main_mediaserver.cpp
/frameworks/native/libs/binder/IServiceManager.cpp
/frameworks/native/libs/binder/ProcessState.cpp
/frameworks/native/libs/binder/IPCThreadState.cpp
/frameworks/native/libs/binder/BpBinder.cpp
/frameworks/native/libs/binder/Parcel.cpp
/frameworks/native/libs/binder/include/binder/IInterface.h
/frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
网友评论