1. 程式人生 > >C++ Binder機制學習

C++ Binder機制學習

核心內容

Binder機制的核心實際上和Android中的Handler傳送訊息的機制很像,在Binder中負責發訊息的是繼承了BpInterface的子類,負責處理訊息的是BnInterface的子類

傳送訊息的具體函式是

remote()->transact();

處理訊息的具體函式是

onTransact();

基礎知識

  • BpInterface和BpBinder中的p表示的意思就是proxy,表示中間的呼叫和代理,不會具體實現功能
  • BnInterface和BBinder中的n表示的意思就是native 是最終實現的地方
  • BpBinder類由client來繼承,當然,如果用不上的話,也可以不用繼承
  • 如果一個類如果想使用android中的智慧指標,就必須繼承或者間接繼承RefBase類,比如client

繼承關係

  • 定義一個介面類IDemo,繼承IInterface
  • 定義一個BnDemoService類,繼承BnInterface<IDemo>
  • 定義一個BpDemoService類,繼承BpInterface<IDemo>
  • 定義一個DemoService類,繼承BnDemoService,用來實現具體的函式

具體的實現

定義一個介面類IDemo,繼承IInterface,裡面只有一個函式

class IDemo :public IInterface
{
    public:
        virtual int getAge();
}

定義一個BnDemoService類,繼承BnInterface<IDemo>

class BnDemoService: public BnInterface<IDemo>
{
    public:
        virtual status_t onTransact(uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags= 0 );
};

status_t BnDemoService::onTransact(uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags)
{
	switch(code)
		{
			case CUSTOM_CODE:
				{
					CHECK_INTERFACE(IDemo,data,reply);
					int res = getAge();
					reply->writeInt32((int32_t)res);
					return NO_ERROR;
				}
				break;
			default:
	            break;
	   }
	return BBinder::onTransact(code, data, reply, flags);
}

定義一個BpDemoService類,繼承BpInterface,<IDemo>

enum
{
	CUSTOM_CODE = IBinder::FIRST_CALL_TRANSACTION
};
class BpDemoService: public BnInterface<IDemo>
{
    public:
        BpDemoService(const sp<IBinder>& impl):BpInterface<IDemo> (impl){};
        virtual BOOL getAge()
		{
			Parcel data, reply;
		    data.writeInterfaceToken(IDemo::getInterfaceDescriptor());
		    remote()->transact(CUSTOM_CODE, data, &reply);
			return (BOOL)reply.readInt32();
		}
}

定義一個Service類,繼承BnDemoService,用來具體實現函式,最後記得別忘了呼叫IMPLEMENT_META_INTERFACE巨集來進行註冊

class DemoService : public BnDemoService,public BinderService<DemoService>
{
    public:
        int getAge();
}
IMPLEMENT_META_INTERFACE(DemoService, "demo.service");

呼叫順序

  • 在client端呼叫的時候,首先獲取ServiceManager
  • 然後建立一個binder用來裝載service
  • 使用interface_cast()來獲得對應的代理端
  • 通過代理端呼叫在service中實現的函式
sp < IServiceManager > sm = defaultServiceManager();
sp < IBinder > binder;
binder = sm->getService(String16("demo.service"));
sp<IDemo> m_pDemoService;
m_pDemoService = interface_cast<IDemo> (binder);
m_pDemoService->getAge();

重點函式

interface_cast()函式

作用是把從getService獲取到的Binder強制轉換為IInterface的子類,也就是定義了自己的那些介面的類
函式原型

template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
    return INTERFACE::asInterface(obj);
}

asInterface這個函式是IMPLEMENT_META_INTERFACE巨集中進行定義的。具體可以參考

#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \
    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);/* IMPORTENT */           \
            }                                                           \
        }                                                               \
        return intr;                                                    \
    }                                                                   \
    I##INTERFACE::I##INTERFACE() { }                                    \
    I##INTERFACE::~I##INTERFACE() { }         

也就是說interface_cast函式最後返回的實際上是new BpDemoService(binder);


remote()->transact()函式

位置是在代理類中呼叫的,用來遠端給onTransact函式傳送訊息和資料的,類似於handler.sendMessage()
函式原型

status_t BBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

onTransact()函式的位置是在實現類(實現BnInterface)中的,相當於hander中的handleMessage函式
函式原型
virtual status_t onTransact(uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags= 0 );