zoukankan      html  css  js  c++  java
  • android binder机制之——(创建binder服务)

     

    Binder机制编程

            前面的几篇文章具体介绍了android中binder机制的方方面面,相信你对binder机制已经有了较深刻的理解。俗话说得好“学以致用”,以下我们就通过在android系统中创建一个我们自己的binder服务,来加深对binder机制的理解。

    (1)增加新建的服务名称

              在service_manager.c文件里有一个结构数组allowed,在allowed结构体数组中增加新建的服务名称

    static struct {
        unsigned uid;
        const char *name;
    } allowed[] = {
    #ifdef LVMX
        { AID_MEDIA, "com.lifevibes.mx.ipc" },
    #endif
        { AID_MEDIA, "media.audio_flinger" },
        { AID_MEDIA, "media.player" },
        { AID_MEDIA, "media.camera" },
        { AID_MEDIA, "media.audio_policy" },
        { AID_RADIO, "radio.phone" },
        { AID_RADIO, "radio.sms" },
        { AID_RADIO, "radio.phonesubinfo" },
        { AID_RADIO, "radio.simphonebook" },
    /* TODO: remove after phone services are updated: */
        { AID_RADIO, "phone" },
        { AID_RADIO, "isms" },
        { AID_RADIO, "iphonesubinfo" },
    { AID_RADIO, "simphonebook" },
     
    {AID_NEW, "newservice"}
    };
     

    (2)定义ImyService类

             定义一个继承自IInterface的接口类,须是以大写字母I開始,以IMyService为例接口函数必须为纯虚函数,以便在子类中生产,在定义接口时将DECLARE_META_INTERFACE宏放进接口类定义中,这个宏的最重要作用是将代理对象BpBinder转化成本地封装的服务代理对象(在这里是BpMyService对象),代码大致例如以下:

    Class ImyService:public IInterface
    {
    Public:
        DECLARE_META_INTERFACE(MyService);
            
        Virtual fun1() = 0;
        Virtual fun2() = 0;
    }

     

    (3)定义一个本地实现类BnMyService

            在IMyService.h头文件里定义接口实现类BnMyService, 需继承自BnInterface,间接双继承了IMyService接口类和BBinder类,代码例如以下:

    Class BnMyService:public BnInterface<IMyService>
    {
    Public:
        Virtual status_t onTransact(uint32_t code,
                                        const Parcel& data,
                                        Parcel* reply,
                                        uint32_t flags = 0);
    }

    (4)定义本地代理类BpMyService

             在IMyService.cpp源文件里,定义接口代理类BpMyService,需继承自BpInterface。BpMyService能够提供IMyService接口所定义的接口函数。

    class BpMyService: public BpInterface<IMyService>
    {
    public:
        BpMyService(const sp<IBinder>& impl)
            : BpInterface<IMyService>(impl)
        {
    }
    void fun1()
        {
            Parcel data, reply;
            ……            //数据写入
            remote()->transact(枚举量, data, &reply);
            return ……     //数据返回
        }
    ……
    }

    (5)增加宏定义

            在IMyService.cpp源文件里,增加宏定义IMPLEMENT_META_INTERFACE()

     
    IMPLEMENT_META_INTERFACE(MyService, "XXX");
     

    (6)定义BnMyService的onTransact()函数

             在IMyService.cpp源文件里实现接口实现类BnMyService,当中onTrasact()函数依据功能代码枚举量的不同分别运行不同的功能调用。

    status_t BnMyService::onTransact(
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    {
        switch(code) {      //code功能代码枚举量
            case功能代码枚举量: {
                LOGV("NOTIFY_CALLBACK");
                CHECK_INTERFACE(ICameraClient, data, reply);    //检查描写叙述符字符串
                ……        //參数输入,接口函数功能的真正实现
                reply->……);   //返回数据
                return NO_ERROR;
            } break;
    ……
    default:
                return BBinder::onTransact(code, data, reply, flags);
    }

    (7)创建真正的本地接口实现类MyService类

            在头文件里定义类MyService,继承自BnInterface,定义功能函数和初始化函数instantiate():

    Class MyService:public BnMyService
    {
    Public:
        Static void instantiate();
        
        Virtual func1();
        Virtual func2();
        ……
    }
     

     (8)定义MyService::instantiate()函数

    void MyService::instantiate() {
        defaultServiceManager()->addService(
                String16("newservice"), new MyService());
    }
        

    (9)服务进程中注冊服务

            在服务进程A初始化时增加MyService:: instantiate()函数,注冊服务,调用joinThreadPool()函数进入循环等待调用,侦听请求、处理请求。

    int main(int argc, char** argv)
    {
        sp<ProcessState> proc(ProcessState::self());
        sp<IServiceManager> sm = defaultServiceManager();
        LOGI("ServiceManager: %p", sm.get());
        MyService::instantiate();
        ……
        ProcessState::self()->startThreadPool();
        IPCThreadState::self()->joinThreadPool();
    }

    (10)client获取服务代理对象

            client进程B要想和服务端通讯,首先须要获取服务管家ServiceManager的代理对象,,然后查找服务,由于服务已经注冊,所以会返回一个该服务代理对象的引用,此代理对象中包括一个指向查找的服务的handle句柄。

    const sp<IMyService>& MyServiceSystem::get_MyService()
    {
        Mutex::Autolock _l(mLock);
        if (gMyService.get() == 0) {
            sp<IServiceManager> sm = defaultServiceManager();    //获取服务管家的代
    //理对象
            sp<IBinder> binder;
            do {
                binder = sm->getService(String16("newservice")); //查找到服务后,
    //返回服务的代理对象
                ……
            } while(true);
            ……
            gMyService = interface_cast<IMyService>(binder);    //将其转换为本地服
    //务代理对象(BpMyService)
            ……
        }
        ……
        return mMyService;
    }

    (11)client调用服务端函数

            client进程B调用IMyService的接口函数,调用会传递给包括了服务对象handle的代理对象BpBinder,写入binder内核驱动。binder驱动知道数据传递到的对象,于是将数据传递给进程A。

    服务端进程A从binder驱动中读取数据,然后处理远程调用,然后发送reply数据给binder驱动。binder驱动将reply传递给client进程B。进程B从binder驱动中读取数据并最终获取到reply,从而完毕进程通信。

    Status_t MyServiceSystem::func1()
    {
        Const sp<IMyService>& af = MyServiceSystem::get_MyService();
        Af::Func1();
        ……
    }

            到这里,我们已经把android中的binder机制介绍完了。呵呵,本来认为binder机制总结起来不会非常难,可在写总结的过程中还是遇到了非常多问题。呵呵,只是还好,都差点儿相同一一攻克了,最终写完了。总结过程中相当于又学了一边binder机制,并且还有新的收获,真的不错哦!

  • 相关阅读:
    MyBatis使用
    华为如何实现基于Git的跨地域协同开发
    推荐一款华为最新的自动化代码检查工具
    我是如何进行code review的
    谈谈敏捷开发
    软件测试管理的一点小心得
    (转)技术转管理可能遇到的 3 大挑战及解决方案
    领域驱动设计和实践
    NET开源项目
    asp.net搭建mybatis开发环境
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4302231.html
Copyright © 2011-2022 走看看