Android记 - Binder语言

    技术2026-08-25  10

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

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

    BnInterface:模板类,封装了Binder接口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:用于把数据打包parcelwaitForResponse:调用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; }
    Processed: 0.012, SQL: 9