• 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 ativelibsinderincludeinderIInterface.h文件中, frameworks ativelibsguiincludeguiISurfaceComposer.h文件中使用了DECLARE_META_INTERFACE,而frameworks ativelibsguiISurfaceComposer.cpp文件使用了IMPLEMENT_META_INTERFACE,二者是成对使用的。看代码的时候要注意这个地方。 

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

       frameworks ativelibsguiSurfaceComposerClient.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 ativelibsinderincludeinderIInterface.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
  • 相关阅读:
    NHibernate开源框架Cuyahoga学习之数据访问实现
    Petshop4.0 缓存设计学习
    Jquery实现ToolTip之元素定位
    客户单操作Cookie
    .Net 通过MySQLDriverCS操作MySQL
    NHibernate的基本使用
    提高ASP.NET性能的十大方法
    工作流引擎下基于表达式Tree复杂验证的实现
    C#注册表操作
    WinForm应用程序中的ComboBox实现ReadOnly功能
  • 原文地址:https://www.cnblogs.com/tsts/p/9743987.html
Copyright © 2020-2023  润新知