摘要:本节主要来讲解Android10.0 Binder的Native层实例流程
阅读本文大约需要花费35分钟。
文章首发微信公众号:IngresGe
专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢!
[Android取经之路] 的源码都基于Android-Q(10.0) 进行分析
[Android取经之路] 系列文章:
《系统启动篇》
《日志系统篇》
《Binder通信原理》:
在上一节中,我们知道了ServiceManager的启动过程,注册、获取服务的细节处理。服务的信息都存在于一个全局变量svclist的链表中。
svclist对应的结构为svcinfo,其中有两个成员很重要:handle 和name,handle代表了service的句柄,我们也可以理解为service的实体, name为service的名称。
那么这个service的Binder句柄-handle是怎么来的?在Native层,我们是如何进行注册、获取服务的,还不清楚。
这一节,我们用一个Native层的实例来进行分析。
遵循了不少网络大神的路线,也通过media的服务来进行分析。media的Binder服务注册,是一个很典型的Binder服务注册流程。
服务端存在一个Binder实体--BBinder,以及对应的实体接口--BnInterface;
客户端存在一个Binder代理--BpBinder,以及对应的代理接口--BpInterface
服务端通过Binder驱动向ServiceManager进行注册,把BBinder的实体对象存入ServiceManager,对应svcinfo的handle;
客户端通过Binder驱动向ServiceManager发起查询请求,获取到service的Binder句柄--handle,进行一层转换变成BpBinder;
客户端拿到了服务的代理后,就可以调用服务的代理接口来实现相应的功能。
假如是你,该如何来注册、获取一个服务?
按照我们正常的设计方法,服务注册该走下面几步:
1)定义一个服务的名字
2)生成一个服务本身的实体BBinder
4)通过ServiceManager的代理接口,调用addService()这种接口实现服务注册,传入“服务名称”和“服务对象实体”,用来和ServiceManager的name-handle进行对应
5)开启一个线程池,把当前的线程加入线程池,方便管理,防止主线程的阻塞
服务获取该走下面几步:
1)获取ServiceManager的代理对象,用于和ServiceManager进行通信
2)通过ServiceManager的代理接口,调用getService()这种接口来获取指向服务实体的代理接口
3)客户端通过调用已得到的service代理的成员函数,把自己的binder实体作为参数,传递到目标service进程
4)获得合法的服务代理对象
在真正看代码前,需要先了解两个类-ProcessState和IPCThreadState 这两个很重要类的概念。
ProcessState从字面意思可以理解,表示是“进程状态”,代表了这个进程的行为,Android中,每个进程都是独立的,所以每个进程都要有一个“进程状态”--ProcessState.
在Binder通信机制中,ProcessState使用了单例模式,即一个进程只有个ProcessState对象,一个进程中有很多个线程,不能每个线程都来new一个新的ProcessState(),采用单例模式后,每个线程都可以使用同一个ProcessState来和Binder驱动通信。
ProcessState作为进程状态的记录器,主要用来打开Binder驱动获取句柄,mmap申请一块(1M-8K)的内存空间,设置Binder线程最大个数。
IPCThreadState从字面意思可以理解,表示是“进程间通信的线程状态”,有了进程状态后,自然需要有线程状态。
ProcessState代表了进程,IPCThreadState代表了线程。Android系统中有很多进程,进程间相互隔离,每个进程内部又有很多线程,线程之间也是相互独立的。所以说一个进程会存在很多个线程,每个线程都有自己的“线程状态”--IPCThreadState对象.这个对象存储在线程的本地存储区(TLS:Thread local storage)中,每个线程都拥有自己的TLS,并且是私有空间,线程之间不会共享。
IPCThreadState对象根据key:gTLS去进行存储。通过pthread_getspecific/pthread_setspecific函数可以获取/设置这些空间中的内容。
IPCThreadState负责与Binder驱动进行数据交互。
BpBinder 展开后就是Binder Proxy,也就是Binder代理的含义。BpBinder是客户端用来与服务交互的代理类,负责实现跨进程传输的传输机制,不关心具体的传输内容。通信功能由其它类和函数实现,但由于这些类和函数被BpBinder代理,所以客户端需要通过BpBinder来发送Binder通信数据。
BBinder代表服务端,可以理解为服务的Binder实体,当服务端从Binder驱动中读取到数据后,由BBinder类进行处理。
[/frameworks/av/media/mediaserver/main_mediaserver.cpp]
int main(int argc __unused, char **argv __unused)
{
signal(SIGPIPE, SIG_IGN);
sp proc(ProcessState::self()); //获得ProcessState实例对象
sp sm(defaultServiceManager()); //获取BpServiceManager对象
ALOGI("ServiceManager: %p", sm.get());
AIcu_initializeIcuOrDie();
MediaPlayerService::instantiate(); //注册多媒体服务
ResourceManagerService::instantiate();
registerExtensions();
ProcessState::self()->startThreadPool(); //启动Binder线程池
IPCThreadState::self()->joinThreadPool(); //当前线程加入到线程池
}
media的服务注册流程分为以下几步:
前面我们已经知道了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::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)
--defaultServiceManager()
当服务进程获取到了ProcessState对象后,接下来要拿到ServiceManager的代理对象--BpServiceManager。
[/frameworks/native/libs/binder/IServiceManager.cpp]
sp defaultServiceManager()
{
if (gDefaultServiceManager != nullptr) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
//当ServiceManager还未准备好,等待1秒后重新获取ServiceManager对象
while (gDefaultServiceManager == nullptr) {
gDefaultServiceManager = interface_cast(
ProcessState::self()->getContextObject(nullptr));
if (gDefaultServiceManager == nullptr)
sleep(1);
}
}
return gDefaultServiceManager;
}
ServiceManager的对象获取也采用了一个单例模式,一个进程中只要获取一次即可,对象存储在gDefaultServiceManager中。
主要流程如下:
getContextObject()调用getStrongProxyForHandle()进行处理,传入handle=0,在前面ServiceManager那一节我们知道,系统中约定了ServiceManager的handle=0
sp ProcessState::getContextObject(const sp& /*caller*/)
{
return getStrongProxyForHandle(0);
}
sp ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp 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)
真正获取ServiceManager的代理对象的是 interface_cast
[/frameworks/native/libs/binder/include/binder/IInterface.h]
template
inline sp interface_cast(const sp& obj)
{
return INTERFACE::asInterface(obj);
}
这里采用了C++的模板函数,interface_cast
但是IServiceManager中没有看到 asInterface()的实现,我们就在IInterface.h 进行查找,找到了asInterface()实现,分别在申明--DECLARE_META_INTERFACE和实现--IMPLEMENT_META_INTERFACE中
#define DECLARE_META_INTERFACE(INTERFACE) \
public: \
static const ::android::String16 descriptor; \
static ::android::sp asInterface( \
const ::android::sp<::android::IBinder>& obj); \
virtual const ::android::String16& getInterfaceDescriptor() const; \
I##INTERFACE(); \
virtual ~I##INTERFACE(); \
static bool setDefaultImpl(std::unique_ptr impl); \
static const std::unique_ptr& getDefaultImpl(); \
private: \
static std::unique_ptr 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::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; \
} \
std::unique_ptr I##INTERFACE::default_impl; \
bool I##INTERFACE::setDefaultImpl(std::unique_ptr impl)\
{ \
if (!I##INTERFACE::default_impl && impl) { \
I##INTERFACE::default_impl = std::move(impl); \
return true; \
} \
return false; \
} \
const std::unique_ptr& 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
转换后,变成 所以gDefaultServiceManager =new BpServiceManager(new BpBinder(0,trackedUid));
BpServiceManager()的继承有必要展开下,方便后面的分析:
1)class BpServiceManager : public BpInterface
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& 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.
}
}
[/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对象。
类的继承关系如下:
继续往下看BpServiceManager::addService()是如何工作的
[/frameworks/native/libs/binder/IServiceManager.cpp]
virtual status_t addService(const String16& name, const sp& 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;
}
主要流程:
最核心的就是 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& /*proc*/,
const sp& 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;
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(local->getWeakRefs());
obj.cookie = reinterpret_cast(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扁平数据所在的位置,示意图如下:
接下来看看传输过程BpBinder->transact(ADD_SERVICE_TRANSACTION,XXX)。
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() 进行处理
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;
}
IPCThreadState::transact()主要做了下面几步:
writeTransactionData 代码如下:
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(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对象的具体位置,如下图所示:
当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 驱动一节进行详细分析,这里只要了解一个大概即可,不要陷入死胡同。
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()进行最终的语义处理,发送出去。
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()进行处理。
status_t IPCThreadState::executeCommand(int32_t cmd)
{
...
case BR_TRANSACTION:
if (tr.target.ptr) {
if (reinterpret_cast(
tr.target.ptr)->attemptIncStrong(this)) {
//这里的cookie就是驱动层binder_node 节点的cookie发挥作用,拿到了一个合法的BBinder
error = reinterpret_cast(tr.cookie)->transact(tr.code, buffer,
&reply, tr.flags);
reinterpret_cast(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()成员函数。
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)
{
....
}
注册服务的流程简单的总结一下:
在第5节中,我们了解了media服务的注册流程,接下来我们一起看看,其他进程是如何获取media的服务来进行通信。
在ServiceManager一节,我们知道了注册、获取服务我们都要通过ServiceManager进行处理,所以获取服务,大体还是分为下面几步
获取media服务序列图:
[/frameworks/av/media/libmedia/IMediaDeathNotifier.cpp]
IMediaDeathNotifier::getMediaPlayerService()
{
ALOGV("getMediaPlayerService");
Mutex::Autolock _l(sServiceLock);
if (sMediaPlayerService == 0) {
//获取ServiceManager的代理对象BpServiceManager
sp sm = defaultServiceManager();
sp 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(binder);
}
ALOGE_IF(sMediaPlayerService == 0, "no media player service!?");
return sMediaPlayerService;
}
流程如下:
通过defaultServiceManager()来获取ServiceManager的对象,参考[6.1.3],我们接下来主要来看getService的流程
defaultServiceManager->getService()其实就是BpServiceManager->getService。
virtual sp getService(const String16& name) const
{
//检索指定服务是否存在
sp 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 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.
checkService()和前面的addService类似,都是组织一个Parcel结构,然后调用BpBinder的transact()方法,把服务信息和传输code--CHECK_SERVICE_TRANSACTION 发给Binder驱动.
virtual sp 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相应码。
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(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t),
freeBuffer, this);
} else {
err = *reinterpret_cast(tr.data.ptr.buffer);
freeBuffer(nullptr,
reinterpret_cast(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), this);
}
} else {
freeBuffer(nullptr,
reinterpret_cast(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), this);
continue;
}
}
goto finish;
...
}
checkservice()收到ServiceManager发来的reply后,调用readStrongBinder()来获取服务的对象。主要在unflatten_binder 中,根据flat的type是handle还是实体,从而返回BpBinder对象 或者BBinder实体。
sp Parcel::readStrongBinder() const
{
sp val;
readNullableStrongBinder(&val);
return val;
}
status_t Parcel::readNullableStrongBinder(sp* val) const
{
return unflatten_binder(ProcessState::self(), *this, val);
}
status_t unflatten_binder(const sp& proc,
const Parcel& in, sp* out)
{
const flat_binder_object* flat = in.readObject(false);
if (flat) {
switch (flat->hdr.type) {
case BINDER_TYPE_BINDER:
*out = reinterpret_cast(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(out->get()), *flat, in); //返回BpBinder代理对象
}
}
return BAD_TYPE;
}
获取服务的流程简单的总结一下:
注意:
Binder通信协议是基于Command-Reply的方式的。
Android9.0之前的协议码流程:
Android9.0及之后的协议码流程:
上面第5步的 BR_TRANSACTION_COMPLETE 被延迟到 第 10步 ,Android做了deferred_thread_work,延迟 TRANSACTION_COMPLETE,因此不会立即返回到用户空间;这允许目标进程立即开始处理此事务,从而减少延迟。然后,当目标回复(或出现错误)时,我们将返回TRANSACTION_COMPLETE。
注册服务的详细代码流程,kernel细节的代码这里就不贴了,后面在内核章节进行详细解析:
/frameworks/av/media/mediaserver/main_mediaserver.cpp
/frameworks/native/libs/binder/IServiceManager.cpp
/frameworks/native/libs/binder/ProcessState.cpp
/frameworks/native/libs/binder/Parcel.cpp
/frameworks/native/libs/binder/include/binder/IInterface.h
/frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
服务的注册和获取,主要还是 进程和Binder驱动,和ServiceManager交互的流程,这一节只是介绍了流程,但是BC_XXX 传输码和BR_XXX 响应码的转换流程还没有细讲,下一节会单独进行讲解。
另外服务注册后,启动的Binder线程池,本节也没有细讲,后面单独开一节来进行分析。
我的微信公众号:IngresGe