Binder学习—— C++实现分析
一、测试Demo的实现
1.Binder C++实现参考文件
frameworks/av/include/media/IMediaPlayerService.h frameworks/av/media/libmedia/IMediaPlayerService.cpp frameworks/av/media/libmediaplayerservice/MediaPlayerService.h frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp frameworks/av/media/mediaserver/Main_mediaserver.cpp
2.实现代码
实现Service端和Client端,test_server.cpp中注册两个服务"hello"和"goodbye",test_client.cpp来获取使用服务。 定义抽象类,包含Service和Client两端都要实现的函数: IHelloService.h IGoodbyeService.h Service端的实现(Bn: Binder native): BnHelloService.h BnGoodbyeService.h BnHelloService.cpp BnGoodbyeService.cpp Client端的实现(Bp: Binder proxy): BpHelloService.cpp BpGoodbyeService.cpp # tree . ├── Android.mk ├── BnGoodbyeService.cpp ├── BnGoodbyeService.h ├── BnHelloService.cpp ├── BnHelloService.h ├── BpGoodbyeService.cpp ├── BpHelloService.cpp ├── IGoodbyeService.h ├── IHelloService.h ├── test_client.cpp └── test_server.cpp
(1) IHelloService.h
/* 参考: frameworks\av\include\media\IMediaPlayerService.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 0 #define HELLO_SVR_CMD_SAYHELLO_TO 1 #if 1 /*-----DECLARE_META_INTERFACE(HelloService);等效如下:-----*/ static const android::String16 descriptor; static android::sp<IHelloService> asInterface(const android::sp<android::IBinder>& obj); virtual const android::String16& getInterfaceDescriptor() const; IHelloService(); virtual ~IHelloService(); /*--------------------------------------------------------*/ #endif namespace android { class IHelloService: public IInterface { public: DECLARE_META_INTERFACE(HelloService); /*使用纯虚函数做成抽象类*/ virtual void sayhello(void) = 0; virtual int sayhello_to(const char *name) = 0; }; } #endif
(2) IGoodbyeService.h
/* 参考: frameworks\av\include\media\IMediaPlayerService.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 0 #define GOODBYE_SVR_CMD_SAYGOODBYE_TO 1 namespace android { class IGoodbyeService: public IInterface { public: DECLARE_META_INTERFACE(GoodbyeService); virtual void saygoodbye(void) = 0; virtual int saygoodbye_to(const char *name) = 0; }; } #endif
(3) BnHelloService.h
#ifndef ANDROID_BNHELLOERVICE_H #define ANDROID_BNHELLOERVICE_H #include "IHelloService.h" namespace android { class BnHelloService: public BnInterface<IHelloService> { 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); }; } #endif
(4) BnGoodbyeService.h
#ifndef ANDROID_BNGOODBYEERVICE_H #define ANDROID_BNGOODBYEERVICE_H #include "IGoodbyeService.h" namespace android { 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
(5) BnHelloService.cpp
/* 参考: frameworks\av\media\libmedia\IMediaPlayerService.cpp */ #define LOG_TAG "HelloService" #include "BnHelloService.h" namespace android { 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(); return NO_ERROR; } break; case HELLO_SVR_CMD_SAYHELLO_TO: { /* 从data中取出参数 */ int32_t policy = data.readInt32(); String16 name16 = data.readString16(); String8 name8(name16); int cnt = sayhello_to(name8.string()); /* 把返回值写入reply传回去 */ reply->writeInt32(cnt); return NO_ERROR; } break; default: return BBinder::onTransact(code, data, reply, flags); } } void BnHelloService::sayhello(void) { static int cnt = 0; ALOGI("say hello : %d\n", cnt++); } int BnHelloService::sayhello_to(const char *name) { static int cnt = 0; ALOGI("say hello to %s : %d\n", name, cnt++); return cnt; } }
(6) BnGoodbyeService.cpp
/* 参考: frameworks\av\media\libmedia\IMediaPlayerService.cpp */ #define LOG_TAG "GoodbyeService" #include "BnGoodbyeService.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(); return NO_ERROR; } break; case GOODBYE_SVR_CMD_SAYGOODBYE_TO: { /* 从data中取出参数 */ int32_t policy = data.readInt32(); String16 name16 = data.readString16(); String8 name8(name16); int cnt = saygoodbye_to(name8.string()); /* 把返回值写入reply传回去 */ 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\n", cnt++); } int BnGoodbyeService::saygoodbye_to(const char *name) { static int cnt = 0; ALOGI("say goodbye to %s : %d\n", name, cnt++); return cnt; } }
(7) BpHelloService.cpp
/* 参考: frameworks\av\media\libmedia\IMediaPlayerService.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; /*为了兼容之前的C程序才写入这个垃圾数据的*/ data.writeInt32(0); /*调用远端的hello函数*/ remote()->transact(HELLO_SVR_CMD_SAYHELLO, data, &reply); /*remote() ?*/ } int sayhello_to(const char *name) { /* 构造/发送数据 */ Parcel data, reply; /*为了兼容之前的C程序才写入这个垃圾数据(0)的*/ data.writeInt32(0); data.writeString16(String16(name)); remote()->transact(HELLO_SVR_CMD_SAYHELLO_TO, data, &reply); /*传送回返回值*/ return reply.readInt32(); } }; IMPLEMENT_META_INTERFACE(HelloService, "android.media.IHelloService"); } #if 1 /*------IMPLEMENT_META_INTERFACE(HelloService, "android.media.IHelloService"); 等效如下:-------*/ const android::String16 IHelloService::descriptor("android.media.IHelloService"); const android::String16& IHelloService::getInterfaceDescriptor() const { return IHelloService::descriptor; } android::sp<IHelloService> IHelloService::asInterface(const android::sp<android::IBinder>& obj) { android::sp<IHelloService> intr; if (obj != NULL) { intr = static_cast<IHelloService*>(obj->queryLocalInterface(IHelloService::descriptor).get()); if (intr == NULL) { intr = new BpHelloService(obj); } } return intr; } IHelloService::IHelloService() { } IHelloService::~IHelloService() { } #endif
(8) BpGoodbyeService.cpp
/* 参考: frameworks\av\media\libmedia\IMediaPlayerService.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); remote()->transact(GOODBYE_SVR_CMD_SAYGOODBYE, data, &reply); } int saygoodbye_to(const char *name) { /* 构造/发送数据 */ Parcel data, reply; data.writeInt32(0); data.writeString16(String16(name)); remote()->transact(GOODBYE_SVR_CMD_SAYGOODBYE_TO, data, &reply); return reply.readInt32(); } }; IMPLEMENT_META_INTERFACE(GoodbyeService, "android.media.IGoodbyeService"); }
参考:http://github.com/weidongshan/APP_0004_Binder_CPP_App.git
3.编译测试
将代码放在frameworks/testing/biner_cpp_v1下,然后mm编译。
二、分析
1. Service的注册过程处理过程分析(test_server.cpp)
(1) 获取SM分析
defaultServiceManager //IServiceManager.cpp gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL)); obj = ProcessState::self()->getContextObject(NULL) getStrongProxyForHandle(0); //ProcessState.cpp 直接指定的是handle=0了,是SM return new BpBinder(0); //BpBinder.cpp SM就表示为一个handle=0的BpBinder对象。obj=此BpBinder对象 IServiceManager::asInterface(obj); //obj=此BpBinder对象 return new BpServiceManager(obj); //IServiceManager.cpp BpServiceManager充当SM的角色。
(2) addService()分析
sm->addService(String16("hello"), new BnHelloService()); //test_server.cpp virtual status_t addService(const String16& name, const sp<IBinder>& service, bool allowIsolated); //IServiceManager.cpp //allowIsolated声明的时候声明为: bool allowIsolated=false,使用的是默认参数 data.writeStrongBinder(service); //service=BnHelloService flatten_binder(ProcessState::self(), val, this); //Parcel.cpp val=service=BnHelloService IBinder *local = binder->localBinder(); //binder=val,根据继承关系,localBinder直接return this, local也就是BnHelloService对象。 flat_binder_object obj; obj.type = BINDER_TYPE_BINDER; //add service的时候的type obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs()); obj.cookie = reinterpret_cast<uintptr_t>(local); // BnHelloService对象赋值给flat_binder_object的cookie域 finish_flatten_binder //Parcel.cpp 应该是写到驱动 out->writeObject(flat, false);
(3)创建一个子线程循环read-parse-process
ProcessState::self()->startThreadPool(); //test_server.cpp 它会以一个线程的状态存在,可以通过/proc/$(PID)/task来验证。 spawnPooledThread(true); //ProcessState.cpp isMain=true sp<Thread> t = new PoolThread(isMain); t->run(name.string()); //相当于执行PoolThread中的threadLoop IPCThreadState::self()->joinThreadPool(true); mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER); //IPCThreadState.cpp //若是isMain=true表示注册是主线程,为false表示新创建的子线程 //循环读取数据,解析数据,执行,答复 getAndExecuteCommand executeCommand(cmd) //IPCThreadState.cpp case BR_TRANSACTION: sp<BBinder> b((BBinder*)tr.cookie); //cookie 就是 BnHelloService 对象 b->transact(tr.code, buffer, &reply, tr.flags); //这里调用的就是 BnHelloService.transact() case BR_SPAWN_LOOPER: mProcess->spawnPooledThread(false); //Service创建多线程
IPCThreadState::self()->joinThreadPool(); //test_server.cpp 也是进入解析数据,执行,答复的循环
补充:
① ProcessState::self():获取ProcessState的单例模式,每个进程有一个唯一的实例
② IPCThreadState::self():获取IPCThreadState的单例模式,每个线程都有一个唯一的实例,实现如下:
处理涉及线程特有数据(Thread Specific Data)
这里,每个线程都有一个IPCThreadState对象,也就是说这个对象是每个线程特有的东西,各不相同,因此它应该存在这个线程的局部空间里。
K = pthread_key_create()
(K, V) 同一个K对于不同的线程可以设置不同的Value
每个线程设置不同的Value
线程1:pthread_setspecific(K, V1);
线程2:pthread_setspecific(K, V2); // V1和V2都存在于线程的局部空间里
线程1:pthread_getspecific(K); 得到V1
线程2:pthread_getspecific(K); 得到V2
这里不同的线程使用的是同一个键,但是不同的值,通过判断值是否为NULL来判断是否每个线程已经分配过了。
2. Client获取服务过程和使用服务分析(test_client.cpp)
(1) 打开binder设备节点和获取SM
sp<ProcessState> proc(ProcessState::self()); //test_client.cpp 构造函数中打开binder设备并进行mmap了 sp<IServiceManager> sm = defaultServiceManager(); //test_client.cpp 获得BpServiceManager 在IServiceManager.cpp中定义的
(2) 获取BpBinder对象的过程
sp<IBinder> binder = sm->getService(String16("hello")); //test_client.cpp //binder是BpBinder对象,里面含有HelloService的handle sp<IBinder> svc = checkService(name); remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply); //remote()是获取服务时赋值,Bpbinder或BinderProxy对象。 return reply.readStrongBinder(); unflatten_binder //Parcel.cpp *out = proc->getStrongProxyForHandle(flat->handle); //获取到一个 flat_binder_object 结构,里面有 Service 的 handle,通过 flat->handle 获取一个 sp<IBinder> 对象。
(3) 获得BpHelloService对象的过程
调用BpServiceManager的getService函数获得一个flat_binder_object,从中取出handle, 创建一个BpBinder(handle), 然后使用interface_cast使用这个BpBinder创建一个BpHelloService对象 sp<IHelloService> service = interface_cast<IHelloService>(binder); //binder是BpBinder对象, 里面含有HelloService的handle,把binder转换为IHelloService接口(BpHelloService对象) 之后就可以通过service来访问这个服务里面提供的函数了。
补充:
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");展开后: android::sp<IServiceManager> IServiceManager::asInterface(const android::sp<android::IBinder>& obj) { android::sp<IServiceManager> intr; if (obj != NULL) { /*这个是Client端获取执行*/ intr = static_cast<IServiceManager*>(obj->queryLocalInterface(IServiceManager::descriptor).get()); if (intr == NULL) { /*这个是Service端注册执行*/ intr = new BpServiceManager(obj); } } return intr; }
posted on 2019-05-10 18:24 Hello-World3 阅读(897) 评论(0) 编辑 收藏 举报