Introdução ao BpBinder, BnBinder e IInterface do Princípio do Binder

Um: Introdução ao mecanismo de encadernação

O mecanismo Binder é um mecanismo de comunicação entre processos fornecido pelo sistema Android. O processo Cliente espera se comunicar com o processo Servidor, mas por ser um processo cruzado, ele precisa se comunicar com o processo do driver Binder.

O Binder consiste nos seguintes módulos:

    * Driver de fichário

    * Processo Binder Servidor-Servidor

    * Processo Binder Cliente-Cliente

    * ServiceManager - Gerente

O modelo de comunicação do Binder é o seguinte:

 Dois: Crie um modelo de serviço

Se você deseja criar um Serviço, você precisa que o Servidor herde BnInterface e o Cliente herde BpInterface. Especificamente, pode ser representado pela seguinte figura:

Declarações relacionadas a Bn, Bp podem ser encontradas nos seguintes documentos

frameworks/native/libs/binder/include/binder/IInterface.h

frameworks/native/libs/binder/include/binder/IBinder.h

 O código específico é o seguinte

frameworks/native/libs/binder/include/binder/IInterface.h
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;
};
-----------------------------------------------------------
class BnInterface : public INTERFACE, public BBinder
{
public:
    virtual sp<IInterface>      queryLocalInterface(const String16& _descriptor);
    virtual const String16&     getInterfaceDescriptor() const;

protected:
    typedef INTERFACE           BaseInterface;
    virtual IBinder*            onAsBinder();
};

frameworks/native/libs/binder/include/binder/Binder.h
class BBinder : public IBinder
{
public:
                        BBinder();

    virtual const String16& getInterfaceDescriptor() const;
    virtual bool        isBinderAlive() const;
    virtual status_t    pingBinder();
...
};
frameworks/native/libs/binder/include/binder/IBinder.h
class [[clang::lto_visibility_public]] IBinder : public virtual RefBase
{
public:
    enum {
        FIRST_CALL_TRANSACTION = 0x00000001,
        LAST_CALL_TRANSACTION = 0x00ffffff,
...
};
-------------------------------------------------------------------
class BpInterface : public INTERFACE, public BpRefBase
{
public:
    explicit                    BpInterface(const sp<IBinder>& remote);

protected:
    typedef INTERFACE           BaseInterface;
    virtual IBinder*            onAsBinder();
};

frameworks/native/libs/binder/include/binder/Binder.h
class BpRefBase : public virtual RefBase
{
protected:
    explicit                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() const { return mRemote; }//返回的是BpBinder
    inline sp<IBinder> remoteStrong() const { return sp<IBinder>::fromExisting(mRemote); ...

 Três: O transportador de transferência de dados entre processos - Parcela

O código do Parcel está localizado no diretório a seguir e o Parcel é usado para transferir dados entre processos. Quer o Cliente envie dados para o Servidor ou o Servidor envie dados para o Cliente, eles são transmitidos através do Parcel.

frameworks/native/include/binder/Parcel.h

frameworks/native/include/binder/Parcel.cpp

escreva interfaces relacionadas:

    status_t            write(const void* data, size_t len);
    status_t            writeInt32(int32_t val);
    status_t            writeUint32(uint32_t val);
    status_t            writeInt64(int64_t val);
    status_t            writeUint64(uint64_t val);
    status_t            writeFloat(float val);
    status_t            writeDouble(double val);
    status_t            writeStrongBinder(const sp<IBinder>& val);
    status_t            writeInt32Array(size_t len, const int32_t *val);
    status_t            writeByteArray(size_t len, const uint8_t *val);
    status_t            writeBool(bool val);
    status_t            writeChar(char16_t val);
    status_t            writeByte(int8_t val);
......

 leia interfaces relacionadas:

    status_t            read(void* outData, size_t len) const;
    const void*         readInplace(size_t len) const;
    int32_t             readInt32() const;
    status_t            readInt32(int32_t *pArg) const;
    uint32_t            readUint32() const;
    status_t            readUint32(uint32_t *pArg) const;
    int64_t             readInt64() const;
    status_t            readInt64(int64_t *pArg) const;
    uint64_t            readUint64() const;
    status_t            readUint64(uint64_t *pArg) const;
    float               readFloat() const;
    status_t            readFloat(float *pArg) const;
    double              readDouble() const;
    status_t            readDouble(double *pArg) const;
    bool                readBool() const;
    status_t            readBool(bool *pArg) const;
    char16_t            readChar() const;
    status_t            readChar(char16_t *pArg) const;
    int8_t              readByte() const;
    status_t            readByte(int8_t *pArg) const;
......

Por exemplo, como transferir dados através do Parcel no serviço nativo, conforme mostrado abaixo, são todos transferidos através do Parcel.

class BpCustomizeManagerService : public BpInterface<ICustomizeManagerService>
{
public:
    explicit BpCustomizeManagerService (const sp<IBinder>& impl)
      : BpInterface <ICustomizeManagerService>(impl)
    {
        ALOGD("create Service \n");
    }

    int customeize(int size){
        Parcel data, reply;
        data.writeInterfaceToken(ICustomizeManagerService::getInterfaceDescriptor());
        data.writeInt32(size);
        remote()->transact(CUSTOMIZE, data, &reply);
        return reply.readInt32();
    }
};

status_t BnCustomizeManagerService ::onTransact(uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags){
    switch (code)
    {
        case CUSTOMIZE:
        {
            CHECK_INTERFACE(ICustomizeManagerService, data, reply);
            int size = data.readInt32();
            int ret = customeize(size);
            //函数返回值从Server传递给Client
            reply->writeInt32();
            return NO_ERROR;
        }
...
};

Acho que você gosta

Origin blog.csdn.net/weixin_41028555/article/details/130379626
Recomendado
Clasificación