通过IInterface里定义的这些不太好理解的模板方法,使得编写一个Native Service的工作量也并不大.
http://blog.csdn.net/21cnbao/article/details/8087328
Proxy端:
\frameworks\av\media\libmedia\IMediaPlayerService.cpp:
class BpMediaPlayerService: public BpInterface<IMediaPlayerService>
{
public:
BpMediaPlayerService(const sp<IBinder>& impl)
: BpInterface<IMediaPlayerService>(impl)
{
}
在frameworks\native\include\binder\IInterface.h中定义
template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase
{
public:
BpInterface(const sp<IBinder>& remote);
protected:
virtual IBinder* onAsBinder();
};
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;
};
在:frameworks\av\include\media\IMediaPlayerService.h中定义:
class IMediaPlayerService: public IInterface
{
public:
DECLARE_META_INTERFACE(MediaPlayerService);
在:\frameworks\native\include\binder\Binder.h:
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;
RefBase::weakref_type* mRefs;
std::atomic<int32_t> mState;
};
在:\frameworks\native\include\binder\IBinder.h:
class IBinder : public virtual RefBase
{
public:
在:frameworks\native\include\binder\BpBinder.h
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);
在:frameworks\native\libs\binder\BpBinder.cpp
status_t BpBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
// Once a binder has died, it will never come back to life.
if (mAlive) {
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}
return DEAD_OBJECT;
}
在:frameworks\native\include\binder\IPCThreadState.h
class IPCThreadState
{
public:
sp<ProcessState> process();
status_t transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags);
Stub端:
在:\frameworks\av\media\libmediaplayerservice\MediaPlayerService.h:
class MediaPlayerService : public BnMediaPlayerService
{
class Client;
在:frameworks\av\include\media\IMediaPlayerService.h中定义:
class BnMediaPlayerService: public BnInterface<IMediaPlayerService>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
在frameworks\native\include\binder\IInterface.h中定义
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();
};
在:\frameworks\native\include\binder\Binder.h:
class BBinder : public IBinder
{
public:
BBinder();
virtual const String16& getInterfaceDescriptor() const;
virtual status_t transact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
以MediaPlayerService为例子:
在Native Service的类的继承关系上,所有加了颜色标识的部分,IMediaPlayerService接口类、BpInteface<IMediaPlayerService>和BnInterface<IMediaPlayerService>模板类、以及进一步派出来的BpMediaPlayerService和BnMediaPlayerService,都是需要手动实现的。
这样实现最终得到的结果,就是我们可以通过一个继承自BnMediaPlayerService的可实例化的类MediaPlayerService构造一个对象,这一对象便可以在其生存期内响应与处理Binder命令的请求。
而通过中间引入的一层BpMediaPlayerService,也可以自动地将客户端代码通过BpRefBase的引用自动生成。
作为所有实现的源头,于是我们需要定义IMediaPlayerService接口类:
enum {
CREATE = IBinder::FIRST_CALL_TRANSACTION,
CREATE_MEDIA_RECORDER,
CREATE_METADATA_RETRIEVER,
GET_OMX,
MAKE_HDCP,
ADD_BATTERY_DATA,
PULL_BATTERY_DATA,
LISTEN_FOR_REMOTE_DISPLAY,
GET_CODEC_LIST,
};
class IMediaPlayerService: public IInterface
{
public:
DECLARE_META_INTERFACE(MediaPlayerService);
virtual sp<IMediaRecorder> createMediaRecorder(const String16 &opPackageName) = 0;
virtual sp<IMediaMetadataRetriever> createMetadataRetriever() = 0;
virtual sp<IMediaPlayer> create(const sp<IMediaPlayerClient>& client,
audio_session_t audioSessionId = AUDIO_SESSION_ALLOCATE) = 0;
virtual sp<IOMX> getOMX() = 0;
virtual sp<IHDCP> makeHDCP(bool createEncryptionModule) = 0;
virtual sp<IMediaCodecList> getCodecList() const = 0;
// Connects to a remote display.
// 'iface' specifies the address of the local interface on which to listen for
// a connection from the remote display as an ip address and port number
// of the form "x.x.x.x:y". The media server should call back into the provided remote
// display client when display connection, disconnection or errors occur.
// The assumption is that at most one remote display will be connected to the
// provided interface at a time.
virtual sp<IRemoteDisplay> listenForRemoteDisplay(const String16 &opPackageName,
const sp<IRemoteDisplayClient>& client, const String8& iface) = 0;
virtual void addBatteryData(uint32_t params) = 0;
virtual status_t pullBatteryData(Parcel* reply) = 0;
};
作为兼用于Proxy与Stub的接口类定义的IInterface,实际上至少还需要定义Binder命令、asBinder()等基本方法。这时,我们就可以看到在IInterface定义里使用宏的好处了,我们这里只需要定义属于特性的部分,比如这一Native Service所需要的Binder命令,和支持这一Binder命令的远程接口方法,仅此而已。而其他部分的代码,并不需要我们直接实现,我们只需要使用DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE这两个宏来自动化生成这些共性的部分。于是,实现一个远程接口类,会是通过继承IInterface接口类,然后得到具体的接口类,比如我们这里的IMediaPlayerService。剩下的部分,会是如下四路的基本套路:
- 1) 定义Binder命令,而且命令都以IBinder::FIRST_CALL_TRANSACTION,也就是1开始;
- 2) 定义接口方法,也就是一个纯虚方法,比如
createMediaRecorder();
- 3) 通过DECLARE_META_INTERFACE,从而自动生成这一接口类所需要的通用属性与方法;
#define DECLARE_META_INTERFACE(MediaPlayerService) \
static const android::String16 descriptor; \
static android::sp<IMediaPlayerService> asInterface( \
const android::sp<android::IBinder>& obj); \
virtual const android::String16& getInterfaceDescriptor() const; \
IMediaPlayerService(); \
virtual ~IMediaPlayerService(); \
- 4) 使用IMPLEMENT_META_INTERFACE,自动提供第3)里所缺少方法的实现。
#define IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.media.IMediaPlayerService") \
const android::String16 IMediaPlayerService::descriptor("android.media.IMediaPlayerService"); \
const android::String16& \
IMediaPlayerService::getInterfaceDescriptor() const { \
return IMediaPlayerService::descriptor; \
} \
android::sp<IMediaPlayerService> IMediaPlayerService::asInterface( \
const android::sp<android::IBinder>& obj) \
{ \
android::sp<IMediaPlayerService> intr; \
if (obj != NULL) { \
intr = static_cast<IMediaPlayerService*>( \
obj->queryLocalInterface( \
IMediaPlayerService::descriptor).get()); \
if (intr == NULL) { \
intr = new BpMediaPlayerService(obj); \
} \
} \
return intr; \
} \
IMediaPlayerService::IMediaPlayerService() { } \
IMediaPlayerService::~IMediaPlayerService() { } \
Proxy端:
有了具有共性的接口类定义之后,剩下的就是分别实现Proxy与Stub端了。我们可以先来看Proxy端的实现,从IInterface里的定义里可以看到,同样出于代码重用的目的,Proxy端的代码都将源自BpInterface模板类,只需要实现接口方法即可。我们通过BpInterface模板套用到接口IMediaPlayerService之上,就得到了我们需要的BpMediaPlayerService类,然后在BpMediaPlayerService类里实现具体的接口方法,把接口方法转换成Binder命令的发送操作,Proxy端的实现便完成了。
class BpMediaPlayerService: public BpInterface<IMediaPlayerService>
{
public:
BpMediaPlayerService(const sp<IBinder>& impl)
: BpInterface<IMediaPlayerService>(impl)
{
}
virtual sp<IMediaMetadataRetriever> createMetadataRetriever()
{
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
remote()->transact(CREATE_METADATA_RETRIEVER, data, &reply);
return interface_cast<IMediaMetadataRetriever>(reply.readStrongBinder());
}
virtual sp<IMediaPlayer> create(
const sp<IMediaPlayerClient>& client, audio_session_t audioSessionId) {
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
data.writeStrongBinder(IInterface::asBinder(client));
data.writeInt32(audioSessionId);
remote()->transact(CREATE, data, &reply);
return interface_cast<IMediaPlayer>(reply.readStrongBinder());
}
virtual sp<IMediaRecorder> createMediaRecorder(const String16 &opPackageName)
{
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
data.writeString16(opPackageName);
remote()->transact(CREATE_MEDIA_RECORDER, data, &reply);
return interface_cast<IMediaRecorder>(reply.readStrongBinder());
}
virtual sp<IOMX> getOMX() {
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
remote()->transact(GET_OMX, data, &reply);
return interface_cast<IOMX>(reply.readStrongBinder());
}
virtual sp<IHDCP> makeHDCP(bool createEncryptionModule) {
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
data.writeInt32(createEncryptionModule);
remote()->transact(MAKE_HDCP, data, &reply);
return interface_cast<IHDCP>(reply.readStrongBinder());
}
virtual void addBatteryData(uint32_t params) {
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
data.writeInt32(params);
remote()->transact(ADD_BATTERY_DATA, data, &reply);
}
virtual status_t pullBatteryData(Parcel* reply) {
Parcel data;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
return remote()->transact(PULL_BATTERY_DATA, data, reply);
}
virtual sp<IRemoteDisplay> listenForRemoteDisplay(const String16 &opPackageName,
const sp<IRemoteDisplayClient>& client, const String8& iface)
{
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
data.writeString16(opPackageName);
data.writeStrongBinder(IInterface::asBinder(client));
data.writeString8(iface);
remote()->transact(LISTEN_FOR_REMOTE_DISPLAY, data, &reply);
return interface_cast<IRemoteDisplay>(reply.readStrongBinder());
}
virtual sp<IMediaCodecList> getCodecList() const {
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
remote()->transact(GET_CODEC_LIST, data, &reply);
return interface_cast<IMediaCodecList>(reply.readStrongBinder());
}
};
在BpMediaPlayerService类实现里,我们也可以拓展其构造或是析构方法来处理一些私有属性。但最重要的是,一定要在BpMediaPlayerService类里通过虚拟继承实现所有的接口方法,比如我们在IMediaPlayerService接口里定义的createMetadataRetriever(),并且在这一方法里将该方法转换成Binder命令的发送与返回值的处理。除此之外,其他具有共性的部分,都会由系统来完成,比如BpInterface会继承自BpRefBase,通过remote()方法返回的也是BpRefBase,但BpRefBase最终会引用到BpBinder对象,最终通过这一BpBinder命令将Binder命令发送出去。
Stub端:
对于Stub端的实现,无论是Java环境里还是C++实现的Native环境,所有的消息分发处理的接口都是onTransact()回调方法。于是,整个Stub端实现就会是基于BnInterface模板,然后再覆盖其onTransact()方法。对于我们例子里的BnMediaPlayerService,由会有如下的实现:
class BnMediaPlayerService: public BnInterface<IMediaPlayerService>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
//覆盖OnTransact()方法
status_t BnMediaPlayerService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch (code) {
case CREATE: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
sp<IMediaPlayerClient> client =
interface_cast<IMediaPlayerClient>(data.readStrongBinder());
audio_session_t audioSessionId = (audio_session_t) data.readInt32();
sp<IMediaPlayer> player = create(client, audioSessionId);
reply->writeStrongBinder(IInterface::asBinder(player));
return NO_ERROR;
} break;
case CREATE_MEDIA_RECORDER: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
const String16 opPackageName = data.readString16();
sp<IMediaRecorder> recorder = createMediaRecorder(opPackageName);
reply->writeStrongBinder(IInterface::asBinder(recorder));
return NO_ERROR;
} break;
case CREATE_METADATA_RETRIEVER: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
sp<IMediaMetadataRetriever> retriever = createMetadataRetriever();
reply->writeStrongBinder(IInterface::asBinder(retriever));
return NO_ERROR;
} break;
case GET_OMX: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
sp<IOMX> omx = getOMX();
reply->writeStrongBinder(IInterface::asBinder(omx));
return NO_ERROR;
} break;
case MAKE_HDCP: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
bool createEncryptionModule = data.readInt32();
sp<IHDCP> hdcp = makeHDCP(createEncryptionModule);
reply->writeStrongBinder(IInterface::asBinder(hdcp));
return NO_ERROR;
} break;
case ADD_BATTERY_DATA: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
uint32_t params = data.readInt32();
addBatteryData(params);
return NO_ERROR;
} break;
case PULL_BATTERY_DATA: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
pullBatteryData(reply);
return NO_ERROR;
} break;
case LISTEN_FOR_REMOTE_DISPLAY: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
const String16 opPackageName = data.readString16();
sp<IRemoteDisplayClient> client(
interface_cast<IRemoteDisplayClient>(data.readStrongBinder()));
if (client == NULL) {
reply->writeStrongBinder(NULL);
return NO_ERROR;
}
String8 iface(data.readString8());
sp<IRemoteDisplay> display(listenForRemoteDisplay(opPackageName, client, iface));
reply->writeStrongBinder(IInterface::asBinder(display));
return NO_ERROR;
} break;
case GET_CODEC_LIST: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
sp<IMediaCodecList> mcl = getCodecList();
reply->writeStrongBinder(IInterface::asBinder(mcl));
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
BnMediaPlayerService这个Stub实现,BnInterface模板套用到IMediaPlayerService接口类上得到的类,然后再实现自己的onTransact()。在我们这个例子里将BnMediaPlayerService定义与onTranscat()实现分开来,但把两者写到一起是一回事。
在前面的Binder底层分析里我们知道, IPCThreadState对象会捕获底层的Binder命令,然后回调到onTransact()方法处理这一命令,于是在onTranscat()里只需要根据传入的code进行命令的分发与处理即可。比如我们例子里,当检查到命令的code是CREATE_MEDIA_RECORDER,也就是我们在IMediaPlayerService接口类里定义的Binder命令,会根据这一命令调用到createMediaRecorder()方法,然后再将结果通过reply这一Parcel传回给调用端,这样就完成了远程调用的实现。最后,缕缕进行一次IoC反向调用到父类的onTransact(),从而可以处理一些通用的Binder命令。
但到此,我们的Native Service实现并不完整,我们在Stub端并没有提供createMediaRecorder()方法的实现,这样BnMediaPlayerService这个类是无法被实例化成具体的对象,从而响应远程请求。
于是,我们通过继承BnMediaPlayerService,然后再实现接口方法createMediaRecorder(),这一新的对象便可被实例化成为一个具体的对象。这样做的目的进一步将Binder处理相关代码与具体的实现拆分开,我们可以得到在命名和实现上更加清晰的MediaPlayerService:
class MediaPlayerService : public BnMediaPlayerService
{
class Client;
//...
public:
static void instantiate();
// IMediaPlayerService interface
virtual sp<IMediaRecorder> createMediaRecorder(const String16 &opPackageName);
void removeMediaRecorderClient(wp<MediaRecorderClient> client);
virtual sp<IMediaMetadataRetriever> createMetadataRetriever();
virtual sp<IMediaPlayer> create(const sp<IMediaPlayerClient>& client,
audio_session_t audioSessionId);
virtual sp<IMediaCodecList> getCodecList() const;
virtual sp<IOMX> getOMX();
virtual sp<IHDCP> makeHDCP(bool createEncryptionModule);
virtual sp<IRemoteDisplay> listenForRemoteDisplay(const String16 &opPackageName,
const sp<IRemoteDisplayClient>& client, const String8& iface);
virtual status_t dump(int fd, const Vector<String16>& args);
void removeClient(wp<Client> client);
bool hasClient(wp<Client> client);
MediaPlayerService继承自BnMediaPlayerService,又提供了所需要的接口方法,于是任何被系统调度到的可执行部分,无论是线程还是进程,都可以通过实例化一个MediaPlayerService对象响应远程的createMediaRecorder()的调用请求。在代码的实现角度,一般IMediaPlayerService会在一个独立的源文件存放,以标明这是一个接口类,而MediaPlayerService会列入到另一个MediaPlayerService.cpp以说明这一个Service的具体实现。虽然不是强制要求,但这样的实现会更符合android里的编码习惯,更容易维护。
但需要注意的是,IMediaPlayerService接口类会通过IMPLEMENT_META_INTERFACE()这个宏来设置descriptor,于是在整个系统环境里, 由某个descriptor来标识的Service必然会是唯一的。比如某个进程已经通过自己的ProcessState加入到了Binder域,则加入这一新加入的Binder处理只需要如下的简单两行,一行创建MediaPlayerService对象并加入到ServiceManager的管理,另一行启动MediaPlayerService的Binder线程:
void MediaPlayerService::instantiate() {
defaultServiceManager()->addService(
String16("media.player"), new MediaPlayerService());
}
frameworks\av\media\mediaserver\main_mediaserver.cpp:
int main(int argc __unused, char **argv __unused)
{
signal(SIGPIPE, SIG_IGN);
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm(defaultServiceManager());
ALOGI("ServiceManager: %p", sm.get());
InitializeIcuOrDie();
MediaPlayerService::instantiate();
ResourceManagerService::instantiate();
registerExtensions();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
为了减小Native Service在编程上的工作量,在Binder里还会有另一个BinderService相关的实现,也会使用模板的方式进一步节省代码的工作量,见frameworks/base/include/binder/BinderService.h:
template<typename SERVICE>
class BinderService
{
public:
static status_t publish(bool allowIsolated = false) {
sp<IServiceManager> sm(defaultServiceManager());
return sm->addService(
String16(SERVICE::getServiceName()),
new SERVICE(), allowIsolated);
}
static void publishAndJoinThreadPool(bool allowIsolated = false) {
publish(allowIsolated);
joinThreadPool();
}
static void instantiate() { publish(); }
static status_t shutdown() { return NO_ERROR; }
private:
static void joinThreadPool() {
sp<ProcessState> ps(ProcessState::self());
ps->startThreadPool();
ps->giveThreadPoolName();
IPCThreadState::self()->joinThreadPool();
}
};
使用这一BinderService模板,便我们的代码进一步被简化,比如我们在Android系统内见到不会接触到IPCThreadState和ProcessState对象,在定义NativeService时,一般会使用这样的方式,比如AudioFlinger:
class AudioFlinger :
public BinderService<AudioFlinger>,
public BnAudioFlinger
{
friend class BinderService<AudioFlinger>; // for AudioFlinger()
}
于是在某个进程里,我们就只需要最简单一行:
在:frameworks\av\media\audioserver\main_audioserver.cpp
int main(int argc __unused, char **argv)
{
signal(SIGPIPE, SIG_IGN);
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
ALOGI("ServiceManager: %p", sm.get());
AudioFlinger::instantiate();
AudioPolicyService::instantiate();
RadioService::instantiate();
SoundTriggerHwService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
NativeService是由libbinder提供的一种机制,相当于是Java环境Remote Service的底层”Hack”实现。而通过Native Service,我们得到Java环境所不具备的一些新的特质:
- 1) 性能更高。性能上的差异性取决于执行时的不同上下文环境,但通常来说,Native代码总会有比Java这种解释型语言高得多的执行效率。
- 2) 使用同一种语言编程,更加容易理解与调试。Java语言不能直接进行系统调用,必须透过JNI来调用C代码来访问系统功能。而NativeService则完全不同,C++具备直接进行系统调用的能力,于是在访问操作系统或是硬件功能时,不再需要JNI,可以直接进行调用,代码实现上会更加统一。
- 3) 自动化GC,Native态的Binder,与Java协作时被自动切入到Dalvik虚拟机的GC管理,也能使用类似于Java环境的自动化垃圾回收。同时,这种GC机制可以通过RefBase进行进一步拓展。
- 4) 缺点:不能使用AIDL,编码工作量更大。
- 5) 缺点:跟Java的Binder域编程环境功能重叠,也有可能会出错。比如Binder命令的定义,在Java与Native Service交互时,在Java环境与C++环境都要有各自一份拷贝。
综合所有的这些因素,虽然Native Service有一定的局限性,但带来的好处要更多。于是在Android的版本变更过程中,NativeService使用越来越普遍。
总结下: