做android的同学们都应该知道有个叫做binder的东西,它是android的ipc机制,是一个核心的组成部分。
一直以来,我对于binder只有一个概念,对细节不清楚,特别是核心的binder device。最近有空,完整的学习下android binder,这篇文章,基本上是整个学习过程的一个记录,如有错误的问题,请大家指正。本文中只从native service分析,分析分成两大步:
1,了解android binder的natvie api和关键的类,编写自己的SampleService/SampleClient。在这一步中,我们会忽略具体的数据如何传递的,只要有个概念即可。
2,从简单的service入手分析,service/client如何通过binder device来交换数据的。
注:
1,基于android 4.4的代码进行分析。
2,文中引用的代码会省略掉部分代码,用......来代替。
一,准备知识
在开始之前,先对service运行时候的相关的几个角色和他们的关系有个概念。
在serivce运行中,主要有上面这几个角色,
service就是运行的服务。
client是使用service的程序。
ServiceManager也是一个service,只是有一定的特殊性,他是管理其他的android service,要单独拉出来说。
/dev/binder是binder的虚拟设备。
这个图中,用虚线来表示逻辑上的交互关系,实线来表示实际的交互。
这几个角色的关系可以总结成:所有调用service的操作逻辑都是通过binder device中转来完成交互。
二,android binder native api
选择surfaceflinger来分析,是因为他是一个很独立的natvie service,方便分析,第二个原因是因为个人比较熟悉这块,先上图看看surfaceflinger service相关几个类。
2.1 SampleService接口定义
写service第一步当然是定义service的接口,先看下surfaceflinger的接口是怎么做的,surfaceflinger的接口定义是class ISurfaceComposer,在frameworks/natvie/include/gui/ISurfaceComposer.h:
class ISurfaceComposer: public IInterface {
public:
DECLARE_META_INTERFACE(SurfaceComposer);
//TODO
//eOpaque = 0x00000400,
//eLayerOpaque = 0x20
// flags for setTransactionState()
enum {
eSynchronous = 0x01,
eAnimation = 0x02,
};
enum {
eDisplayIdMain = 0,
eDisplayIdHdmi = 1
};
/* create connection with surface flinger, requires
* ACCESS_SURFACE_FLINGER permission
*/
virtual sp<ISurfaceComposerClient> createConnection() = 0;
/* create a graphic buffer allocator
*/
virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc() = 0;
/* return an IDisplayEventConnection */
virtual sp<IDisplayEventConnection> createDisplayEventConnection() = 0;
/* create a virtual display
* requires ACCESS_SURFACE_FLINGER permission.
*/
virtual sp<IBinder> createDisplay(const String8& displayName,
bool secure) = 0;
/* destroy a virtual display
* requires ACCESS_SURFACE_FLINGER permission.
*/
virtual void destroyDisplay(const sp<IBinder>& display) = 0;
/* get the token for the existing default displays. possible values
* for id are eDisplayIdMain and eDisplayIdHdmi.
*/
virtual sp<IBinder> getBuiltInDisplay(int32_t id) = 0;
/* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */
virtual void setTransactionState(const Vector<ComposerState>& state,
const Vector<DisplayState>& displays, uint32_t flags) = 0;
/* signal that we're done booting.
* Requires ACCESS_SURFACE_FLINGER permission
*/
virtual void bootFinished() = 0;
/* verify that an IGraphicBufferProducer was created by SurfaceFlinger.
*/
virtual bool authenticateSurfaceTexture(
const sp<IGraphicBufferProducer>& surface) const = 0;
/* triggers screen off and waits for it to complete
* requires ACCESS_SURFACE_FLINGER permission.
*/
virtual void blank(const sp<IBinder>& display) = 0;
/* triggers screen on and waits for it to complete
* requires ACCESS_SURFACE_FLINGER permission.
*/
virtual void unblank(const sp<IBinder>& display) = 0;
/* returns information about a display
* intended to be used to get information about built-in displays */
virtual status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info) = 0;
/* Capture the specified screen. requires READ_FRAME_BUFFER permission
* This function will fail if there is a secure window on screen.
*/
virtual status_t captureScreen(const sp<IBinder>& display,
const sp<IGraphicBufferProducer>& producer,
uint32_t reqWidth, uint32_t reqHeight,
uint32_t minLayerZ, uint32_t maxLayerZ) = 0;
};
class中除了定义了一堆的接口函数,有两个地方需要仔细看下:
- 继承的IInterface
- DECLARE_META_INTERFACE(SurfaceComposer);
2.1.1 IInterface
先看下IInterface的定义和实现,在frameworks/natvie/include/binder/IInterface.h,frameworks/natvie/binder/IInterface.cpp。
class IInterface : public virtual RefBase
{
public:
IInterface();
sp<IBinder> asBinder();
sp<const IBinder> asBinder() const;
protected:
virtual ~IInterface();
virtual IBinder* onAsBinder() = 0;
};
class IInterface的代码很简单,我们可以获得几点信息:
- 继承了RefBase。
- 从接口上看这个class和binder有关系(具体关系不清楚)。
- 该类的子类需要实现onAsBinder()这个接口。
2.1.2 DECLARE_META_INTERFACE
DECLARE_META_INTERFACE是一个宏,定义在frameworks/natvie/include/binder/IInterface.h中,代码如下
#define DECLARE_META_INTERFACE(INTERFACE) \
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();
我们把参数带入看看DECLARE_META_INTERFACE(SurfaceComposer)看看实际内容:
static const android::String16 descriptor;
static android::sp<ISurfaceCompoer> asInterface(
const android::sp<android::IBinder>& obj);
virtual const android::String16& getInterfaceDescriptor() const;
ISurfaceComposer();
virtual ~ISurfaceComposer();
这样看就清楚多了,展开后的代码就是为ISurfaceComposer声明了构造/析构函数,还有另外的几个成员。从接口名称上看,定义的都是公用的接口,并非是surfaceflinger独有的,对于我们定义service接口应该也是必要的。
PS:注意DECLARE_META_INTERFACE这个宏对于接口的class name有要求,接口class name必须是I开头的,否则展开的函数就出现问题了。
在这里有一个疑问,DECLARE_META_INTERFACE声明的函数都不是virtual的,也就是说必须要有实现,那么他们的实现在什么地方?很巧,就在DECLEAR_META_INTERFACE这个宏的下面,还有另外一个宏定义IMPLEMENT_META_INTERFACE,看看他的定义:
#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 != NULL) { \
intr = static_cast<I##INTERFACE*>( \
obj->queryLocalInterface( \
I##INTERFACE::descriptor).get()); \
if (intr == NULL) { \
intr = new Bp##INTERFACE(obj); \
} \
} \
return intr; \
} \
I##INTERFACE::I##INTERFACE() { } \
I##INTERFACE::~I##INTERFACE() { } \
宏里面我们可以看到,里面的确是看到了在DECLARE_META_INTERFACE()中声明的函数,看看SurfaceComposer里面怎么用的,在ISurfaceComposer.cpp中找到了
IMPLEMENT_META_INTERFACE(SurfaceComposer, "android.ui.ISurfaceComposer");
展开后
const android::String16 ISurfaceComposer::descriptor("android.ui.ISurfaceComposer");
const android::String16&
ISurfaceComposer::getInterfaceDescriptor() const {
return ISurfaceComposer::descriptor;
}
android::sp<ISurfaceComposer> ISurfaceComposer::asInterface(
const android::sp<android::IBinder>& obj)
{
android::sp<ISurfaceComposer> intr;
if (obj != NULL) {
intr = static_cast<ISurfaceComposer*>(
obj->queryLocalInterface(
ISurfaceComposer::descriptor).get());
if (intr == NULL) {
intr = new BpSurfaceComposer(obj);
}
}
return intr;
}
ISurfaceComposer::ISurfaceComposer) { }
ISurfaceComposer::~ISurfaceComposer() { }
IInterface::IInterface()
: RefBase() {
}
IInterface::~IInterface() {
}
sp<IBinder> IInterface::asBinder()
{
return this ? onAsBinder() : NULL;
}
sp<const IBinder> IInterface::asBinder() const
{
return this ? const_cast<IInterface*>(this)->onAsBinder() : NULL;
}
这样可以确认IMPLEMENT_META_INTERFACE这个宏的确是实现了DECLARE_META_INTERFACE中声明的函数,传入的第一个参数还是和之前一样是service的name,第二个参数是service的描述。在ISurfaceComposer::asInterface()函数中,出现了一个类BpSurfaceComposer,这个是client端使用的class,暂时不管他。
2.1.3 小结
OK。到这边,ISurfaceComposer的声明基本看完了,定义一个service的接口有3个步骤:- 继承IInterface
- 在class 声明中加入DECLARE_META_INTERFACE(serviceName);
- 加上IMPLEMENT_META_INTERFACE(serviceName,serviceDescriptor);实现DECLARE_META_INTERFACE中定义的接口。
现在,我们可以写下SampleService接口定义了:
class ISampleService: public IInterface {
public:
DECLARE_META_INTERFACE(SampleService);
//declear interface funs
virtual int sayHello(const String8& clientName) = 0;
};
IMPLEMENT_META_INTERFACE(SampleService,"android.binder.sample");
2.2 SampleService实现
定义好接口,之后就来看看怎么去实现定义好的接口,还是先看看surfaceflinger是怎么做的。从SurfaceFlinger的类图上,ISurfaceComposer接口被三个class一层层的继承了,我们逐个看下这个3个class。
2.2.1 BnInterface<ISurfaceComposer>
这个class是BnInterface模板的特例化,模板定义在frameworks/natvie/include/binder/IInterface.h:
template<typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder
{
public:
virtual sp<IInterface> queryLocalInterface(const String16& _descriptor);
virtual const String16& getInterfaceDescriptor() const;
protected:
virtual IBinder* onAsBinder();
};
BnInterface模板是继承了BBinder和INTERFACE,并且新定义了几个接口,这几个接口已经实现好,在 frameworks/natvie/include/binder/IInterface.h中:
template<typename INTERFACE>
inline sp<IInterface> BnInterface<INTERFACE>::queryLocalInterface(
const String16& _descriptor)
{
if (_descriptor == INTERFACE::descriptor) return this;
return NULL;
}
template<typename INTERFACE>
inline const String16& BnInterface<INTERFACE>::getInterfaceDescriptor() const
{
return INTERFACE::getInterfaceDescriptor();
}
template<typename INTERFACE>
IBinder* BnInterface<INTERFACE>::onAsBinder()
{
return this;
}
这几个函数中都用了IInterface中DECLARE_META_INTERFACE中声明的变量和函数,函数实现看起来都是有意义的,并且SurfaceFlinger中也没有重新实现,我们也不需要重新实现了。
另外一个父类BBinder,从名字上看就是和binder相关的,class中所有的函数都有实现,我们暂时也不要去研究它,继续后面的分析。
BnInterface<ISurfaceComposer>小结
BnInterface<ISurfaceComposer>这部分不需要我们实现任何代码,那我们在实现自己的service的时候,也不需要做什么工作了。
2.2.2 BnSurfaceComposer
BnSurfaceComposer的声明在frameworks/natvie/include/gui/ISurfaceComposer.h
class BnSurfaceComposer: public BnInterface<ISurfaceComposer> {
public:
enum {
// Note: BOOT_FINISHED must remain this value, it is called from
// Java by ActivityManagerService.
BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
CREATE_CONNECTION,
CREATE_GRAPHIC_BUFFER_ALLOC,
CREATE_DISPLAY_EVENT_CONNECTION,
CREATE_DISPLAY,
DESTROY_DISPLAY,
GET_BUILT_IN_DISPLAY,
SET_TRANSACTION_STATE,
AUTHENTICATE_SURFACE,
BLANK,
UNBLANK,
GET_DISPLAY_INFO,
CONNECT_DISPLAY,
CAPTURE_SCREEN,
};
virtual status_t onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags = 0);
};
class里面只有一个函数onTransact,实现在文件frameworks/native/libs/gui/ISurfaceComposer.cpp:
status_t BnSurfaceComposer::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
......
case GET_BUILT_IN_DISPLAY: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
int32_t id = data.readInt32();
sp<IBinder> display(getBuiltInDisplay(id));
reply->writeStrongBinder(display);
return NO_ERROR;
}
......
}
// should be unreachable
return NO_ERROR;
}
这边碰到了class Parcel,简单说下他的用途:在做跨进程通信的时候,对象不能直接传递,要先转换成字节流的形式才能传递出去,然后接受端再从字节流中重新组织出一个对象来。Parcel就是帮助我们做这个转换的动作的,在service和client会有对应Parcel保存字节流数据,并且帮助我们read/write数据。我们在class Parcel中里面看到大多数函数都是writeXXX,readXXX,就是把数据写入字节流,把数据从字节流中读出。
下面,我们通过GET_BUILT_IN_DISPLAY这个case的代码来了解下onTransact()的用途是什么:
第一行:CHECK_INTERFACE(ISurfaceComposer, data, reply);
CHECK_INTERFACE的宏定义如下:
#define CHECK_INTERFACE(interface, data, reply) \
if (!data.checkInterface(this)) { return PERMISSION_DENIED; } \
展开后是
if (!data.enforceInterface(this->getInterfaceDescriptor(),NULL)) { return PERMISSION_DENIED; }
继续看Parcel::enforceInterface的实现:
bool Parcel::enforceInterface(const String16& interface,
IPCThreadState* threadState) const
{
int32_t strictPolicy = readInt32();
if (threadState == NULL) {
threadState = IPCThreadState::self();
}
if ((threadState->getLastTransactionBinderFlags() &
IBinder::FLAG_ONEWAY) != 0) {
// For one-way calls, the callee is running entirely
// disconnected from the caller, so disable StrictMode entirely.
// Not only does disk/network usage not impact the caller, but
// there's no way to commuicate back any violations anyway.
threadState->setStrictModePolicy(0);
} else {
threadState->setStrictModePolicy(strictPolicy);
}
const String16 str(readString16());
if (str == interface) {
return true;
} else {
ALOGW("**** enforceInterface() expected '%s' but read '%s'\n",
String8(interface).string(), String8(str).string());
return false;
}
}
这个函数关键的就是
const String16 str(readString16());
if (str == interface) {
从data中读取一个string,然后和传入的interface description比较,一致就返回true,否则返回false。CHECK_INTERFACE的意义就是通过比较当前的interface是不是和传入的parcel(参数Parcal& data)中要求的interface是否一致的。
第二行:int32_t id = data.readInt32();
第三行:sp<IBinder> display(getBuiltInDisplay(id));
这两个行就是调用了getBuiltInDisplay()函数,而getBuiltInDisplay恰好是ISurfaceComposer中定义的提供给client调用的Service接口。
调用的参数从Parcel data中得到。
第四行:reply->writeStrongBinder(display);
这行代码是把getBuiltInDisplay返回的对象写入到了Parcel replay中去了。
看完这几行代码,我们可以看到几点信息:
- onTransact()中调用了提供给client的service接口,而且onTransact()又是在service端的函数,我们可以想到这个函数是client调用到service接口的一个中间过程。
- Parcel data中是client传递过来的调用service接口的数据。
- Parcel reply是service要返回给client的数据。
对于这三点,我们去参照其他的case,都是完全符合的。
另外知道了Parcel data是由client传递过来的信息,那么CHECK_INTERFACE很明显就是为了确保检验调用的正确性,检查当前的service是否是client所期望调用的service。
BnSurfaceComposer小结
至此,我们已经了解到BnSurfaceComposer是surfaceflinger client调用service接口的一个中转的class。我们实现自己的Service的时候,也需要实现这样一个类,实现这个类主要是下面几步:
- 定义和接口对应的command code。
- 实现onTransact()函数。
- 对于每个command:
- 调用CHECK_INTERFACE
- 从Parcel data中读取参数,如果需要的话。
- 调用对应的接口函数。
- 将返回值写入Parcel reply中,如果需要的话。
- default case参考ISurfaceComposer中调用BBinder::onTransact(code, data, reply, flags);
- 对于每个command:
现在,我们来按照step来实现SampleService的BnSampleService:
class BnSampleService: public BnInterface<ISampleService> {
public:
enum {
SAY_HELLO = IBinder::FIRST_CALL_TRANSACTION,
};
virtual status_t onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags = 0);
};
status_t BnSampleService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags ){
switch(code){
case SAY_HELLO:{
String8 clientName = data.readString8();
int ret = sayHello(clientName);
reply->writeInt32(ret);
return NO_ERROR;
}
default: {
return BBinder::onTransact(code, data, reply, flags);
}
}
return NO_ERROR;
}
2.2.3 IBinder::DeathRecipient
在类图上,我们还可以看到SurfaceFlinger继承了一个和binder有关系的接口:DeathRecipient,定义在在frameworks/native/include/binder/IBinder.h:
class DeathRecipient : public virtual RefBase
{
public:
virtual void binderDied(const wp<IBinder>& who) = 0;
};
DeathRecipient是client端用来监听service是否died的一个callback,SurfaceFlinger中是用来监听WindowManagerService是否died(在SurfaceFlinger::bootFinished()中注册):
// wait patiently for the window manager death
const String16 name("window");
sp<IBinder> window(defaultServiceManager()->getService(name));
if (window != 0) {
window->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
}
对于SampleService来说,我们不需要监听其他service的状态,所以也不需要去实现这个接口。
2.2.4 SurfaceFlinger
到了SurfaceFlinger这一层就是实现前面的定义的各种接口了,我们快速对照下SurfaceFlinger的头文件frameworks/native/services/surfaceflinger/SurfaceFlinger.h头文件(文件太长就不贴了)中对照一下,看看他实现/重写了哪些接口:
- ISurfaceComposer定义的service接口都是纯虚函数,在SurfaceFlinger都有实现。
- BnInterface中定义的接口未重写。
- SurfaceFlinger中进行了重写onTransact(),不过只是做了一些扩展,最终还是会调用到BnSurfaceComposer的onTransact中去,并不会影响整个调用流程。
SurfaceFlinger小结
SurfaceFlinger主要是实现了ISurfaceComposer中的service接口和DeathRecipient中定义的接口。那么我们实现自己的service的时候,因为不需要DeathRecipient,所以只需要实现定义好的Service接口即可。
好了,来实现我们的SampleService:
class SampleService : public BnSampleService {
public:
//service interface
int sayHello(const String8& clientName);
//DeathRecipient interface
void binderDied(const wp<IBinder>& who);
};
int SampleService::sayHello(const String8& clientName){
ALOGD("Hello %s",clientName.string());
return 1;
}
到这里,我们已经完成了service的class的实现了,下面看看如何启动service。
-------------------------------------------
by sky