当前位置: 移动技术网 > 移动技术>移动开发>Android > Android记之语言Binder

Android记之语言Binder

2020年07月13日  | 移动技术网移动技术  | 我要评论

理解Binder设计

以我的理解,先有Android后有Binder,Binder就像是Android这个世界的语言。Binder目前的设计是为了满足Android的需求,Linux现存的进程间通信机制不满足Android的需求。Android的Binder的进程间通信设计了类似C/S的架构,为了满足这样的结构设计,要定义client端和server端的”通信协议“,所以android中用接口的方式来定义,client和server要分别实现接口的方法。然后要实现两端的通信,那么就要使用binder驱动,Android中使用IBinder来对binder驱动进行抽象,然后client端使用BpBinder来和binder驱动接口通信,server端使用BBinder来和binder通信。以上就是Binder的总体设计,从概念来理解很简单,但是真正实现还是弯弯绕绕,我们就以AudioFlinger为例,按照上面的思路就来看具体设计。

先设计接口(IAudioFlinger)

IAudioFlinger的接口声明如下:

class IAudioFlinger : public IInterface
{
public:
    DECLARE_META_INTERFACE(AudioFlinger);
	...
	virtual     status_t    setMasterVolume(float value) = 0;
	...
}

接口设计为纯虚函数,继承类要实现这些方法,这样接口接定义了C/S两端的接口,Client端调用了setMasterVolume,就相当于调用了Server的setMasterVolume,对于应用开发来说非常方便。
接下来就要为这个接口分别加上C/S的Binder通信接口。

Server端加上通信接口

声明的接口代码看起来也很简单:

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

    // Requests media.log to start merging log buffers
    virtual void requestLogMerge() = 0;
};

这里透露出来的重要信息有两部分:

  1. BnInterface:模板类,封装了Binder接口
  2. onTransact:解析code,然后调用到对应的方法,如:setMasterVolume

BnInterface

template<typename INTERFACE>
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();
};

BBinder和IBinder

class BBinder : public IBinder-----------IBinder就是个接口
{
...
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);-------又看到了onTransact
...
}

onTransact

status_t BnAudioFlinger::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
	...
	switch (code) {
	...
	    case SET_MASTER_VOLUME: {
            CHECK_INTERFACE(IAudioFlinger, data, reply);
            reply->writeInt32( setMasterVolume(data.readFloat()) );
            return NO_ERROR;
        } break;
	...
	}
	...
}

这是onTransact的最终实现,server端肯定有一个循环一直在调用onTransact,那么是在哪里呢,在桥梁那一节我们就可以看到
setMasterVolume最终的实现没有在BnAudioFlinger,而是在AudioFlinger中,继续看

Server端实现接口(AudioFlinger)

实现接口就很简单了,先声明

class AudioFlinger :
    public BinderService<AudioFlinger>,
    public BnAudioFlinger
{
...
    static const char* getServiceName() ANDROID_API { return "media.audio_flinger"; }
    ...
	virtual     status_t    setMasterVolume(float value);
...
}

具体实现:

status_t AudioFlinger::setMasterVolume(float value)
{
    status_t ret = initCheck();
    if (ret != NO_ERROR) {
        return ret;
    }

    // check calling permissions
    if (!settingsAllowed()) {
        return PERMISSION_DENIED;
    }

    Mutex::Autolock _l(mLock);
    mMasterVolume = value;

    // Set master volume in the HALs which support it.
    for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
        AutoMutex lock(mHardwareLock);
        AudioHwDevice *dev = mAudioHwDevs.valueAt(i);

        mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
        if (dev->canSetMasterVolume()) {
            dev->hwDevice()->setMasterVolume(value);
        }
        mHardwareStatus = AUDIO_HW_IDLE;
    }

    // Now set the master volume in each playback thread.  Playback threads
    // assigned to HALs which do not have master volume support will apply
    // master volume during the mix operation.  Threads with HALs which do
    // support master volume will simply ignore the setting.
    for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
        if (mPlaybackThreads.valueAt(i)->isDuplicating()) {
            continue;
        }
        mPlaybackThreads.valueAt(i)->setMasterVolume(value);
    }

    return NO_ERROR;
}

Server向ServiceManager注册服务

系统起来后,每个server都会向ServiceManager注册自己,一般都是在main_*.cpp中实现,以audioserver来举例:

int main(int argc __unused, char **argv)
{
...
	AudioFlinger::instantiate();--------注册audioflinger服务
    AudioPolicyService::instantiate();
...
    IPCThreadState::self()->joinThreadPool();---这里实现循环,一直调用onTransact,具体在桥梁一节分析
}

我们来看看AudioFlinger::instantiate的具体实现,还记得上面的BinderService吗,audioflinger继承于它:

template<typename SERVICE>
class BinderService
{
public:
    static status_t publish(bool allowIsolated = false,
                            int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) {
        sp<IServiceManager> sm(defaultServiceManager());
        return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated,
                              dumpFlags);
    }
    ...
    static void instantiate() { publish(); }
}

代码很清晰,通过sm->addService来注册自己"media.audio_flinger"

Client端的实现

IAudioFlinger.cpp

class BpAudioFlinger : public BpInterface<IAudioFlinger>
{
public:
    explicit BpAudioFlinger(const sp<IBinder>& impl)---------impl是要传入的BpBinder
        : BpInterface<IAudioFlinger>(impl)
    {
    }
    ...
    virtual status_t setMasterVolume(float value)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
        data.writeFloat(value);
        remote()->transact(SET_MASTER_VOLUME, data, &reply);--------通过remote来进行binder通信
        return reply.readInt32();
    }
}

上面的Bp也就是Binder Proxy,而Bn就是Bindernative。上面就是Client端的实现,每个用户使用的话都会new BpAudioFlinger,而且要传入一个参数,这个参数就是client端的Binder接口BpBinder,下面两个小节就以这两个疑问展开,在此之前,我们先把BpInterface模板类看完。

BpInterface

IInterface.h

template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase
{
public:
    explicit                    BpInterface(const sp<IBinder>& remote);

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

template<typename INTERFACE>
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
    : BpRefBase(remote)----------------------------------------------------impl传入到这里,impl==remote
{
}

Binder.cpp

BpRefBase::BpRefBase(const sp<IBinder>& o)
    : mRemote(o.get()), mRefs(nullptr), mState(0)----------------------remote传给mRemote
{
    extendObjectLifetime(OBJECT_LIFETIME_WEAK);

    if (mRemote) {
        mRemote->incStrong(this);           // Removed on first IncStrong().
        mRefs = mRemote->createWeak(this);  // Held for our entire lifetime.
    }
}

最终我们得出mRemote就是BpBinder,而且我们看到BpAudioFlinger每个函数里面传输数据都会调用remote()来进行,再来看看BpRefBase的声明:
Binder.h

class BpRefBase : public virtual RefBase
{
...
    inline  IBinder*        remote()                { return mRemote; }
    inline  IBinder*        remote() const          { return mRemote; }

private:
...
    IBinder* const          mRemote;
...
};

获取BpBinder

好了,继续聊上面的两个疑问。首先,我们要知道谁会去获取AudioFlinger的client,答案是AudioSystem,有一个封装好的接口:

const sp<IAudioFlinger> AudioSystem::get_audio_flinger()
{
    sp<IAudioFlinger> af;
    sp<AudioFlingerClient> afc;
    {
        Mutex::Autolock _l(gLock);
        if (gAudioFlinger == 0) {
            sp<IServiceManager> sm = defaultServiceManager();
            sp<IBinder> binder;
            do {
                binder = sm->getService(String16("media.audio_flinger"));---------从servceManager获取我们要的BpBinder
                if (binder != 0)
                    break;
                ALOGW("AudioFlinger not published, waiting...");
                usleep(500000); // 0.5 s
            } while (true);
            if (gAudioFlingerClient == NULL) {
                gAudioFlingerClient = new AudioFlingerClient();
            } else {
                if (gAudioErrorCallback) {
                    gAudioErrorCallback(NO_ERROR);
                }
            }
            binder->linkToDeath(gAudioFlingerClient);
            gAudioFlinger = interface_cast<IAudioFlinger>(binder);-----------重要的事情来了,创建BpAudioFlinger
            LOG_ALWAYS_FATAL_IF(gAudioFlinger == 0);
            afc = gAudioFlingerClient;
            // Make sure callbacks can be received by gAudioFlingerClient
            ProcessState::self()->startThreadPool();
        }
        af = gAudioFlinger;
    }
    if (afc != 0) {
        int64_t token = IPCThreadState::self()->clearCallingIdentity();
        af->registerClient(afc);
        IPCThreadState::self()->restoreCallingIdentity(token);
    }
    return af;
}

new Bp##INTERFACE(new BpAudioFlinger)

从上面知道了一个重要的模板函数interface_cast

template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
    return INTERFACE::asInterface(obj);
}

实例化后就是调用IAudioFlinger::asInterface(obj),又回到了IAudioFlinger,我们再从头看一下这个函数是怎么实现的吧,下面就不得不说两个重要的宏定义了

  • DECLARE_META_INTERFACE--------------------------声明
#define DECLARE_META_INTERFACE(INTERFACE)                               \
public:                                                                 \
    static const ::android::String16 descriptor;                        \
    static ::android::sp<I##INTERFACE> asInterface(                     \
            const ::android::sp<::android::IBinder>& obj);              \
    virtual const ::android::String16& getInterfaceDescriptor() const;  \
    I##INTERFACE();                                                     \
    virtual ~I##INTERFACE();                                            \
    static bool setDefaultImpl(std::unique_ptr<I##INTERFACE> impl);     \
    static const std::unique_ptr<I##INTERFACE>& getDefaultImpl();       \
private:                                                                \
    static std::unique_ptr<I##INTERFACE> default_impl;                  \
public:                                                                 \

这个宏我们在IAudioFlinger接口设计那里已经看到过,这里我们看到了asInterface的声明,INTERFACE在本文就是IAudioFlinger

  • IMPLEMENT_META_INTERFACE(android10)-----定义
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \
    DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(INTERFACE, NAME)    \

#define DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(INTERFACE, NAME)\
    const ::android::StaticString16                                     \
        I##INTERFACE##_descriptor_static_str16(__IINTF_CONCAT(u, NAME));\
    const ::android::String16 I##INTERFACE::descriptor(                 \
        I##INTERFACE##_descriptor_static_str16);                        \
    const ::android::String16&                                          \
            I##INTERFACE::getInterfaceDescriptor() const {              \
        return I##INTERFACE::descriptor;                                \
    }                                                                   \
    ::android::sp<I##INTERFACE> I##INTERFACE::asInterface(              \
            const ::android::sp<::android::IBinder>& obj)               \
    {                                                                   \
        ::android::sp<I##INTERFACE> intr;                               \
        if (obj != nullptr) {                                           \
            intr = static_cast<I##INTERFACE*>(                          \
                obj->queryLocalInterface(                               \
                        I##INTERFACE::descriptor).get());               \
            if (intr == nullptr) {                                      \
                intr = new Bp##INTERFACE(obj);                          \
            }                                                           \
        }                                                               \
        return intr;                                                    \
    }                                                                   \
    std::unique_ptr<I##INTERFACE> I##INTERFACE::default_impl;           \
    bool I##INTERFACE::setDefaultImpl(std::unique_ptr<I##INTERFACE> impl)\
    {                                                                   \
        if (!I##INTERFACE::default_impl && impl) {                      \
            I##INTERFACE::default_impl = std::move(impl);               \
            return true;                                                \
        }                                                               \
        return false;                                                   \
    }                                                                   \
    const std::unique_ptr<I##INTERFACE>& I##INTERFACE::getDefaultImpl() \
    {                                                                   \
        return I##INTERFACE::default_impl;                              \
    }                                                                   \
    I##INTERFACE::I##INTERFACE() { }                                    \
    I##INTERFACE::~I##INTERFACE() { }                                   \

我们看一下asInterface的宏定义,首先检索对象是否已存在,如果为空,那么我们要找的东西就来了,new Bp##INTERFACE,目标达成。

桥梁(ProcessState/IPCThreadState)

上面分析了那么多,但是我们一直没看到具体操作binder驱动的接口。client通过transact来传输数据,而server端通过onTransact来处理数据,具体这两个接口是如何衔接上的呢。借着这两个问题,我们从BBinder和BpBinder这两个类说起,这两个类都继承于Binder的业务层接口IBinder。Client要传输数据,要调用transact,那么BpBinder的这个函数怎么实现呢?

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;
}

这里出现了一个重要的类IPCThreadState,这个类是用于每个线程来调用传输数据的,看下他的transact实现

status_t IPCThreadState::transact(int32_t handle,
                                  uint32_t code, const Parcel& data,
                                  Parcel* reply, uint32_t flags)
{
    ...
    err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, nullptr);
    ...
    if ((flags & TF_ONE_WAY) == 0) {
        ...
        if (reply) {
            err = waitForResponse(reply);
        } else {
            Parcel fakeReply;
            err = waitForResponse(&fakeReply);
        }
        ...
    } else {
        err = waitForResponse(nullptr, nullptr);
    }

    return err;
}
  • writeTransactionData:用于把数据打包parcel
  • waitForResponse:调用binder驱动接口进行数据传输,具体是在函数talkWithDriver中实现
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
    if (mProcess->mDriverFD < 0) {
        return -EBADF;
    }
    ...
    do {
        ...
        if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)-------Binder的ioctl接口实现数据传输
        ...
    } while (err == -EINTR);
    ...
}

这里看到了binder驱动的文件描述符,这是在另一个类ProcessState创建的时候打开的,IPCThreadState中的mProcess就保存了ProcessState,ProcessState每个进程只有一份,这样就没必要每个线程都去打开驱动

sp<ProcessState> ProcessState::self()
{
    Mutex::Autolock _l(gProcessMutex);
    if (gProcess != nullptr) {
        return gProcess;
    }
    gProcess = new ProcessState(kDefaultDriver);
    return gProcess;
}
ProcessState::ProcessState(const char *driver)
    : mDriverName(String8(driver))
    , mDriverFD(open_driver(driver))------------------打开binder驱动
    , mVMStart(MAP_FAILED)
    , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
    , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
    , mExecutingThreadsCount(0)
    , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
    , mStarvationStartTimeMs(0)
    , mBinderContextCheckFunc(nullptr)
    , mBinderContextUserData(nullptr)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
    , mCallRestriction(CallRestriction::NONE)
{
    ...
}

这样Client从业务层到驱动的调用顺序我们都清楚了,那么Server肯定也遵循这样的轨迹,通过BBinder的transact来调用IPCThreadState的transact进行数据传输,不过Server要执行一个loop来循环处理每条收到的数据并执行相应的命令来调用对应的函数。以AudioServer为例,在init的时候就会执行,我们来看看main函数的实现

int main(int argc __unused, char **argv)
{
    ...
    pid_t childPid;

    if (doLog && (childPid = fork()) != 0) {
        ...
    } else {
        ...
        sp<ProcessState> proc(ProcessState::self());--------------创建ProcessState并打开binder驱动
        sp<IServiceManager> sm = defaultServiceManager();---------获得Client ServiveManager
        ALOGI("ServiceManager: %p", sm.get());
        AudioFlinger::instantiate();------------------------------server AudioFlinger初始化
        AudioPolicyService::instantiate();------------------------server AudioPolicy初始化
        ...
        SoundTriggerHwService::instantiate();
        ProcessState::self()->startThreadPool();
        IPCThreadState::self()->joinThreadPool();-----------------循环处理
    }
}
void IPCThreadState::joinThreadPool(bool isMain)
{
    ...
    do {
        ...
        result = getAndExecuteCommand();循环处理每条命令
        ...
    } while (result != -ECONNREFUSED && result != -EBADF);
    ...
}

getAndExecuteCommand会调用talkWithDriver,收到数据后进行解析处理,然后调用executeCommand

status_t IPCThreadState::executeCommand(int32_t cmd)
{
    ...
    switch ((uint32_t)cmd) {
    case BR_ERROR:
    ...
    case BR_ACQUIRE:
    ...
    case BR_TRANSACTION:
    ...
            if (tr.target.ptr) {
                // We only have a weak reference on the target object, so we must first try to
                // safely acquire a strong reference before doing anything else with it.
                if (reinterpret_cast<RefBase::weakref_type*>(
                        tr.target.ptr)->attemptIncStrong(this)) {
                    error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,
                            &reply, tr.flags);
                    reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this);
                } else {
                    error = UNKNOWN_TRANSACTION;
                }

            } else {
                error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
            }
    ...
    }
}

调用BBinder->transact

status_t BBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    data.setDataPosition(0);

    status_t err = NO_ERROR;
    switch (code) {
        case PING_TRANSACTION:
            err = pingBinder();
            break;
        case EXTENSION_TRANSACTION:
            err = reply->writeStrongBinder(getExtension());
            break;
        case DEBUG_PID_TRANSACTION:
            err = reply->writeInt32(getDebugPid());
            break;
        default:
            err = onTransact(code, data, reply, flags);--------------好了,我们找到onTransact了
            break;
    }

    // In case this is being transacted on in the same process.
    if (reply != nullptr) {
        reply->setDataPosition(0);
    }

    return err;
}

本文地址:https://blog.csdn.net/l289123557/article/details/107134333

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网