美文网首页
Binder NDK接口介绍

Binder NDK接口介绍

作者: Little熊猫 | 来源:发表于2019-03-06 14:59 被阅读0次

    一 binder NDK接口使用

    从android Q开始,binder添加了ndk使用的接口,相关使用接口示例如下:
    iface.h

    class IFoo : public virtual ::android::RefBase {
       public:
        static const char* kSomeInstanceName;
        static const char* kInstanceNameToDieFor;
    
        static AIBinder_Class* kClass;
    
        // Takes ownership of IFoo
        binder_status_t addService(const char* instance);
        static ::android::sp<IFoo> getService(const char* instance, AIBinder** outBinder = nullptr);
    
        enum Call {
            DOFOO = FIRST_CALL_TRANSACTION + 0,
            DIE = FIRST_CALL_TRANSACTION + 1,
        };
    
        virtual ~IFoo();
    
        virtual binder_status_t doubleNumber(int32_t in, int32_t* out) = 0;
        virtual binder_status_t die() = 0;
    
       private:
        // this variable is only when IFoo is local (since this test combines 'IFoo' and 'BnFoo'), not
        // for BpFoo.
        AIBinder_Weak* mWeakBinder = nullptr;
    };
    

    iface.cpp

    truct IFoo_Class_Data {
        sp<IFoo> foo;
    };
    
    void* IFoo_Class_onCreate(void* args) {
        IFoo_Class_Data* foo = static_cast<IFoo_Class_Data*>(args);
        // This is a foo, but we're currently not verifying that. So, the method newLocalBinder is
        // coupled with this.
        return static_cast<void*>(foo);
    }
    
    void IFoo_Class_onDestroy(void* userData) {
        delete static_cast<IFoo_Class_Data*>(userData);
    }
    
    binder_status_t IFoo_Class_onTransact(AIBinder* binder, transaction_code_t code, const AParcel* in,
                                          AParcel* out) {
        binder_status_t stat = STATUS_FAILED_TRANSACTION;
    
        sp<IFoo> foo = static_cast<IFoo_Class_Data*>(AIBinder_getUserData(binder))->foo;
        CHECK(foo != nullptr) << "Transaction made on already deleted object";
    
        switch (code) {
            case IFoo::DOFOO: {
                int32_t valueIn;
                int32_t valueOut;
                stat = AParcel_readInt32(in, &valueIn);
                if (stat != STATUS_OK) break;
                stat = foo->doubleNumber(valueIn, &valueOut);
                if (stat != STATUS_OK) break;
                stat = AParcel_writeInt32(out, valueOut);
                break;
            }
            case IFoo::DIE: {
                stat = foo->die();
                break;
            }
        }
    
        return stat;
    }
    
    AIBinder_Class* IFoo::kClass = AIBinder_Class_define(kIFooDescriptor, IFoo_Class_onCreate,
                                                         IFoo_Class_onDestroy, IFoo_Class_onTransact);
    
    class BpFoo : public IFoo {
       public:
        explicit BpFoo(AIBinder* binder) : mBinder(binder) {}
        virtual ~BpFoo() { AIBinder_decStrong(mBinder); }
    
        virtual binder_status_t doubleNumber(int32_t in, int32_t* out) {
            binder_status_t stat = STATUS_OK;
    
            AParcel* parcelIn;
            stat = AIBinder_prepareTransaction(mBinder, &parcelIn);
            if (stat != STATUS_OK) return stat;
    
            stat = AParcel_writeInt32(parcelIn, in);
            if (stat != STATUS_OK) return stat;
    
            ::ndk::ScopedAParcel parcelOut;
            stat = AIBinder_transact(mBinder, IFoo::DOFOO, &parcelIn, parcelOut.getR(), 0 /*flags*/);
            if (stat != STATUS_OK) return stat;
    
            stat = AParcel_readInt32(parcelOut.get(), out);
            if (stat != STATUS_OK) return stat;
    
            return stat;
        }
    
        virtual binder_status_t die() {
            binder_status_t stat = STATUS_OK;
    
            AParcel* parcelIn;
            stat = AIBinder_prepareTransaction(mBinder, &parcelIn);
    
            ::ndk::ScopedAParcel parcelOut;
            stat = AIBinder_transact(mBinder, IFoo::DIE, &parcelIn, parcelOut.getR(), 0 /*flags*/);
    
            return stat;
        }
    
       private:
        // Always assumes one refcount
        AIBinder* mBinder;
    };
    
    IFoo::~IFoo() {
        AIBinder_Weak_delete(mWeakBinder);
    }
    
    binder_status_t IFoo::addService(const char* instance) {
        AIBinder* binder = nullptr;
    
        if (mWeakBinder != nullptr) {
            // one strong ref count of binder
            binder = AIBinder_Weak_promote(mWeakBinder);
        }
        if (binder == nullptr) {
            // or one strong refcount here
            binder = AIBinder_new(IFoo::kClass, static_cast<void*>(new IFoo_Class_Data{this}));
            if (mWeakBinder != nullptr) {
                AIBinder_Weak_delete(mWeakBinder);
            }
            mWeakBinder = AIBinder_Weak_new(binder);
        }
    
        binder_status_t status = AServiceManager_addService(binder, instance);
        // Strong references we care about kept by remote process
        AIBinder_decStrong(binder);
        return status;
    }
    
    sp<IFoo> IFoo::getService(const char* instance, AIBinder** outBinder) {
        AIBinder* binder = AServiceManager_getService(instance);  // maybe nullptr
        if (binder == nullptr) {
            return nullptr;
        }
    
        if (!AIBinder_associateClass(binder, IFoo::kClass)) {
            AIBinder_decStrong(binder);
            return nullptr;
        }
    
        if (outBinder != nullptr) {
            AIBinder_incStrong(binder);
            *outBinder = binder;
        }
    
        if (AIBinder_isRemote(binder)) {
            sp<IFoo> ret = new BpFoo(binder);  // takes ownership of binder
            return ret;
        }
    
        IFoo_Class_Data* data = static_cast<IFoo_Class_Data*>(AIBinder_getUserData(binder));
    
        CHECK(data != nullptr);  // always created with non-null data
    
        sp<IFoo> ret = data->foo;
    
        AIBinder* held = AIBinder_Weak_promote(ret->mWeakBinder);
        CHECK(held == binder);
        AIBinder_decStrong(held);
    
        AIBinder_decStrong(binder);
        return ret;
    }
    

    使用

    class MyTestFoo : public IFoo {
        binder_status_t doubleNumber(int32_t in, int32_t* out) override {
            *out = 2 * in;
            LOG(INFO) << "doubleNumber (" << in << ") => " << *out;
            return STATUS_OK;
        }
        binder_status_t die() override {
            ADD_FAILURE() << "die called on local instance";
            return STATUS_OK;
        }
    };
    
    TEST(NdkBinder, GetServiceInProcess) {
        static const char* kInstanceName = "test-get-service-in-process";
    
        sp<IFoo> foo = new MyTestFoo;
        EXPECT_EQ(STATUS_OK, foo->addService(kInstanceName));
    
        sp<IFoo> getFoo = IFoo::getService(kInstanceName);
        EXPECT_EQ(foo.get(), getFoo.get());
    
        int32_t out;
        EXPECT_EQ(STATUS_OK, getFoo->doubleNumber(1, &out));
        EXPECT_EQ(2, out);
    }
    

    二 binder ndk引入的原因

    为什么要引入binder ndk的接口呢? 答案很简单就是使用简单。像iface.h和iface.cpp 这两个文件完全可以通过aidl文件自动生成,接口使用简单,ABI稳定。谷歌相关的commit log

    Initial C library for libbinder.
    
    This creates a simple wrapper around libbinder with a stable C ABI. It
    also embeds the concept of an IBinder and IBinder transactions into the
    ABI so that parts of their transactions can be changed and considered
    implementation details of libbinder. With this basic class, you can
    create a service, use it with primitive data types, but it does not yet
    suppport the entire range of binder objects.
    

    相关文章

      网友评论

          本文标题:Binder NDK接口介绍

          本文链接:https://www.haomeiwen.com/subject/jdotpqtx.html