看了老罗的Binder源码分析实在是有点难懂,驱动的分析因为没有基础所以看起来很吃力,但android在native层给我们封装了快速实现Binder应用的库,在此记录,以作查用。
分析媒体框架发现,我们要实现一个IPC服务,大体可以总结为以下几步。
1、获得ServiceManager。
2、实现Service并把自己加入ServiceManager中。
3、进入等待,并接受Client的请求。
其中大多的方法和实现Android都有现成的可以调用,我们只要实现第2步,即实现自己Service。
下面我们就具体实践:
首先肯定会有一个C++程序,类似于main_MediaService的入口
int main(int argc, char** argv) { sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm = defaultServiceManager(); MediaPlayerService::instantiate(); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); }
定义XXX接口
XXX接口是和XXX服务相关,例如提供getXXX , setXXX函数,和应用逻辑相关。
需要从IInterface派生
class IXXX: public IInterface { public: DECLARE_META_INTERFACE(XXX);申明宏 virtual getXXX() = 0; virtual setXXX() = 0; }这是一个接口。
我们声明了一个 DECLARE_META_INTERFACE(XXX) 的宏,他的定义在IInterface.h中,展开看看
class IXXX: public IInterface { 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(); virtual getXXX() = 0; virtual setXXX() = 0; }
为了把IXXX加入到Binder结构中去,需要定义BnXXX和对客户端透明的BpXXX。
既然要透明我们就要把BpXXX放在cpp中实现。
BnXXX是需要头文件的,可以把它和IXXX定义放在一块,分开也行,我们把他放入一个文件IXXX.h 文件中。
class BnXXX: public BnInterface<IXXX> { public: virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); //由于IXXX是个纯虚类,而BnXXX只实现了onTransact函数,所以BnXXX依然是一个纯虚类 };
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(); };
兑现后为
class BnXXX: public IXXX, public BBinder { public: virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);//这样BnXXX就拥有了IXXX以下的方法: 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(); virtual getXXX() = 0; virtual setXXX() = 0; };
接着我们在某个CPP中实现他们,IXXX.cpp :
IMPLEMENT_META_INTERFACE(XXX, "android.xxx.IXXX");//IMPLEMENT宏 status_t BnXXX::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { case GET_XXX: { CHECK_INTERFACE(IXXX, data, reply); //读请求参数 //调用虚函数getXXX() return NO_ERROR; } break; case SET_XXX: { CHECK_INTERFACE(IXXX, data, reply); //读请求参数 //调用虚函数getXXX() return NO_ERROR; } }
展开并兑现了看看...
const android::String16 I##INTERFACE::descriptor(NAME); \ 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 != NULL) { \ intr = static_cast<I##INTERFACE*>( \ obj->queryLocalInterface( \ I##INTERFACE::descriptor).get()); \ if (intr == NULL) { \ intr = new Bp##INTERFACE(obj); \ } \ } \ return intr; \ } \ I##INTERFACE::I##INTERFACE() { } \ I##INTERFACE::~I##INTERFACE() { } status_t BnXXX::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { ... } }
class BpXXX: public BpInterface<IXXX> { public: BpXXX (const sp<IBinder>& impl): BpInterface< IXXX >(impl) //定义调用父类的构造 { } vitural getXXX() { Parcel data, reply; data.writeInterfaceToken(IXXX::getInterfaceDescriptor()); data.writeInt32(pid); remote()->transact(GET_XXX, data, &reply); return; } vitural setXXX() { Parcel data, reply; data.writeInterfaceToken(IXXX::getInterfaceDescriptor()); data.writeInt32(pid); remote()->transact(SET_XXX, data, &reply); return; } }
class BpInterface : public INTERFACE, public BpRefBase { public: BpInterface(const sp<IBinder>& remote); protected: virtual IBinder* onAsBinder(); };
兑现为:
class BpXXX: public IXXX, BpRefBase { public: BpXXX (const sp<IBinder>& impl): BpInterface<IXXX>(impl) { //调用父类BpInterface构造,BpInterface又调用父类BpRefBase的构造(这层实现是通过IInterface 的内联函数重载了的), BpRefBase只是简单的把 imp 保存在自己的成员变量中mRemote, 子类可以调用他的remote()函数把他返回出来,另作他用 } vitural getXXX() //继承自 IXXX方法 { ... remote()->transact(GET_XXX, data, &reply); ... } vitural setXXX() //继承自 IXXX方法 { ... remote()->transact(SET_XXX, data, &reply); ... } protected: virtual IBinder* onAsBinder(); //实现与IInterface 内联函数,只是调用父类BpRefBase.remote()返回 impl对象 }
XXXClient::getService() { sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> binder = sm->getService(String16("android.xxx.IXXX")); sp<IXXX> service = interface_cast<IXXX>(binder); //interface_cast<IXXX>(binder) 等于 IXXX.asInterface(binder) , 定义在IInterface return service; }