android Binder详解 (1)

做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来熟悉下android binder的api,编写出我们的SampleSerivce。
选择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()这个接口。
我们大致可以判断出来,IInterface和surfaceflinger无关,是一个重要的基础类,定义接口需要继承这个class。

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);

现在,我们来按照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


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值