如何使用Binder实现分析

看了老罗的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依然是一个纯虚类
};

继承BnInterface<IXXX>是继承什么,他的定义同样在IInterface中。

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


IMPLEMENT_META_INTERFACE(XXX,"");定义在IInterface中。

展开并兑现了看看...

    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)
	{
		...
	}
    }


这样已兑现,该实现的都实现了,就只剩getXXX(), setXXX()应用逻辑需要我们实现。一个宏声明,一个宏实现,我们就把Binder接入自己的程序了,省去了很多步啊, 继续啊...
我们在asInterfance中看到,new Bp##INTERFACE(obj), 这个就是Client的获得proxy对象了,用来封装参数IPC到我们的进程中,它也实现在IXXX.cpp 文件中。

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


BpInterface<IXXX>的继承关系定义在IInterface中

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对象
}


到此为止我们就已经实现了自己定义的Service.
Client通过ServiceManager查询出我们的就可以调用我们提供的服务了

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

  • to be continued..










你可能感兴趣的:(如何使用Binder实现分析)