Android(安卓)Binder入门指南之Binder相关的接口和类
Android Binder入门指南之Binder相关的接口和类
前言
前面的篇章Android Binder机制(二) Binder中的数据结构对我们要攀登的Binder机制中将要牵涉到的数据结构(包括应用层的和内核层的)做了非常详细的讲解和阐述。本篇幅重点要突破的是Binder机制中相关的接口和类,我们知道Android的绝大部分跨进程通信机制都是基于Binder的,正所谓做戏得全套,Binder也不列外,这种机制不但会在底层C++的世界使用,也会在上层Java的世界使用,所以必须提供Java和C++两个层次的支持。当然这些Android的妈咪谷歌都为我们考虑到了。
在正式开始正文介绍前附上本篇相关代码的所在文件的路径。
frameworks/base/core/java/android/os/IBinder.javaframeworks/base/core/java/android/os/Binder.javaframeworks/base/core/java/android/os/IInterface.javaframeworks/native/include/binder/IBinder.hframeworks/native/libs/binder/Binder.cppframeworks/native/include/binder/Binder.hframeworks/native/include/binder/BpBinder.hframeworks/native/libs/binder/BpBinder.cppsystem/core/include/utils/RefBase.hframeworks/native/include/binder/IInterface.hframeworks/native/include/binder/ProcessState.hframeworks/native/libs/binder/ProcessState.cppframeworks/native/include/binder/IPCThreadState.hframeworks/native/libs/binder/IPCThreadState.cpp
注意:本文是基于Android 7.1版本进行介绍的!
1. Java层次的Binder接口和类
Java层级Binder相关的接口和类并不是很多,因为Binder其实大部分的重头戏都是在C++层和内核层,常见的接口和类有IBinder接口、IInterface接口,Binder类,BinderProxy类等。
1.1 IBinder
Android要求所有的Binder实体都必须实现IBinder接口,其文件在Android源码的路径是frameworks/base/core/java/android/os/IBinder.java,该接口的定义截选如下:
public interface IBinder {... public String getInterfaceDescriptor() throws RemoteException; public boolean pingBinder(); public boolean isBinderAlive(); public IInterface queryLocalInterface(String descriptor); public void dump(FileDescriptor fd, String[] args) throws RemoteException; public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException; public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ResultReceiver resultReceiver) throws RemoteException; public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException; public interface DeathRecipient { public void binderDied(); } public void linkToDeath(DeathRecipient recipient, int flags) throws RemoteException; public boolean unlinkToDeath(DeathRecipient recipient, int flags);}
1.2 IInterface
IInterface接口比较简单,其源码路径为仅仅单单定义了一个方法,不管是服务端还是客户端都需要实现该接口
public interface IInterface {IBinder asBinder();}
1.3 BinderProxy
BinderProxy是IBinder的子类,客户端进程持有关联的服务的的BinderProxy对象从而完成相关的远程服务调用,其底层相对应的C++层的BpBinder后续会介绍。
final class BinderProxy implements IBinder { public native boolean pingBinder(); public native boolean isBinderAlive(); public IInterface queryLocalInterface(String descriptor) { return null; } public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { Binder.checkParcel(this, code, data, "Unreasonably large binder buffer"); if (Binder.isTracingEnabled()) { Binder.getTransactionTracker().addTrace(); } return transactNative(code, data, reply, flags); } public native String getInterfaceDescriptor() throws RemoteException; public native boolean transactNative(int code, Parcel data, Parcel reply, int flags) throws RemoteException;...}
1.4 Binder
Binder也是IBinder的子类,Java层提供服务的Server进程持有一个Binder对象从而完成跨进程间通信。
public class Binder implements IBinder { public String getInterfaceDescriptor() { return mDescriptor; } public IInterface queryLocalInterface(String descriptor) { if (mDescriptor.equals(descriptor)) { return mOwner; } return null; }protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { ... } public final boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { if (false) Log.v("Binder", "Transact: " + code + " to " + this); if (data != null) { data.setDataPosition(0); } boolean r = onTransact(code, data, reply, flags); if (reply != null) { reply.setDataPosition(0); } return r; }}
Java层次中,与Binder相关的接口或类的继承关系如下:
在实际开发使用中,我们并不需要编写上图的XXXXNative、XXXXProxy,它们会由ADT根据我们编写的aidl脚本自动生成。但是最好能掌握手撕什么相关的类实现,这样对于更好的理解和掌握BInd非常有帮助的。用户只需继承XXXXNative编写一个具体的XXXXService即可,这个XXXXService就是远程通信的服务实体类,而XXXXProxy则是其对应的代理类。
关于Java层次的binder组件,我们就先说这么多,主要是先介绍一个大概。就研究跨进程通信而言,其实质内容基本上都在C++层次,Java层次只是一个壳而已。以后我会写专文来打通Java层次和C++层次,看看它们是如何通过JNI技术关联起来的。现在我们还是把注意力集中在C++层次吧。
2. C++层次的相关接口和类
在C++层次,就能看到各种关于Binder博客中经常反复肯定会被提到的BpBinder类和BBinder了,这两个类都继承于IBinder。当然还有IInterface,BpInterface,BnInterface,BpRefBase,ProcessState ,IPCThreadState ,下面我们来分别进行简单的介绍,在正式介绍前先奉上一关于上述几个接口和类之前的关系图,这就好比相亲之前得让介绍人先给个对方的照片,看过以后才能确定是否有进一步发展的空间不是!
2.1 IBinder
它定义在frameworks/native/include/binder/IBinder.h中。IBinder也是一个抽象出来的类,它包括了localBinder(), remoteBinder()和transact()等非常重要的接口。IBinder有两个直接子类类:BpBinder和BBinder。
class IBinder : public virtual RefBase{public:... IBinder(); virtual sp<IInterface> queryLocalInterface(const String16& descriptor); virtual const String16& getInterfaceDescriptor() const = 0; virtual bool isBinderAlive() const = 0; virtual status_t pingBinder() = 0; virtual status_t dump(int fd, const Vector<String16>& args) = 0; static status_t shellCommand(const sp<IBinder>& target, int in, int out, int err, Vector<String16>& args, const sp<IResultReceiver>& resultReceiver); virtual status_t transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) = 0; class DeathRecipient : public virtual RefBase { public: virtual void binderDied(const wp<IBinder>& who) = 0; }; virtual status_t linkToDeath(const sp<DeathRecipient>& recipient, void* cookie = NULL, uint32_t flags = 0) = 0; virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient, void* cookie = NULL, uint32_t flags = 0, wp<DeathRecipient>* outRecipient = NULL) = 0; virtual bool checkSubclass(const void* subclassID) const; typedef void (*object_cleanup_func)(const void* id, void* obj, void* cleanupCookie); virtual void attachObject( const void* objectID, void* object, void* cleanupCookie, object_cleanup_func func) = 0; virtual void* findObject(const void* objectID) const = 0; virtual void detachObject(const void* objectID) = 0; virtual BBinder* localBinder(); virtual BpBinder* remoteBinder();protected: virtual ~IBinder();private:};
2.2 BpBinder和BBinder
BpBinder和BBinder是相互对应的,可以算是一对兄弟组合,下面分别来介绍一下:
(1). BpBinder:是Binder代理类。通过remoteBinder()可以获取BpBinder对象;而且,对于C++层而言,它相当于一个远程Binder。BpBinder的事务接口transact()会调用IPCThreadState的transact(),进而实现与Binder驱动的事务交互。此外,BpBinder中有一个mHandle句柄成员,它用来保存Server位于Binder驱动中的"Binder引用的描述"。句柄0是ServiceManager的句柄。
class BpBinder : public IBinder{public: BpBinder(int32_t handle); inline int32_t handle() const { return mHandle; } ... virtual status_t transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); ...virtual BpBinder* remoteBinder();private: const int32_t mHandle; ...}
(2).BBinder:是本地Binder。通过localBinder()可以获取BBinder对象。当Server收到请求之后,会调用BBinder的onTransact()函数进行处理。而不同的Server会重载onTransact()函数,从而可以根据各自的情况对事务进行处理。
class BBinder : public IBinder{public: BBinder(); virtual const String16& getInterfaceDescriptor() const; virtual bool isBinderAlive() const; virtual status_t pingBinder();... virtual status_t transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);... virtual BBinder* localBinder();protected: virtual ~BBinder(); virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);private: BBinder(const BBinder& o);...};
2.3 RefBase和BpRefBase
如果说BpBinder和BBinder是兄弟组合,那么RefBase和BpRefBase就是父子组合了,下面分别就两位来一个全方位的展示:
(1).RefBase:它定义在system/core/include/utils/RefBase.h中。RefBase是一个公共父类,它声明了许多常用的接口。包括增加引用计数,获取引用计数,新增对象的弱引用等接口,其中比较重要的方法是onFirstRef(),在Android的Native世界里面你会惊奇的发现许多C++的初始化工作都是在onFirstRef()里面执行的,不信可以搜搜试试。
class RefBase{public: void incStrong(const void* id) const; void decStrong(const void* id) const; void forceIncStrong(const void* id) const; int32_t getStrongCount() const; class weakref_type { public: RefBase* refBase() const; void incWeak(const void* id); void decWeak(const void* id); ... }; ...protected: RefBase(); virtual ~RefBase(); ... virtual void onFirstRef();...};
(2).BpRefBase:它定义在frameworks/native/include/binder/Binder.h中。BpRefBase继承于RefBase,它有一个IBinder*类型的成员mRemote,同时提供了获取该mRemote的方法。实际上,该mRemote就是BpBinder对象。
class BpRefBase : public virtual RefBase{protected: 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() { return mRemote; } inline IBinder* remote() const { return mRemote; }private: BpRefBase(const BpRefBase& o); BpRefBase& operator=(const BpRefBase& o); IBinder* const mRemote;//这就是那个很重要的mRemote RefBase::weakref_type* mRefs; std::atomic<int32_t> mState;};
2.4 IInterface
它定义在frameworks/native/include/binder/IInterface.h中。和RefBase类似,它也是一个公共父类,IInterface中声明了asBinder()方法,用于获取对象的IBinder对象。
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;};
2.5 BpInterface和BnInterface
(1).BpInterface:它定义在frameworks/native/include/binder/IInterface.h中。实际上,BpInterface是一个模板类,同时继承了BpRefBase和INTERFACE,这里的INTERFACE是模板。像IServiceManager,IMediaPlayerService等Server都是通过继承模板类是实现的,相关的代码如下:
template<typename INTERFACE>class BpInterface : public INTERFACE, public BpRefBase{public: BpInterface(const sp<IBinder>& remote);protected: virtual IBinder* onAsBinder();};
(2).BnInterface:它定义在frameworks/native/include/binder/IInterface.h中。和BpInterface类似,BnInterface也是一个模板类,它同时继承了BBinder和INTERFACE。像BnServiceManager,BnMediaPlayerService等本地Server都是通过继承模板类是实现的,相关的代码如下:
template<typename INTERFACE>class BnInterface : public INTERFACE, public BBinder{public: virtual sp<IInterface> queryLocalInterface(const String16& _descriptor); virtual const String16& getInterfaceDescriptor() const;protected: virtual IBinder* onAsBinder();};
前面篇幅的章节一和章节二让我们对Java层和C++层的Binder有关的类有了一个比较清晰的认识,但是还是比较模糊是不,那么可以通过下面的示意图来一个清晰的整体概括,通过该示意图我们应该能大致上了解Java和C++层的Binder怎么关联起来了。
3.ProcessState
它的源码定义在它定义在frameworks/native/libs/binder/ProcessState.cpp中。对于开发Android app的读者来说,在Android上层架构中,谷歌妈咪已经很大幅度地弱化了进程的概念了。应用开发的小伙伴能看到的主要是四大组件的概念了,再也找不到以前熟悉的main()函数了。然而,底层程序(C++层次)毕竟还是得跑在一个个进程之上,现在我们就来看底层进程是如何运用Binder机制来完成跨进程通信的。
在每个进程中,会有一个全局的ProcessState对象。这个很容易理解,ProcessState的字面意思不就是“进程状态”吗,ProcessState的实例是采用单例模式实现的,我们截选其中的一部分重要的:
class ProcessState : public virtual RefBase{public: static sp<ProcessState> self(); ... void startThreadPool(); ... void spawnPooledThread(bool isMain); status_t setThreadPoolMaxThreadCount(size_t maxThreads);private: friend class IPCThreadState; ... struct handle_entry { IBinder* binder; RefBase::weakref_type* refs; }; handle_entry* lookupHandleLocked(int32_t handle); int mDriverFD; void* mVMStart; mutable Mutex mLock; // protects everything below. Vector<handle_entry> mHandleToObject; ... KeyedVector<String16, sp<IBinder> > mContexts; ...};
它拥有两个非常重要的成员:mDriverFD和mHandleToObject,我们知道,Binder内核被设计成一个驱动程序,所以ProcessState里专门搞了个mDriverFD域,来记录binder驱动对应的句柄值,以便随时和binder驱动通信。ProcessState对象采用了典型的单例模式,在一个应用进程中,只会有唯一的一个ProcessState对象,它将被进程中的多个线程共用,因此每个进程里的线程其实是共用所打开的那个驱动句柄(mDriverFD)的,示意图如下:
每个进程基本上都是这样的结构,组合起来的示意图就是:
而mHandleToObject是一个Vector矢量数组,它的定义如下:
Vector<handle_entry> mHandleToObject;
矢量数组中的每个元素都保存了两个变量:Server的句柄,以及Server对应的BpBinder对象。实际上,Server的句柄是"Server在Binder驱动中的Binder引用的描述";句柄0是ServiceManager的句柄。其中的binder域,记录的就是BpBinder对象。
4.IPCThreadState
它定义在frameworks/native/libs/binder/IPCThreadState.cpp中中。IPCThreadState的实例也是采用单例模式实现的,它是正在与Binder驱动进行交互的类,和Binder内核层的binder_thread相对应
class IPCThreadState{public: static IPCThreadState* self();... sp<ProcessState> process(); ... void joinThreadPool(bool isMain = true); // Stop the local process. void stopProcess(bool immediate = true); status_t transact(int32_t handle, uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);...private: IPCThreadState(); ~IPCThreadState(); status_t sendReply(const Parcel& reply, uint32_t flags); status_t waitForResponse(Parcel *reply, status_t *acquireResult=NULL); status_t talkWithDriver(bool doReceive=true); status_t writeTransactionData(int32_t cmd, uint32_t binderFlags, int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer); status_t getAndExecuteCommand(); status_t executeCommand(int32_t command); void processPendingDerefs(); void clearCaller(); static void threadDestructor(void *st); static void freeBuffer(Parcel* parcel, const uint8_t* data, size_t dataSize, const binder_size_t* objects, size_t objectsSize, void* cookie); const sp<ProcessState> mProcess; const pid_t mMyThreadId;...};
总结
理解上面的基本概念之后,我们现在就从整体上对涉及到的Binder概念对它们进行一下总结和概括!对于一个Server而言,它都会存在一个"远程BpBinder对象"和"本地BBinder对象"。
(01) 远程BpBinder对象的作用:是和Binder驱动进行交互。具体的方式是,当Server要向Binder发起事务请求时,会调用BpBinder的transact()接口,而该接口会调用到IPCThreadState::transact()接口,通过IPCThreadState类来和Binder驱动交互。此外,该BpBinder在Binder驱动中的Binder引用的描述会被保存到ProcessState的mHandleToObject矢量缓冲数组中。
(02) 本地BBinder对象的作用:是Server响应Client请求的类。当Client有请求发送给Server时,都会调用到BBinder的onTransact()函数,而每个Server都会覆盖onTransact()函数。这样,每个Server就可以在onTransact()中根据自己的情况对请求进行处理。
更多相关文章
- 类和 Json对象
- 打造Android的中文Siri语音助手(一)——小I机器人的接口
- 图解 Android(安卓)Handler 线程消息机制
- Android(安卓)绑定Service 实现android控制service的生命周期
- Android,谁动了我的内存
- Android(安卓)HIDL第一个HelloWorld demo
- 【如何在不同Android设备中得到有效的AudioRecord实例】
- Android(安卓)Activity应用窗口的创建过程分析
- 图解 Android(安卓)Handler 线程消息机制