用android 模板,实现native service


  通过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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值