目录:
-
Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制?
-
Android : 跟我学Binder --- (2) AIDL分析及手动实现
-
Android : 跟我学Binder --- (3) C程序示例
-
Android : 跟我学Binder --- (4) 驱动情景分析
-
Android : 跟我学Binder --- (5) C++实现
-
Android : 跟我学Binder --- (6) JAVA实现
一、程序实现
参考文件:
frameworksavincludemediaIMediaPlayerService.h (IMediaPlayerService,BnMediaPlayerService)
frameworksavmedialibmediaIMediaPlayerService.cpp (BpMediaPlayerService)
frameworksavmedialibmediaplayerserviceMediaPlayerService.h
frameworksavmedialibmediaplayerserviceMediaPlayerService.cpp
frameworksavmediamediaserverMain_mediaserver.cpp (server, addService)
之前的代码结构是 test_server 向 service_manager 注册服务,test_client 通过 service_manager 获取服务并使用,服务的实现和数据解析都是在单一的.c文件中实现,接下来对程序框架进行改进,将服务具体函数抽离出来模块化实现,统一由头文件分别定义服务的接口: IHelloService.h 和 IGoodbyeService.h,然后cpp文件实现具体功能:server端为 BnHelloService.cpp 和 BnGoodbyeService.cpp,client端为 BpHelloService.cpp 和 BpGoodbyeService.cpp。
(1)接口定义:(I代表interface)
①IHelloService.h
/* 参考: frameworksavincludemediaIMediaPlayerService.h */
#ifndef ANDROID_IHELLOERVICE_H #define ANDROID_IHELLOERVICE_H #include <utils/Errors.h> // for status_t #include <utils/KeyedVector.h> #include <utils/RefBase.h> #include <utils/String8.h> #include <binder/IInterface.h> #include <binder/Parcel.h> #define HELLO_SVR_CMD_SAYHELLO 1 #define HELLO_SVR_CMD_SAYHELLO_TO 2 #define HELLO_SVR_CMD_GET_FD 3 namespace android { class IHelloService: public IInterface { public: DECLARE_META_INTERFACE(HelloService); //宏自动声明必须的接口 virtual void sayhello(void) = 0; virtual int sayhello_to(const char *name) = 0; virtual int get_fd(void) = 0; }; class BnHelloService: public BnInterface<IHelloService> { private: int fd; public: virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); virtual void sayhello(void); virtual int sayhello_to(const char *name); virtual int get_fd(void); BnHelloService(); BnHelloService(int fd); }; } #endif
②IGoodbyeService.h
/* 参考: frameworksavincludemediaIMediaPlayerService.h */ #ifndef ANDROID_IGOODBYEERVICE_H #define ANDROID_IGOODBYEERVICE_H #include <utils/Errors.h> // for status_t #include <utils/KeyedVector.h> #include <utils/RefBase.h> #include <utils/String8.h> #include <binder/IInterface.h> #include <binder/Parcel.h> #define GOODBYE_SVR_CMD_SAYGOODBYE 1 #define GOODBYE_SVR_CMD_SAYGOODBYE_TO 2 namespace android { class IGoodbyeService: public IInterface { public: DECLARE_META_INTERFACE(GoodbyeService); virtual void saygoodbye(void) = 0; virtual int saygoodbye_to(const char *name) = 0; }; class BnGoodbyeService: public BnInterface<IGoodbyeService> { public: virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); virtual void saygoodbye(void); virtual int saygoodbye_to(const char *name); }; } #endif
(2)功能实现:(B代表binder,n代表native-本地实现,p代表proxy-代理)
①BnHelloService.cpp
/* 参考: frameworksavmedialibmediaIMediaPlayerService.cpp */ #define LOG_TAG "HelloService" #include "IHelloService.h" namespace android { BnHelloService::BnHelloService() { } BnHelloService::BnHelloService(int fd) { this->fd = fd; } status_t BnHelloService::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { /* 解析数据,调用sayhello/sayhello_to */ switch (code) { case HELLO_SVR_CMD_SAYHELLO: { sayhello(); reply->writeInt32(0); /* no exception */ return NO_ERROR; } break; case HELLO_SVR_CMD_SAYHELLO_TO: { /* 从data中取出参数 */ int32_t policy = data.readInt32(); String16 name16_tmp = data.readString16(); /* IHelloService */ String16 name16 = data.readString16(); String8 name8(name16); int cnt = sayhello_to(name8.string()); /* 把返回值写入reply传回去 */ reply->writeInt32(0); /* no exception */ reply->writeInt32(cnt); return NO_ERROR; } break; case HELLO_SVR_CMD_GET_FD: { int fd = this->get_fd(); reply->writeInt32(0); /* no exception */ /* 参考: * frameworksasecorejniandroid_view_InputChannel.cpp * android_view_InputChannel_nativeWriteToParcel */ reply->writeDupFileDescriptor(fd); return NO_ERROR; } break; default: return BBinder::onTransact(code, data, reply, flags); } } void BnHelloService::sayhello(void) { static int cnt = 0; ALOGI("say hello : %d ", ++cnt); } int BnHelloService::sayhello_to(const char *name) { static int cnt = 0; ALOGI("say hello to %s : %d ", name, ++cnt); return cnt; } int BnHelloService::get_fd(void) { return fd; } }
②BnGoodbyeService.cpp
/* 参考: frameworksavmedialibmediaIMediaPlayerService.cpp */ #define LOG_TAG "GoodbyeService" #include "IGoodbyeService.h" namespace android { status_t BnGoodbyeService::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { /* 解析数据,调用saygoodbye/saygoodbye_to */ switch (code) { case GOODBYE_SVR_CMD_SAYGOODBYE: { saygoodbye(); reply->writeInt32(0); /* no exception */ return NO_ERROR; } break; case GOODBYE_SVR_CMD_SAYGOODBYE_TO: { /* 从data中取出参数 */ int32_t policy = data.readInt32(); String16 name16_tmp = data.readString16(); /* IGoodbyeService */ String16 name16 = data.readString16(); String8 name8(name16); int cnt = saygoodbye_to(name8.string()); /* 把返回值写入reply传回去 */ reply->writeInt32(0); /* no exception */ reply->writeInt32(cnt); return NO_ERROR; } break; default: return BBinder::onTransact(code, data, reply, flags); } } void BnGoodbyeService::saygoodbye(void) { static int cnt = 0; ALOGI("say goodbye : %d ", ++cnt); } int BnGoodbyeService::saygoodbye_to(const char *name) { static int cnt = 0; ALOGI("say goodbye to %s : %d ", name, ++cnt); return cnt; } }
③BpHelloService.cpp
/* 参考: frameworksavmedialibmediaIMediaPlayerService.cpp */ #include "IHelloService.h" namespace android { class BpHelloService: public BpInterface<IHelloService> { public: BpHelloService(const sp<IBinder>& impl) : BpInterface<IHelloService>(impl) { } void sayhello(void) { /* 构造/发送数据 */ Parcel data, reply; data.writeInt32(0); data.writeString16(String16("IHelloService")); remote()->transact(HELLO_SVR_CMD_SAYHELLO, data, &reply); } int sayhello_to(const char *name) { /* 构造/发送数据 */ Parcel data, reply; int exception; data.writeInt32(0); data.writeString16(String16("IHelloService")); data.writeString16(String16(name)); remote()->transact(HELLO_SVR_CMD_SAYHELLO_TO, data, &reply); exception = reply.readInt32(); if (exception) return -1; else return reply.readInt32(); } int get_fd(void) { /* 构造/发送数据 */ Parcel data, reply; int exception; data.writeInt32(0); data.writeString16(String16("IHelloService")); remote()->transact(HELLO_SVR_CMD_GET_FD, data, &reply); exception = reply.readInt32(); if (exception) return -1; else { /* 参考: * frameworksasecorejniandroid_view_InputChannel.cpp * android_view_InputChannel_nativeReadFromParcel */ int rawFd = reply.readFileDescriptor(); return dup(rawFd); } } }; IMPLEMENT_META_INTERFACE(HelloService, "android.media.IHelloService"); }
④BpGoodbyeService.cpp
/* 参考: frameworksavmedialibmediaIMediaPlayerService.cpp */ #include "IGoodbyeService.h" namespace android { class BpGoodbyeService: public BpInterface<IGoodbyeService> { public: BpGoodbyeService(const sp<IBinder>& impl) : BpInterface<IGoodbyeService>(impl) { } void saygoodbye(void) { /* 构造/发送数据 */ Parcel data, reply; data.writeInt32(0); data.writeString16(String16("IGoodbyeService")); remote()->transact(GOODBYE_SVR_CMD_SAYGOODBYE, data, &reply); } int saygoodbye_to(const char *name) { /* 构造/发送数据 */ Parcel data, reply; int exception; data.writeInt32(0); data.writeString16(String16("IGoodbyeService")); data.writeString16(String16(name)); remote()->transact(GOODBYE_SVR_CMD_SAYGOODBYE_TO, data, &reply); exception = reply.readInt32(); if (exception) return -1; else return reply.readInt32(); } }; IMPLEMENT_META_INTERFACE(GoodbyeService, "android.media.IGoodbyeService"); }
(3)测试代码:
①test_server.cpp
/* 参考: frameworksavmediamediaserverMain_mediaserver.cpp */ //#define LOG_NDEBUG 0 #include <fcntl.h> #include <sys/prctl.h> #include <sys/wait.h> #include <binder/IPCThreadState.h> #include <binder/ProcessState.h> #include <binder/IServiceManager.h> #include <cutils/properties.h> #include <utils/Log.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/socket.h> #include "IHelloService.h" #include "IGoodbyeService.h" #define SOCKET_BUFFER_SIZE (32768U) using namespace android; /* 参考: * http://blog.csdn.net/linan_nwu/article/details/8222349 */ class MyThread: public Thread { private: int fd; public: MyThread() {} MyThread(int fd) { this->fd = fd; } //如果返回true,循环调用此函数,返回false下一次不会再调用此函数 bool threadLoop() { char buf[500]; int len; int cnt = 0; while(1) { /* 读数据: test_client发出的数据 */ len = read(fd, buf, 500); buf[len] = '