用android 模板,实现native service

来源:互联网 发布:linux uname -a 编辑:程序博客网 时间:2024/06/13 18:40


  通过IInterface里定义的这些不太好理解的模板方法,使得编写一个Native Service的工作量也并不大.

http://blog.csdn.net/21cnbao/article/details/8087328

Proxy端:微笑



\frameworks\av\media\libmedia\IMediaPlayerService.cpp:

class BpMediaPlayerService: public BpInterface<IMediaPlayerService>{public:    BpMediaPlayerService(const sp<IBinder>& impl)        : BpInterface<IMediaPlayerService>(impl)    {    }

在frameworks\native\include\binder\IInterface.h中定义

template<typename INTERFACE>class BpInterface : public INTERFACE, public BpRefBase{public:                                BpInterface(const sp<IBinder>& remote);protected:    virtual IBinder*            onAsBinder();};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;};

在:frameworks\av\include\media\IMediaPlayerService.h中定义:
class IMediaPlayerService: public IInterface{public:    DECLARE_META_INTERFACE(MediaPlayerService);

在:\frameworks\native\include\binder\Binder.h:

class BpRefBase : public virtual RefBase{protected:                            BpRefBase(const sp<IBinder>& o);    virtual                 ~BpRefBase();    virtual void            onFirstRef();    virtual void            onLastStrongRef(const void* id);    virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);    inline  IBinder*        remote()                { return mRemote; }    inline  IBinder*        remote() const          { return mRemote; }private:                            BpRefBase(const BpRefBase& o);    BpRefBase&              operator=(const BpRefBase& o);    IBinder* const          mRemote;    RefBase::weakref_type*  mRefs;    std::atomic<int32_t>    mState;};

在:\frameworks\native\include\binder\IBinder.h:

class IBinder : public virtual RefBase{public:

在:frameworks\native\include\binder\BpBinder.h

class BpBinder : public IBinder{public:                        BpBinder(int32_t handle);    inline  int32_t     handle() const { return mHandle; }    virtual status_t    transact(   uint32_t code,                                    const Parcel& data,                                    Parcel* reply,                                    uint32_t flags = 0);

在:frameworks\native\libs\binder\BpBinder.cpp

status_t BpBinder::transact(    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){    // Once a binder has died, it will never come back to life.    if (mAlive) {        status_t status = IPCThreadState::self()->transact(            mHandle, code, data, reply, flags);        if (status == DEAD_OBJECT) mAlive = 0;        return status;    }    return DEAD_OBJECT;}

在:frameworks\native\include\binder\IPCThreadState.h

class IPCThreadState{public:               sp<ProcessState>    process();            status_t            transact(int32_t handle,                                         uint32_t code, const Parcel& data,                                         Parcel* reply, uint32_t flags);


Stub端:

偷笑


在:\frameworks\av\media\libmediaplayerservice\MediaPlayerService.h:

class MediaPlayerService : public BnMediaPlayerService{    class Client;


在:frameworks\av\include\media\IMediaPlayerService.h中定义:

class BnMediaPlayerService: public BnInterface<IMediaPlayerService>{public:    virtual status_t    onTransact( uint32_t code,                                    const Parcel& data,                                    Parcel* reply,                                    uint32_t flags = 0);};

在frameworks\native\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();};

在:\frameworks\native\include\binder\Binder.h:

class BBinder : public IBinder{public:                        BBinder();    virtual const String16& getInterfaceDescriptor() const;    virtual status_t    transact(   uint32_t code,                                    const Parcel& data,                                    Parcel* reply,                                    uint32_t flags = 0);


以MediaPlayerService为例子:


在Native Service的类的继承关系上,所有加了颜色标识的部分,IMediaPlayerService接口类、BpInteface<IMediaPlayerService>和BnInterface<IMediaPlayerService>模板类、以及进一步派出来的BpMediaPlayerService和BnMediaPlayerService,都是需要手动实现的。


这样实现最终得到的结果,就是我们可以通过一个继承自BnMediaPlayerService的可实例化的类MediaPlayerService构造一个对象,这一对象便可以在其生存期内响应与处理Binder命令的请求。


而通过中间引入的一层BpMediaPlayerService,也可以自动地将客户端代码通过BpRefBase的引用自动生成。


作为所有实现的源头,于是我们需要定义IMediaPlayerService接口类:

enum {    CREATE = IBinder::FIRST_CALL_TRANSACTION,    CREATE_MEDIA_RECORDER,    CREATE_METADATA_RETRIEVER,    GET_OMX,    MAKE_HDCP,    ADD_BATTERY_DATA,    PULL_BATTERY_DATA,    LISTEN_FOR_REMOTE_DISPLAY,    GET_CODEC_LIST,};class IMediaPlayerService: public IInterface{public:    DECLARE_META_INTERFACE(MediaPlayerService);    virtual sp<IMediaRecorder> createMediaRecorder(const String16 &opPackageName) = 0;    virtual sp<IMediaMetadataRetriever> createMetadataRetriever() = 0;    virtual sp<IMediaPlayer> create(const sp<IMediaPlayerClient>& client,            audio_session_t audioSessionId = AUDIO_SESSION_ALLOCATE) = 0;    virtual sp<IOMX>            getOMX() = 0;    virtual sp<IHDCP>           makeHDCP(bool createEncryptionModule) = 0;    virtual sp<IMediaCodecList> getCodecList() const = 0;    // Connects to a remote display.    // 'iface' specifies the address of the local interface on which to listen for    // a connection from the remote display as an ip address and port number    // of the form "x.x.x.x:y".  The media server should call back into the provided remote    // display client when display connection, disconnection or errors occur.    // The assumption is that at most one remote display will be connected to the    // provided interface at a time.    virtual sp<IRemoteDisplay> listenForRemoteDisplay(const String16 &opPackageName,            const sp<IRemoteDisplayClient>& client, const String8& iface) = 0;    virtual void addBatteryData(uint32_t params) = 0;    virtual status_t pullBatteryData(Parcel* reply) = 0;};

  作为兼用于Proxy与Stub的接口类定义的IInterface,实际上至少还需要定义Binder命令、asBinder()等基本方法。这时,我们就可以看到在IInterface定义里使用宏的好处了,我们这里只需要定义属于特性的部分,比如这一Native Service所需要的Binder命令,和支持这一Binder命令的远程接口方法,仅此而已。而其他部分的代码,并不需要我们直接实现,我们只需要使用DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE这两个宏来自动化生成这些共性的部分。于是,实现一个远程接口类,会是通过继承IInterface接口类,然后得到具体的接口类,比如我们这里的IMediaPlayerService。剩下的部分,会是如下四路的基本套路:
  • 1)  定义Binder命令,而且命令都以IBinder::FIRST_CALL_TRANSACTION,也就是1开始;
  • 2)  定义接口方法,也就是一个纯虚方法,比如
    createMediaRecorder();
  • 3)  通过DECLARE_META_INTERFACE,从而自动生成这一接口类所需要的通用属性与方法;

#define DECLARE_META_INTERFACE(MediaPlayerService)                               \    static const android::String16 descriptor;                          \    static android::sp<IMediaPlayerService> asInterface(                       \            const android::sp<android::IBinder>& obj);                  \    virtual const android::String16& getInterfaceDescriptor() const;    \    IMediaPlayerService();                                                     \    virtual ~IMediaPlayerService();                                            \

  • 4)  使用IMPLEMENT_META_INTERFACE,自动提供第3)里所缺少方法的实现。
IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.media.IMediaPlayerService");

#define IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.media.IMediaPlayerService")                       \    const android::String16 IMediaPlayerService::descriptor("android.media.IMediaPlayerService");             \    const android::String16&                                            \            IMediaPlayerService::getInterfaceDescriptor() const {              \        return IMediaPlayerService::descriptor;                                \    }                                                                   \    android::sp<IMediaPlayerService> IMediaPlayerService::asInterface(                \            const android::sp<android::IBinder>& obj)                   \    {                                                                   \        android::sp<IMediaPlayerService> intr;                                 \        if (obj != NULL) {                                              \            intr = static_cast<IMediaPlayerService*>(                          \                obj->queryLocalInterface(                               \                        IMediaPlayerService::descriptor).get());               \            if (intr == NULL) {                                         \                intr = new BpMediaPlayerService(obj);                          \            }                                                           \        }                                                               \        return intr;                                                    \    }                                                                   \    IMediaPlayerService::IMediaPlayerService() { }                                    \    IMediaPlayerService::~IMediaPlayerService() { }                                   \

Proxy端:

有了具有共性的接口类定义之后,剩下的就是分别实现Proxy与Stub端了。我们可以先来看Proxy端的实现,从IInterface里的定义里可以看到,同样出于代码重用的目的,Proxy端的代码都将源自BpInterface模板类,只需要实现接口方法即可。我们通过BpInterface模板套用到接口IMediaPlayerService之上,就得到了我们需要的BpMediaPlayerService类,然后在BpMediaPlayerService类里实现具体的接口方法,把接口方法转换成Binder命令的发送操作,Proxy端的实现便完成了。

class BpMediaPlayerService: public BpInterface<IMediaPlayerService>{public:    BpMediaPlayerService(const sp<IBinder>& impl)        : BpInterface<IMediaPlayerService>(impl)    {    }    virtual sp<IMediaMetadataRetriever> createMetadataRetriever()    {        Parcel data, reply;        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());        remote()->transact(CREATE_METADATA_RETRIEVER, data, &reply);        return interface_cast<IMediaMetadataRetriever>(reply.readStrongBinder());    }    virtual sp<IMediaPlayer> create(            const sp<IMediaPlayerClient>& client, audio_session_t audioSessionId) {        Parcel data, reply;        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());        data.writeStrongBinder(IInterface::asBinder(client));        data.writeInt32(audioSessionId);        remote()->transact(CREATE, data, &reply);        return interface_cast<IMediaPlayer>(reply.readStrongBinder());    }    virtual sp<IMediaRecorder> createMediaRecorder(const String16 &opPackageName)    {        Parcel data, reply;        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());        data.writeString16(opPackageName);        remote()->transact(CREATE_MEDIA_RECORDER, data, &reply);        return interface_cast<IMediaRecorder>(reply.readStrongBinder());    }    virtual sp<IOMX> getOMX() {        Parcel data, reply;        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());        remote()->transact(GET_OMX, data, &reply);        return interface_cast<IOMX>(reply.readStrongBinder());    }    virtual sp<IHDCP> makeHDCP(bool createEncryptionModule) {        Parcel data, reply;        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());        data.writeInt32(createEncryptionModule);        remote()->transact(MAKE_HDCP, data, &reply);        return interface_cast<IHDCP>(reply.readStrongBinder());    }    virtual void addBatteryData(uint32_t params) {        Parcel data, reply;        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());        data.writeInt32(params);        remote()->transact(ADD_BATTERY_DATA, data, &reply);    }    virtual status_t pullBatteryData(Parcel* reply) {        Parcel data;        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());        return remote()->transact(PULL_BATTERY_DATA, data, reply);    }    virtual sp<IRemoteDisplay> listenForRemoteDisplay(const String16 &opPackageName,            const sp<IRemoteDisplayClient>& client, const String8& iface)    {        Parcel data, reply;        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());        data.writeString16(opPackageName);        data.writeStrongBinder(IInterface::asBinder(client));        data.writeString8(iface);        remote()->transact(LISTEN_FOR_REMOTE_DISPLAY, data, &reply);        return interface_cast<IRemoteDisplay>(reply.readStrongBinder());    }    virtual sp<IMediaCodecList> getCodecList() const {        Parcel data, reply;        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());        remote()->transact(GET_CODEC_LIST, data, &reply);        return interface_cast<IMediaCodecList>(reply.readStrongBinder());    }};
在BpMediaPlayerService类实现里,我们也可以拓展其构造或是析构方法来处理一些私有属性。但最重要的是,一定要在BpMediaPlayerService类里通过虚拟继承实现所有的接口方法,比如我们在IMediaPlayerService接口里定义的createMetadataRetriever(),并且在这一方法里将该方法转换成Binder命令的发送与返回值的处理。除此之外,其他具有共性的部分,都会由系统来完成,比如BpInterface会继承自BpRefBase,通过remote()方法返回的也是BpRefBase,但BpRefBase最终会引用到BpBinder对象,最终通过这一BpBinder命令将Binder命令发送出去。

Stub端:

对于Stub端的实现,无论是Java环境里还是C++实现的Native环境,所有的消息分发处理的接口都是onTransact()回调方法。于是,整个Stub端实现就会是基于BnInterface模板,然后再覆盖其onTransact()方法。对于我们例子里的BnMediaPlayerService,由会有如下的实现:

class BnMediaPlayerService: public BnInterface<IMediaPlayerService>{public:    virtual status_t    onTransact( uint32_t code,                                    const Parcel& data,                                    Parcel* reply,                                    uint32_t flags = 0);};//覆盖OnTransact()方法status_t BnMediaPlayerService::onTransact(    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){    switch (code) {        case CREATE: {            CHECK_INTERFACE(IMediaPlayerService, data, reply);            sp<IMediaPlayerClient> client =                interface_cast<IMediaPlayerClient>(data.readStrongBinder());            audio_session_t audioSessionId = (audio_session_t) data.readInt32();            sp<IMediaPlayer> player = create(client, audioSessionId);            reply->writeStrongBinder(IInterface::asBinder(player));            return NO_ERROR;        } break;        case CREATE_MEDIA_RECORDER: {            CHECK_INTERFACE(IMediaPlayerService, data, reply);            const String16 opPackageName = data.readString16();            sp<IMediaRecorder> recorder = createMediaRecorder(opPackageName);            reply->writeStrongBinder(IInterface::asBinder(recorder));            return NO_ERROR;        } break;        case CREATE_METADATA_RETRIEVER: {            CHECK_INTERFACE(IMediaPlayerService, data, reply);            sp<IMediaMetadataRetriever> retriever = createMetadataRetriever();            reply->writeStrongBinder(IInterface::asBinder(retriever));            return NO_ERROR;        } break;        case GET_OMX: {            CHECK_INTERFACE(IMediaPlayerService, data, reply);            sp<IOMX> omx = getOMX();            reply->writeStrongBinder(IInterface::asBinder(omx));            return NO_ERROR;        } break;        case MAKE_HDCP: {            CHECK_INTERFACE(IMediaPlayerService, data, reply);            bool createEncryptionModule = data.readInt32();            sp<IHDCP> hdcp = makeHDCP(createEncryptionModule);            reply->writeStrongBinder(IInterface::asBinder(hdcp));            return NO_ERROR;        } break;        case ADD_BATTERY_DATA: {            CHECK_INTERFACE(IMediaPlayerService, data, reply);            uint32_t params = data.readInt32();            addBatteryData(params);            return NO_ERROR;        } break;        case PULL_BATTERY_DATA: {            CHECK_INTERFACE(IMediaPlayerService, data, reply);            pullBatteryData(reply);            return NO_ERROR;        } break;        case LISTEN_FOR_REMOTE_DISPLAY: {            CHECK_INTERFACE(IMediaPlayerService, data, reply);            const String16 opPackageName = data.readString16();            sp<IRemoteDisplayClient> client(                    interface_cast<IRemoteDisplayClient>(data.readStrongBinder()));            if (client == NULL) {                reply->writeStrongBinder(NULL);                return NO_ERROR;            }            String8 iface(data.readString8());            sp<IRemoteDisplay> display(listenForRemoteDisplay(opPackageName, client, iface));            reply->writeStrongBinder(IInterface::asBinder(display));            return NO_ERROR;        } break;        case GET_CODEC_LIST: {            CHECK_INTERFACE(IMediaPlayerService, data, reply);            sp<IMediaCodecList> mcl = getCodecList();            reply->writeStrongBinder(IInterface::asBinder(mcl));            return NO_ERROR;        } break;        default:            return BBinder::onTransact(code, data, reply, flags);    }}

BnMediaPlayerService这个Stub实现,BnInterface模板套用到IMediaPlayerService接口类上得到的类,然后再实现自己的onTransact()。在我们这个例子里将BnMediaPlayerService定义与onTranscat()实现分开来,但把两者写到一起是一回事。


在前面的Binder底层分析里我们知道, IPCThreadState对象会捕获底层的Binder命令,然后回调到onTransact()方法处理这一命令,于是在onTranscat()里只需要根据传入的code进行命令的分发与处理即可。比如我们例子里,当检查到命令的code是CREATE_MEDIA_RECORDER,也就是我们在IMediaPlayerService接口类里定义的Binder命令,会根据这一命令调用到createMediaRecorder()方法,然后再将结果通过reply这一Parcel传回给调用端,这样就完成了远程调用的实现。最后,缕缕进行一次IoC反向调用到父类的onTransact(),从而可以处理一些通用的Binder命令。

但到此,我们的Native Service实现并不完整,我们在Stub端并没有提供createMediaRecorder()方法的实现,这样BnMediaPlayerService这个类是无法被实例化成具体的对象,从而响应远程请求。


于是,我们通过继承BnMediaPlayerService,然后再实现接口方法createMediaRecorder(),这一新的对象便可被实例化成为一个具体的对象。这样做的目的进一步将Binder处理相关代码与具体的实现拆分开,我们可以得到在命名和实现上更加清晰的MediaPlayerService:

class MediaPlayerService : public BnMediaPlayerService{    class Client;    //...public:    static  void                instantiate();    // IMediaPlayerService interface    virtual sp<IMediaRecorder>  createMediaRecorder(const String16 &opPackageName);    void    removeMediaRecorderClient(wp<MediaRecorderClient> client);    virtual sp<IMediaMetadataRetriever> createMetadataRetriever();    virtual sp<IMediaPlayer>    create(const sp<IMediaPlayerClient>& client,                                       audio_session_t audioSessionId);    virtual sp<IMediaCodecList> getCodecList() const;    virtual sp<IOMX>            getOMX();    virtual sp<IHDCP>           makeHDCP(bool createEncryptionModule);    virtual sp<IRemoteDisplay> listenForRemoteDisplay(const String16 &opPackageName,            const sp<IRemoteDisplayClient>& client, const String8& iface);    virtual status_t            dump(int fd, const Vector<String16>& args);            void                removeClient(wp<Client> client);            bool                hasClient(wp<Client> client);

MediaPlayerService继承自BnMediaPlayerService,又提供了所需要的接口方法,于是任何被系统调度到的可执行部分,无论是线程还是进程,都可以通过实例化一个MediaPlayerService对象响应远程的createMediaRecorder()的调用请求。在代码的实现角度,一般IMediaPlayerService会在一个独立的源文件存放,以标明这是一个接口类,而MediaPlayerService会列入到另一个MediaPlayerService.cpp以说明这一个Service的具体实现。虽然不是强制要求,但这样的实现会更符合android里的编码习惯,更容易维护。

但需要注意的是,IMediaPlayerService接口类会通过IMPLEMENT_META_INTERFACE()这个宏来设置descriptor,于是在整个系统环境里, 由某个descriptor来标识的Service必然会是唯一的。比如某个进程已经通过自己的ProcessState加入到了Binder域,则加入这一新加入的Binder处理只需要如下的简单两行,一行创建MediaPlayerService对象并加入到ServiceManager的管理,另一行启动MediaPlayerService的Binder线程:

void MediaPlayerService::instantiate() {    defaultServiceManager()->addService(            String16("media.player"), new MediaPlayerService());}


frameworks\av\media\mediaserver\main_mediaserver.cpp:

int main(int argc __unused, char **argv __unused){    signal(SIGPIPE, SIG_IGN);    sp<ProcessState> proc(ProcessState::self());    sp<IServiceManager> sm(defaultServiceManager());    ALOGI("ServiceManager: %p", sm.get());    InitializeIcuOrDie();    MediaPlayerService::instantiate();    ResourceManagerService::instantiate();    registerExtensions();    ProcessState::self()->startThreadPool();    IPCThreadState::self()->joinThreadPool();}


为了减小Native Service在编程上的工作量,在Binder里还会有另一个BinderService相关的实现,也会使用模板的方式进一步节省代码的工作量,见frameworks/base/include/binder/BinderService.h:

template<typename SERVICE>class BinderService{public:    static status_t publish(bool allowIsolated = false) {        sp<IServiceManager> sm(defaultServiceManager());        return sm->addService(                String16(SERVICE::getServiceName()),                new SERVICE(), allowIsolated);    }    static void publishAndJoinThreadPool(bool allowIsolated = false) {        publish(allowIsolated);        joinThreadPool();    }    static void instantiate() { publish(); }    static status_t shutdown() { return NO_ERROR; }private:    static void joinThreadPool() {        sp<ProcessState> ps(ProcessState::self());        ps->startThreadPool();        ps->giveThreadPoolName();        IPCThreadState::self()->joinThreadPool();    }};

使用这一BinderService模板,便我们的代码进一步被简化,比如我们在Android系统内见到不会接触到IPCThreadState和ProcessState对象,在定义NativeService时,一般会使用这样的方式,比如AudioFlinger:

class AudioFlinger :    public BinderService<AudioFlinger>,    public BnAudioFlinger{    friend class BinderService<AudioFlinger>;   // for AudioFlinger()}
于是在某个进程里,我们就只需要最简单一行:


在:frameworks\av\media\audioserver\main_audioserver.cpp

int main(int argc __unused, char **argv){    signal(SIGPIPE, SIG_IGN);        sp<ProcessState> proc(ProcessState::self());        sp<IServiceManager> sm = defaultServiceManager();        ALOGI("ServiceManager: %p", sm.get());        AudioFlinger::instantiate();        AudioPolicyService::instantiate();        RadioService::instantiate();        SoundTriggerHwService::instantiate();        ProcessState::self()->startThreadPool();        IPCThreadState::self()->joinThreadPool();    }

 NativeService是由libbinder提供的一种机制,相当于是Java环境Remote Service的底层”Hack”实现。而通过Native Service,我们得到Java环境所不具备的一些新的特质:

  • 1)  性能更高。性能上的差异性取决于执行时的不同上下文环境,但通常来说,Native代码总会有比Java这种解释型语言高得多的执行效率。
  • 2)  使用同一种语言编程,更加容易理解与调试。Java语言不能直接进行系统调用,必须透过JNI来调用C代码来访问系统功能。而NativeService则完全不同,C++具备直接进行系统调用的能力,于是在访问操作系统或是硬件功能时,不再需要JNI,可以直接进行调用,代码实现上会更加统一。
  • 3)  自动化GC,Native态的Binder,与Java协作时被自动切入到Dalvik虚拟机的GC管理,也能使用类似于Java环境的自动化垃圾回收。同时,这种GC机制可以通过RefBase进行进一步拓展。
  • 4)  缺点:不能使用AIDL,编码工作量更大。
  • 5)  缺点:跟Java的Binder域编程环境功能重叠,也有可能会出错。比如Binder命令的定义,在Java与Native Service交互时,在Java环境与C++环境都要有各自一份拷贝。

综合所有的这些因素,虽然Native Service有一定的局限性,但带来的好处要更多。于是在Android的版本变更过程中,NativeService使用越来越普遍。


总结下:




0 0
原创粉丝点击