Binder 関連クラス
Android のネイティブレイヤのサービスを実装するには、以下のような Binder 関連クラスを使用します。
継承構造
RefBase
… 各種オブジェクトの生存期間を参照カウンタIBinder
… サービスの基底クラス。プロセス間通信の共通インタフェースとしても使われる。BpBinder
… クライアント側のプロキシクラス(ServiceManager が自動的にインスタンスを生成する)BBinder
… サービスの基底クラス(基本的な実装を提供)BnInterface
IInterface
… クライアントに提供するサービスインタフェースの基底クラスBpRefBase
BpInterface
… クライアントに提供するサービスインタフェースの実装
ポイント
- (a) サービスクラスは
BBinder
をサブクラス化して作成する。 - (b) サービスにアクセスするインタフェースは
IInterface
をサブクラス化して作成する。 - (c) サービスにアクセスするインタフェースの実装は
BpInterface
をサブクラス化して作成する。
(a) さえ準備してサービスを立ち上げれば、クライアントは IBinder
インタフェースでサービスにアクセスできるようになります。
(b)、(c) はまともなサービスインタフェースとしてクライアントに公開する場合に必要です。
ファイルのパス
- クラス定義
- frameworks/base/include/binder/Binder.h (
BBinder
,BpRefBase
) - frameworks/base/include/binder/BpBinder.h (
BpBinder
) - frameworks/base/include/binder/IBinder.h (
IBinder
) - frameworks/base/include/binder/IInterface.h (
IInterface
,BnInterface
,BpInterface
) - frameworks/base/include/utils/RefBase.h (
RefBase
) - frameworks/base/include/utils/StrongPointer.h (
sp
)
- frameworks/base/include/binder/Binder.h (
- 実装
- frameworks/base/libs/binder/BpBinder.cpp
- frameworks/base/libs/binder/IInterface.cpp
- frameworks/base/libs/utils/RefBase.cpp
Binder 関連クラスをざっと眺めてみる
RefBase
RefBase
クラスは、すべての Binder 関連クラスの基底クラスで、インスタンスの生存期間をリファレンスカウンタで管理しています。
IInteface
IInterface
クラスは、ユーザが定義するサービスのインタフェースのベースクラスになります。
class IInterface : public virtual RefBase {
public:
sp<IBinder> asBinder();
sp<const IBinder> asBinder() const;
protected:
virtual IBinder* onAsBinder() = 0;
};
class IEchoService : public IInterface {
public:
virtual int add(int lhs, int rhs);
};
IInterface
クラスには、サービスへアクセスするための IBinder
オブジェクトを取得するための asBinder()
メソッドが実装されています。
この中で使用している onAsBinder()
メソッドは、pure virtual メソッドなので、サービス側で実装する必要があります。
sp<IBinder> IInterface::asBinder() {
return this ? onAsBinder() : NULL;
}
sp<const IBinder> IInterface::asBinder() const {
return this ? const_cast<IInterface*>(this)->onAsBinder() : NULL;
}
asBinder()
は、スマートポインタである sp
クラスのインスタンスを返すため、IBinder
オブジェクトは参照カウンタを使って自動的に生存期間が制御されます。
IBinder
class IBinder : public virtual RefBase {
public:
virtual sp<IInterface> queryLocalInterface(const String16& descriptor);
virtual const String16& getInterfaceDescriptor() const = 0;
virtual bool isBinderAlive() const = 0;
virtual status_t pingBinder() = 0;
- queryLocalInterface を使用して、名前指定で IInterface オブジェクトを取得できる。
- queryLocalInterface は、テンプレートクラス BnInterface を継承したサブクラスを作成することで容易に実装できる。
BBinder
BBinder
クラスは IBinder
を継承しており、BBinder::transact()
の中で abstract method である onTransact()
を呼び出すようになっています。
この onTransact()
を実装するようにすれば OK です。
class BBinder : public IBinder {
public:
virtual const String16& getInterfaceDescriptor() const;
virutal bool isBinderAlive() const;
virtual status_t pingBinder();
virtual status_t dump(int fd, const Vector<String16>& args);
virtual status_t transact(...);
virtual status_t linkToDeath(...);
virtual status_t unlinkToDeath(...);
virtual void attachObject(...);
virtual void* findObject(const void* objectID) const;
virtual void detachObject(const void* objectID);
virtual BBinder* localBinder();
protected:
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
...
};
BpInterface
template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase {
...
};
BnInterface
template<typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder {
...
};
こんな感じで使います。
class BnMyClass : public BnInterface<IMyClass> {
public:
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
};