Binder系列01:一个简单的Binder Service Demo

参考文献:

  1. https://blog.csdn.net/liyuntonglyt/article/details/61912822
  2. https://blog.csdn.net/ljsbuct/article/details/799183
  3. Binder系列:https://www.cnblogs.com/palance/p/5429111.html

Part I:IInterface/Bn/Bp之间的关系

  Iinterface/Bn/Bp是Binder通信中的相关概念。Binder通信是一种client-server的通信结构,这3个类,是对Android Binder框架的抽象,其实这个BBinder,改成BnBinder可能更形象一些。但是要注意的是,一个IXXXService的继承图中,BpBinder并不在这个继承关系之中,也就是说BpBinder并没有子类, BpBinder的是存在于BpRefBase中的mRemote的成员变量中;换句话说,BBinder和BpBinder的功能并不是对称的。但是BBinder是在这个继承关系当中的,它的子类就是BnInterface。 

  从Client调用Service的过程中分析,就更清楚了。假设有一个IXXXService接口:

class IXXXService : public IInterface {
    ....
    public void helloWorld(const char* str);
    ....
}
  • Client调用service:Client得到一个BpXXXService以后

    (a)会调用BpXXXService实现的helloWorld,它会将str参数打包到Parcel中。然后调用remote()->transact(xxx)

    (b)remote()是在BpXXXService的父类BpRefBase中实现的,返回的就是一个BpBinder.实际上调用的就是BpBinder的transact

    (c)BpBinder的transact实现,就是直接调用IPCThreadState::self()->transact()发送数据。

  • Service接收client请求:

    (a)通过IPCThreadState接收到client的请求后,首先会通过remote()调用BBinder的transact方法。

    (b)BBinder的transact方法又会调用子类实现的虚拟方法onTransact。这个虚拟方法是在BnXXXService中实现的。

    (c)onTransact方法,会通过传递进来的参数来判断,需要调用IXXXService中的那个方法,示例中只有一个helloWorld方法。

    (d)直接调用helloWorld,就会找到它的真正实现,也就是BnXXXService的子类XXXService中的helloWorld方法。

总结一下,从上面的流程当中就可以看出前文说的,BpBinder并不在继承关系当中,它只是一个打包数据,并通过IPCThreadState::self()->transact()方法发送出去。而BBinder和BnXXXService的作用,就是接收IPCThreadState传递过来的信息,解包数据,并调用XXXService真正的实现。整个的调用过程是一个同步过程,在server处理的时候,client会block住。整个Binder通信的过程如下图(借用别人博客中的)所示。

  首先来看IInterface类的定义:

class IInterface : public virtual RefBase
{
public:
IInterface();
    static sp<IBinder>  asBinder(const IInterface*);
    static sp<IBinder>  asBinder(const sp<IInterface>&);
protected:
    virtual                     ~IInterface();
    virtual IBinder*            onAsBinder() = 0;
};

  可以看到,这个函数的实现非常简单,重点来看这两个函数:asBinder和onAsBinder。

  asBinder的使用是将Interface类型转换为IBinder类型,其传参为IInterface指针,说明它可以实现下面两种类型的转换:

    BnInterface->BBinder

    BpInterface->BpBinder

  还有一个相反的转换,asInterface完成的是Binder到Interface的转换

    BBinder->BnInterface

    BpBinder->BpInterface

   在分析具体代码之前,有两个宏需要注意一下,这两个宏定义在frameworks\native\libs\binder\include\binder\IInterface.h文件中, frameworks\native\libs\gui\include\gui\ISurfaceComposer.h文件中使用了DECLARE_META_INTERFACE,而frameworks\native\libs\gui\ISurfaceComposer.cpp文件使用了IMPLEMENT_META_INTERFACE,二者是成对使用的。看代码的时候要注意这个地方。 

ISurfaceComposer.h中
DECLARE_META_INTERFACE(SurfaceComposer)
ISurfaceComposer.cpp中
IMPLEMENT_META_INTERFACE(SurfaceComposer, "android.ui.ISurfaceComposer");

   frameworks\native\libs\gui\SurfaceComposerClient.cpp文件通过getService()方法获取名为“SurfaceFlinger”的系统服务。getService方法在IServiceManager.h头文件中定义,因此需要包含该头文件

#include <binder/IServiceManager.h>
……
void ComposerService::connectLocked() {
    const String16 name("SurfaceFlinger");
    while (getService(name, &mComposerService) != NO_ERROR) {
        usleep(250000);
    }
    assert(mComposerService != NULL);
    ……
}

   在IServiceManager.h文件中查看getService方法的实现,它是先通过defaultServiceManager()方法拿到了系统ServiceManager,然后在ServiceManager中查找对应名字的服务。

template<typename INTERFACE>
status_t getService(const String16& name, sp<INTERFACE>* outService)
{
    const sp<IServiceManager> sm = defaultServiceManager();
    if (sm != nullptr) {
        *outService = interface_cast<INTERFACE>(sm->getService(name));
        if ((*outService) != NULL) return NO_ERROR;
    }
    return NAME_NOT_FOUND;
}

   getService方法中使用了一个interface_cast函数,它的实现是通过展开宏来控制的。这个宏定义在frameworks\native\libs\binder\include\binder\IInterface.h文件中。前面提到的两个宏在展开后会生成下面这个函数,也就是说getService()方法中调用的interface_cast方法其实是ISurfaceComposer类中实现的。

  而此时该方法的入参obj其实是从系统Service Manager里面拿出来的SurfaceFlinger系统服务(在main_surfaceflinger.cpp的main函数中注册的),显然此时拿到obj不为null,所以会去调用queryLocalInterface接口去拿ISurfaceComposer的descriptor,queryLocalInterface方法做的事情很简单,就是去比较ISurfaceComposer::descriptor与SurfaceComposer::descriptor是否相等,或相等则返回该服务,若不待,则返回BpSurfaceComposer。而queryLocalInterface方法是在IBinder中定义的默认返回null,只有BnInterface实现了该接口,而BpInterface没有实现该接口(BBinder和BpBinder的功能并不是对称的),因此如果传进来的obj参数,是一个BBinder,就返回自身(这种情况应该是service和client在同一进程),如果是一个BpBinder,就new一个代理对象返回(这种情况应该是service和client在不同进程)。

::android::sp<ISurfaceComposer> ISurfaceComposer::asInterface(
            const ::android::sp<::android::IBinder>& obj)
    {
        ::android::sp< ISurfaceComposer > intr;
        if (obj != nullptr) {
            intr = static_cast< ISurfaceComposer *>(
                obj->queryLocalInterface(
                        ISurfaceComposer::descriptor).get());
            if (intr == nullptr) {
                intr = new BpSurfaceComposer (obj);
            }
        }
        return intr;
} 

template<typename INTERFACE>
inline sp<IInterface> BnInterface<INTERFACE>::queryLocalInterface(const String16& _descriptor)
{
        if (_descriptor == INTERFACE::descriptor) return this;
        return nullptr;
}

   这两个宏的原始声明如下:

template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
    return INTERFACE::asInterface(obj);
}

#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)                         \
    if (!(data).checkInterface(this)) { return PERMISSION_DENIED; }     \

   拿到BpSurfaceComposer服务后,即可以通过Bp向Bn发送消息进行Binder通信,这样,Client就可以间接的调用Server的接口进行功能操作了。看下BpSurfaceComposer的相关实现,这里所有的操作都是通过remote()->transact这个动作向Bn端发起调用的。

class BpSurfaceComposer : public BpInterface<ISurfaceComposer>
{
public:
    virtual sp<ISurfaceComposerClient> createConnection()
    {
        Parcel data, reply;
        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
        remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, &reply);
        return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
    }
    virtual void setTransactionState(
            const Vector<ComposerState>& state,
            const Vector<DisplayState>& displays,
            uint32_t flags)
    {
        Parcel data, reply;
        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
        data.writeUint32(static_cast<uint32_t>(state.size()));
        for (const auto& s : state) {
            s.write(data);
        }
        data.writeUint32(static_cast<uint32_t>(displays.size()));
        for (const auto& d : displays) {
            d.write(data);
        }
        data.writeUint32(flags);
        remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply);
  }
······
}

   而在Server端的实现中,如SurfaceFlinger实现了BnComposerService,SurfaceFlinger会重写onTransact函数,这这个函数里面会调用读取并解析Client写过来的数据,然后调用对应的方法来实现Client的需求动作。

status_t SurfaceFlinger::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    status_t credentialCheck = CheckTransactCodeCredentials(code);
    if (credentialCheck != OK) {
        return credentialCheck;
    }

    status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
    if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
         ……
        int n;
        switch (code) {
            case 1000: // SHOW_CPU, NOT SUPPORTED ANYMORE
            case 1001: // SHOW_FPS, NOT SUPPORTED ANYMORE
                return NO_ERROR;
            case 1002:  // SHOW_UPDATES
                n = data.readInt32();
                mDebugRegion = n ? n : (mDebugRegion ? 0 : 1);
                invalidateHwcGeometry();
                repaintEverything();
                return NO_ERROR;
            case 1004:{ // repaint everything
                repaintEverything();
                return NO_ERROR;
            }
            case 1005:{ // force transaction
                Mutex::Autolock _l(mStateLock);
                setTransactionFlags(
                        eTransactionNeeded|
                        eDisplayTransactionNeeded|
                        eTraversalNeeded);
                return NO_ERROR;
            }
            case 1006:{ // send empty update
                signalRefresh();
                return NO_ERROR;
            }
            case 1008:  // toggle use of hw composer
                n = data.readInt32();
                mDebugDisableHWC = n ? 1 : 0;
                invalidateHwcGeometry();
                repaintEverything();
                return NO_ERROR;
            case 1009:  // toggle use of transform hint
                n = data.readInt32();
                mDebugDisableTransformHint = n ? 1 : 0;
                invalidateHwcGeometry();
                repaintEverything();
                return NO_ERROR;
            case 1010:  // interrogate.
                reply->writeInt32(0);
                reply->writeInt32(0);
                reply->writeInt32(mDebugRegion);
                reply->writeInt32(0);
                reply->writeInt32(mDebugDisableHWC);
                return NO_ERROR;
    ……
}

 

Part II:一个简单的Binder Service Demo

   完整代码地址: https://github.com/hfts/BinderServiceDemo.git

  BpXXX、BnXXX同时实现一个接口IXXX。BpXXX主要是用来处理java层传下来的服务请求,然后通过transact将处理请求传给BnXXX(通过binder)。BpINTERFACE是client端的代理接口,BnINTERFACE是server端的代理接口。注意这里面有一些命令规范,直接继承IInterface接口的接口一定要以I开关,表示这是一个接口。

  IInterface相关的知识结构如下,Andorid系统已经做好了绝大部分,我们在使用IInterface的使用只需要实现下面图中的绿色部分即可。主要包含三个部分:

 

  如Android中的SurfaceFlinger、Client(SurfaceFlinger中)则是分别实现了BnSurfaceComposer和BnSurfaceComposerClient,SurfaceFlinger、Client是真正的服务实现部分,Client端拿到只是BpSurfaceComposer和BpSurfaceComposerClient。

 

  下面自己动手来实现一个简单的Binder Service服务 。

  首先,定义ITestService接口:

class ITestService : public IInterface
{
  public:
    DECLARE_META_INTERFACE(TestService) // detail: frameworks/native/libs/binder/include/binder/IInterface.h
    virtual void testFun_01() = 0;
    virtual void testFun_02() = 0;
};

   在Client端(Java或C++),需要通过getService方法来获取对应的服务,其实这里拿到的就是Binder Proxy对象,即BpBinder,BpBinder(Binder Proxy):主要功能是负责client向Bn发送调用请求的数据。它是client端binder通信的核心对象,通过调用transact函数,client就可以向Bn发送调用请求和数据。这里我们定义一个BpTestService,继承自ITestService,为Client做准备。

class BpTestService : public BpInterface<ITestService>
{
  public:
    explicit BpTestService(const sp<IBinder> &impl)
        : BpInterface<ITestService>(impl)
    {
    }

    virtual ~BpTestService();
    virtual void testFun_01()
    {
        std::cout << "BpTestService::testFun_01" << std::endl;
        Parcel data, reply;
        data.writeInterfaceToken(ITestService::getInterfaceDescriptor());
        remote()->transact(BnTestService::TEST_01, data, &reply);
    }

    virtual void testFun_02()
    {
        std::cout << "BpTestService::testFun_02" << std::endl;
        Parcel data, reply;
        data.writeInterfaceToken(ITestService::getInterfaceDescriptor());
        remote()->transact(BnTestService::TEST_02, data, &reply);
    }
};

   而Server端则对应BnBinder(Binder Native):BnBinder就是具体干事情的对象。这里我们定义一个BnTestService,继承自ITestService。BnTestService是真正的服务端实现,一般在具体实现中,BnTestService会实现一些服务端的基本功能,而更复杂和详细的功能,则是由BnTestService类的子类来实现的。

class BnTestService : public BnInterface<ITestService>
{
  public:
    enum
    {
        TEST_01 = IBinder::FIRST_CALL_TRANSACTION,
        TEST_02,
    };

    virtual void testFun_01()
    {
        std::cout << "BnTestService::testFun_01" << std::endl;
    }
    virtual void testFun_02()
    {
        std::cout << "BnTestService::testFun_02" << std::endl;
    }

    virtual status_t onTransact(uint32_t code, const Parcel &data,
                                Parcel *reply, uint32_t flags = 0);
};

   BnTestService的onTransact函数的实现如下。

status_t BnTestService::onTransact(uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags)
{
    switch (code)
    {
    case TEST_01:
        CHECK_INTERFACE(ITestService, data, reply);
        testFun_01();
        return NO_ERROR;
    case TEST_02:
        CHECK_INTERFACE(ITestService, data, reply);
        testFun_02();
        return NO_ERROR;
    default:
    {
        return BBinder::onTransact(code, data, reply, flags);
    }
    }
}

   写Service,实现接口的虚函数

class TPrimeTestService : public BnTestService
{
  public:
    explicit TPrimeTestService();

    virtual void testFun_01();
    virtual void testFun_02();

    virtual status_t onTransact(uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags);
};

   TPrimeTestService的具体实现部分

TPrimeTestService::TPrimeTestService()
{
}

void TPrimeTestService::testFun_01()
{
    std::cout << "TrpimeTestService::testFun_01" << std::endl;
}

void TPrimeTestService::testFun_02()
{
    std::cout << "TrpimeTestService::testFun_02" << std::endl;
}

status_t TPrimeTestService::onTransact(
    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags)
{
    status_t err = BnTestService::onTransact(code, data, reply, flags);
    if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED)
    {
        CHECK_INTERFACE(ITestService, data, reply);
        std::cout << "TPrimeTestService::onTransact" << std::endl;
    }
    return err;
}

  服务的主函数中,获得ServiceManager,添加Service。

int main()
{
    sp<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> sm = defaultServiceManager();
    sm->addService(String16("tprime.TestService"), new tprime::TPrimeTestService());
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
    return 0;
}

  在Client获取上面注释的服务,并使用它:

int main()
{
    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> binder = sm->getService(String16("tprime.TestService"));
    sp<tprime::ITestService> ts = interface_cast<tprime::ITestService>(binder);
    ts->testFun_01();
    ts->testFun_02();

    return 0;
}

  编译上述代码,会在out/target/product/generic_x86/system/bin目录下面生成两个可执行文件

ubuntu@ubuntu:~/projects/android_8_1_0_r41/out/target/product/generic_x86/system/bin$ ll | grep Test
-rwxrwxr-x  1 ubuntu ubuntu   23284 10月  4 22:34 TestClient*
-rwxrwxr-x  1 ubuntu ubuntu   27504 10月  4 22:34 TestServer*

  将上述两个文件push到手机中(如push到data/tsdebug目录中),chmod给予可执行权限,在不同的终端中,先运行TestServer,再执行TestClient,实际的运行结果如下:

generic_x86:/data/tsdebug # ./TestClient
BpTestService::testFun_01
BpTestService::testFun_02

generic_x86:/data/tsdebug # ./TestServer
TrpimeTestService::testFun_01
TrpimeTestService::testFun_02

 

posted @ 2018-10-05 00:50  TPrime.A  阅读(1457)  评论(0编辑  收藏  举报