欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android记之语言Binder

程序员文章站 2022-06-16 18:41:52
理解binder设计binder是为了设计一套...

理解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