当前位置: 首页 > news >正文

dedecms网站模板江苏企业展厅设计公司

dedecms网站模板,江苏企业展厅设计公司,网站建设与维护试题a卷,免费发布广告的网站手写一个C Android Binder服务及源码分析 前言一、 基于C语言编写Android Binder跨进程通信Demo总结及改进二、C语言编写自己的Binder服务Demo1. binder服务demo功能介绍2. binder服务demo代码结构图3. binder服务demo代码实现3.1 IHelloService.h代码实现3.2 BnHelloService.c… 手写一个C Android Binder服务及源码分析 前言一、 基于C语言编写Android Binder跨进程通信Demo总结及改进二、C语言编写自己的Binder服务Demo1. binder服务demo功能介绍2. binder服务demo代码结构图3. binder服务demo代码实现3.1 IHelloService.h代码实现3.2 BnHelloService.cpp代码实现3.3 BpHelloService.cpp代码实现3.4 test_server.cpp代码实现3.5 test_client.cpp代码实现3.6 编译binder服务的Android.mk文件 三、C编写的Binder服务Demo源码解析1. test_client.cpp源码解析1.1 分析如何获得BpServiceManager对象1.2 分析如何获得BpHelloServie对象1.3 代理类如何发送数据 2. test_server.cpp源码解析2.1 分析数据传输机制ProcessState和IPCThreadState2.2 分析向servicemanager添加服务的具体过程2.3 分析server如何分辨client想使用哪一个服务并调用对应的函数 前言 之前我写了三篇文章深入内核讲明白Android Binder这三篇文章可以理解为是Android Binder的原理篇本篇文章算是应用篇讲明白如何使用C语言编写自己的binder服务C只是利用语言优势更好的封装了C语言实现的Android binder方便开发人员使用binder并深入源码搞清楚C编写binder服务的逻辑。 深入内核讲明白Android Binder【一】 深入内核讲明白Android Binder【二】 深入内核讲明白Android Binder【三】 阅读建议 如果有余力建议去阅读下我之前写的三篇【深入内核讲明白Android Binder】系列的文章这三篇文章深入linux内核解析android binder源码如果搞清楚了这三篇文章再来看这篇使用C应用Android binder的文章就非常容易理解。如果直接看这篇文章也是可以的但这篇文章只能使您停留在会使用C语言编写自己的Android binder服务的层面上。 一、 基于C语言编写Android Binder跨进程通信Demo总结及改进 深入内核讲明白Android Binder【一】我们讲解了如何使用C语言编写自己的binder服务但所有代码都写在一个c文件中。职责不够分明代码不易重用也不利于代码阅读和维护。 我们可以把上面的结构优化下面的结构即定义一个头文件IHelloService.h包含服务端和客户端共用的函数接口BnHelloService和BpHelloService充当代理分别实现客户端和服务端的功能分别供binder服务test_server和客户端test_client.c使用。而这也是C语言编写binder服务的整体框架。 二、C语言编写自己的Binder服务Demo 1. binder服务demo功能介绍 我们继续采用深入内核讲明白Android Binder【一】中C语言实现的binder服务功能。C实现的binder服务也提供sayhello和sayhello_to两个函数供客户端调用。 2. binder服务demo代码结构图 IHelloService.h定义服务端和客户端共用的接口类。BnHelloService.cpp服务端的代理类。BnHelloService类的具体实现binder服务的本地实现BpHelloService.cpp客户端的代理类。文件中定义BpHelloService类继承IHelloService客户端调用binder服务的实现test_server.cppbinder服务提供者服务端test_client.cppbinder服务使用者客户端 3. binder服务demo代码实现 3.1 IHelloService.h代码实现 参考代码:frameworks\av\include\media\IMediaPlayerService.h 定义接口类IHelloService类中有sayhellosayhello_to两个纯虚函数。BnHelloService类和BpHelloService类会继承IHelloService实现这两个虚函数。 /* 参考: 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 1 #define HELLO_SVR_CMD_SAYHELLO_TO 2 #define HELLO_SVR_CMD_GET_FD 3namespace android {class IHelloService: public IInterface { public://声明接口DECLARE_META_INTERFACE(HelloService);virtual void sayhello(void) 0;virtual int sayhello_to(const char *name) 0; }; //继承自IHelloService和BBinder class BnHelloService: public BnInterfaceIHelloService { 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);BnHelloService(); }; }//https://github.com/CyanogenMod/android_frameworks_native/blob/cm-14.1/include/binder/IInterface.h templatetypename INTERFACE class BnInterface : public INTERFACE, public BBinder { public:virtual spIInterface queryLocalInterface(const String16 _descriptor);virtual const String16 getInterfaceDescriptor() const;typedef INTERFACE BaseInterface;protected:virtual IBinder* onAsBinder(); };//通过预处理器运算符##标记粘合符声明接口 #define DECLARE_META_INTERFACE(INTERFACE) \static const android::String16 descriptor; \static android::spI##INTERFACE asInterface( \const android::spandroid::IBinder obj); \virtual const android::String16 getInterfaceDescriptor() const; \I##INTERFACE(); \virtual ~I##INTERFACE(); 3.2 BnHelloService.cpp代码实现 参考代码frameworks\av\media\libmedia\IMediaPlayerService.cpp BnHelloService作为服务端的代理类是binder服务的本地实现 /* 参考: frameworks\av\media\libmedia\IMediaPlayerService.cpp */#define LOG_TAG HelloService#include IHelloService.hnamespace android {BnHelloService::BnHelloService() { }// 根据code确定调用服务的哪一个函数 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; 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; } }3.3 BpHelloService.cpp代码实现 参考代码frameworks\av\media\libmedia\IMediaPlayerService.cpp BpHelloService作为客户端的代理类是客户端调用binder服务的具体实现。 客户端调用服务端函数的步骤1. 构造数据2. 向服务端发送数据3. 获取服务端返回的数据 /* 参考: frameworks\av\media\libmedia\IMediaPlayerService.cpp */#include IHelloService.hnamespace android { //继承自IHelloService和BpRefBase class BpHelloService: public BpInterfaceIHelloService { public:BpHelloService(const spIBinder impl): BpInterfaceIHelloService(impl){}void sayhello(void){/* 构造/发送数据 */Parcel data, reply;//为了与C实现的binder兼容需要把传入的数据格式与C读取的数据格式一致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;elsereturn reply.readInt32();} };// 实现接口 IMPLEMENT_META_INTERFACE(HelloService, android.media.IHelloService);}//https://github.com/CyanogenMod/android_frameworks_native/blob/cm-14.1/include/binder/IInterface.h templatetypename INTERFACE class BpInterface : public INTERFACE, public BpRefBase { public:explicit BpInterface(const spIBinder remote);typedef INTERFACE BaseInterface;protected:virtual IBinder* onAsBinder(); };//通过预处理器运算符##标记粘合符实现接口 #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::spI##INTERFACE I##INTERFACE::asInterface( \const android::spandroid::IBinder obj) \{ \android::spI##INTERFACE intr; \if (obj ! NULL) { \intr static_castI##INTERFACE*( \obj-queryLocalInterface( \I##INTERFACE::descriptor).get()); \if (intr NULL) { \intr new Bp##INTERFACE(obj); \} \} \return intr; \} \I##INTERFACE::I##INTERFACE() { } \I##INTERFACE::~I##INTERFACE() { } 3.4 test_server.cpp代码实现 参考代码frameworks\av\media\mideaserver/main_mediaserver.cpp test_server是binder服务提供者服务端核心步骤 打开驱动获取servicemanager向servicemanager中添加服务死循环等待客户端发来数据并进行处理和回复 /* 参考: frameworks\av\media\mediaserver\Main_mediaserver.cpp */#define LOG_TAG TestService //#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;/* usage : test_server */ int main(void) {/* 打开驱动, mmap */spProcessState proc(ProcessState::self());/* 获得BpServiceManager servicemanager的代理类*/spIServiceManager sm defaultServiceManager();/* 添加服务 */sm-addService(String16(hello), new BnHelloService(sockets[1]));/* 循环体 */ProcessState::self()-startThreadPool(); // 创建子线程死循环等待客户端发送来的数据IPCThreadState::self()-joinThreadPool(); // 创建主线程死循环等待客户端发送来的数据return 0; }3.5 test_client.cpp代码实现 参考代码frameworks\av\media\mideaserver/main_mediaserver.cpp test_client是binder服务使用者客户端实现核心步骤: 打开驱动获得servicemanager从servicemanager获得服务调用服务的函数 #define LOG_TAG TestService //#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 unistd.h#include IHelloService.h #include IGoodbyeService.husing namespace android;/* ./test_client hello* ./test_client hello name*/ int main(int argc, char **argv) {int cnt;if (argc 2){ALOGI(Usage:\n);ALOGI(%s readfile\n, argv[0]);ALOGI(%s hello|goodbye\n, argv[0]);ALOGI(%s hello|goodbye name\n, argv[0]);return -1;}/* getService *//* 打开驱动, mmap */spProcessState proc(ProcessState::self());/* 获得BpServiceManager servicemanager的代理类 */spIServiceManager sm defaultServiceManager();if (strcmp(argv[1], hello) 0){spIBinder binder sm-getService(String16(hello));if (binder 0){ALOGI(cant get hello service\n);return -1;}/* service肯定是BpHelloServie指针 */spIHelloService service interface_castIHelloService(binder);/* 调用Service的函数 */if (argc 3) {service-sayhello();ALOGI(client call sayhello);}else {cnt service-sayhello_to(argv[2]);ALOGI(client call sayhello_to, cnt %d, cnt);}}return 0; }3.6 编译binder服务的Android.mk文件 参考代码frameworks\av\media\mideaserver/Android.mk LOCAL_PATH: $(call my-dir)include $(CLEAR_VARS)LOCAL_SRC_FILES: \BnHelloService.cpp \BpHelloService.cpp \BnGoodbyeService.cpp \BpGoodbyeService.cpp \test_server.cppLOCAL_SHARED_LIBRARIES : \libcutils \libutils \liblog \libbinder LOCAL_MODULE: test_server LOCAL_32_BIT_ONLY : trueinclude $(BUILD_EXECUTABLE)include $(CLEAR_VARS)LOCAL_SRC_FILES: \BpHelloService.cpp \BpGoodbyeService.cpp \test_client.cppLOCAL_SHARED_LIBRARIES : \libcutils \libutils \liblog \libbinder LOCAL_MODULE: test_client LOCAL_32_BIT_ONLY : trueinclude $(BUILD_EXECUTABLE三、C编写的Binder服务Demo源码解析 一图简单回顾下【深入内核讲明白Android Binder】系列的文章中讲解的Binder跨进程通信。 1. test_client.cpp源码解析 1.1 分析如何获得BpServiceManager对象 BpServiceManager是servicemanager服务的代理对象通过BpServiceManager调用servicemanager提供的服务函数BpServiceManager源码链接IServiceManager.cppBpServiceManager继承关系图如下 BpServiceManager继承自IServiceManager和BpRefBase而BpRefBase中的mRemote成员指向BpBinder对象BpBinder中mHandle成员代表了服务的句柄通过mHandle可以获取相应的服务。 //继承自IServiceManager和BpRefBase class BpServiceManager : public BpInterfaceIServiceManager { public:BpServiceManager(const spIBinder impl): BpInterfaceIServiceManager(impl){}virtual spIBinder getService(const String16 name) const{unsigned n;for (n 0; n 5; n){spIBinder svc checkService(name);if (svc ! NULL) return svc;ALOGI(Waiting for service %s...\n, String8(name).string());sleep(1);}return NULL;}virtual spIBinder checkService( const String16 name) const{Parcel data, reply;data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());data.writeString16(name);remote()-transact(CHECK_SERVICE_TRANSACTION, data, reply);return reply.readStrongBinder();}virtual status_t addService(const String16 name, const spIBinder service,bool allowIsolated){Parcel data, reply;data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());data.writeString16(name);data.writeStrongBinder(service);data.writeInt32(allowIsolated ? 1 : 0);status_t err remote()-transact(ADD_SERVICE_TRANSACTION, data, reply);return err NO_ERROR ? reply.readExceptionCode() : err;}virtual VectorString16 listServices(){VectorString16 res;int n 0;for (;;) {Parcel data, reply;data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());data.writeInt32(n);status_t err remote()-transact(LIST_SERVICES_TRANSACTION, data, reply);if (err ! NO_ERROR)break;res.add(reply.readString16());}return res;} };IMPLEMENT_META_INTERFACE(ServiceManager, android.os.IServiceManager);}; // namespace androidclass BpRefBase : public virtual RefBase { protected:BpRefBase(const spIBinder 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;//指向BpBinder对象RefBase::weakref_type* mRefs;std::atomicint32_t mState; };}; // namespace androidclass BpBinder : public IBinder { public:BpBinder(int32_t handle);inline int32_t handle() const { return mHandle; }virtual const String16 getInterfaceDescriptor() const;virtual bool isBinderAlive() const;virtual status_t pingBinder();virtual status_t dump(int fd, const VectorString16 args);virtual status_t transact( uint32_t code,const Parcel data,Parcel* reply,uint32_t flags 0);virtual status_t linkToDeath(const spDeathRecipient recipient,void* cookie NULL,uint32_t flags 0);virtual status_t unlinkToDeath( const wpDeathRecipient recipient,void* cookie NULL,uint32_t flags 0,wpDeathRecipient* outRecipient NULL);virtual void attachObject( const void* objectID,void* object,void* cleanupCookie,object_cleanup_func func);virtual void* findObject(const void* objectID) const;virtual void detachObject(const void* objectID);virtual BpBinder* remoteBinder();status_t setConstantData(const void* data, size_t size);void sendObituary();class ObjectManager{public:ObjectManager();~ObjectManager();void attach( const void* objectID,void* object,void* cleanupCookie,IBinder::object_cleanup_func func);void* find(const void* objectID) const;void detach(const void* objectID);void kill();private:ObjectManager(const ObjectManager);ObjectManager operator(const ObjectManager);struct entry_t{void* object;void* cleanupCookie;IBinder::object_cleanup_func func;};KeyedVectorconst void*, entry_t mObjects;};protected:virtual ~BpBinder();virtual void onFirstRef();virtual void onLastStrongRef(const void* id);virtual bool onIncStrongAttempted(uint32_t flags, const void* id);private:const int32_t mHandle;//最核心的数据struct Obituary {wpDeathRecipient recipient;void* cookie;uint32_t flags;};void reportOneDeath(const Obituary obit);bool isDescriptorCached() const;mutable Mutex mLock;volatile int32_t mAlive;volatile int32_t mObitsSent;VectorObituary* mObituaries;ObjectManager mObjects;Parcel* mConstantData;mutable String16 mDescriptorCache; };之前实现的CDemo中可知我们是通过defaultServiceManager函数获得BpServiceManager /* usage : test_server */ int main(void) {/* 打开驱动, mmap */spProcessState proc(ProcessState::self());/* 获得BpServiceManager */spIServiceManager sm defaultServiceManager();sm-addService(String16(hello), new BnHelloService(sockets[1]));sm-addService(String16(goodbye), new BnGoodbyeService());/* 循环体 */ProcessState::self()-startThreadPool();IPCThreadState::self()-joinThreadPool();return 0; }defaultServiceManager方法源码地址defaultServiceManager() //IServiceManager.cpp spIServiceManager defaultServiceManager() { //单例模式if (gDefaultServiceManager ! NULL) return gDefaultServiceManager;{AutoMutex _l(gDefaultServiceManagerLock);while (gDefaultServiceManager NULL) { //把BpBinder(mHandle0)对象转换为IServiceManager接口BpServiceManagergDefaultServiceManager interface_castIServiceManager(ProcessState::self()-getContextObject(NULL));if (gDefaultServiceManager NULL)sleep(1);}}return gDefaultServiceManager; } //sp是一个智能指针类当没有任何引用指向 IServiceManager 实例时它会自动被销毁。 spIServiceManager gDefaultServiceManager;ProcessState::self()-getContextObject(NULL))获得BpBinder对象 new BpBinder(0) spIBinder ProcessState::getContextObject(const spIBinder /*caller*/) {return getStrongProxyForHandle(0); }spIBinder ProcessState::getStrongProxyForHandle(int32_t handle) {spIBinder result;AutoMutex _l(mLock);handle_entry* e lookupHandleLocked(handle);if (e ! NULL) {// We need to create a new BpBinder if there isnt currently one, OR we// are unable to acquire a weak reference on this current one. See comment// in getWeakProxyForHandle() for more info about this.IBinder* b e-binder;if (b NULL || !e-refs-attemptIncWeak(this)) {if (handle 0) {// Special case for context manager...// The context manager is the only object for which we create// a BpBinder proxy without already holding a reference.// Perform a dummy transaction to ensure the context manager// is registered before we create the first local reference// to it (which will occur when creating the BpBinder).// If a local reference is created for the BpBinder when the// context manager is not present, the driver will fail to// provide a reference to the context manager, but the// driver API does not return status.//// Note that this is not race-free if the context manager// dies while this code runs.//// TODO: add a driver API to wait for context manager, or// stop special casing handle 0 for context manager and add// a driver API to get a handle to the context manager with// proper reference counting.Parcel data;status_t status IPCThreadState::self()-transact(0, IBinder::PING_TRANSACTION, data, NULL, 0);if (status DEAD_OBJECT)return NULL;}b new BpBinder(handle); //传进来的handle等于0e-binder b;if (b) e-refs b-getWeakRefs();result b;} else {// This little bit of nastyness is to allow us to add a primary// reference to the remote proxy when this team doesnt have one// but another team is sending the handle to us.result.force_set(b);e-refs-decWeak(this);}}return result; }BpBinder::BpBinder(int32_t handle): mHandle(handle)//handle赋值给mHandle0, mAlive(1), mObitsSent(0), mObituaries(NULL) {ALOGV(Creating BpBinder %p handle %d\n, this, mHandle);extendObjectLifetime(OBJECT_LIFETIME_WEAK);IPCThreadState::self()-incWeakHandle(handle); }interface_cast(ProcessState::self()-getContextObject(NULL));获得BpServiceManager对象new BpServiceManager(new BpBinder(0)) interface_cast模板方法调用IServiceManager的asInterface方法并把new BpBinder(0)传给asInterface方法。 IServiceManager的asInterface方法在IServiceManager类中通过DECLARE_META_INTERFACE(ServiceManager);进行声明IServiceManager的asInterface方法在BpServiceManager类中通过IMPLEMENT_META_INTERFACE(ServiceManager, “android.os.IServiceManager”);进行实现 //源码https://github.com/CyanogenMod/android_frameworks_native/blob/cm-14.1/include/binder/IInterface.h#L42 templatetypename INTERFACE inline spINTERFACE interface_cast(const spIBinder obj) {return INTERFACE::asInterface(obj); }class IServiceManager : public IInterface { public://声明接口DECLARE_META_INTERFACE(ServiceManager);/*** Retrieve an existing service, blocking for a few seconds* if it doesnt yet exist.*/virtual spIBinder getService( const String16 name) const 0;/*** Retrieve an existing service, non-blocking.*/virtual spIBinder checkService( const String16 name) const 0;/*** Register a service.*/virtual status_t addService( const String16 name,const spIBinder service,bool allowIsolated false) 0;/*** Return list of all existing services.*/virtual VectorString16 listServices() 0;enum {GET_SERVICE_TRANSACTION IBinder::FIRST_CALL_TRANSACTION,CHECK_SERVICE_TRANSACTION,ADD_SERVICE_TRANSACTION,LIST_SERVICES_TRANSACTION,}; };class BpServiceManager : public BpInterfaceIServiceManager { public:BpServiceManager(const spIBinder impl): BpInterfaceIServiceManager(impl){}virtual spIBinder getService(const String16 name) const{unsigned n;for (n 0; n 5; n){spIBinder svc checkService(name);if (svc ! NULL) return svc;ALOGI(Waiting for service %s...\n, String8(name).string());sleep(1);}return NULL;}virtual spIBinder checkService( const String16 name) const{Parcel data, reply;data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());data.writeString16(name);remote()-transact(CHECK_SERVICE_TRANSACTION, data, reply);return reply.readStrongBinder();}virtual status_t addService(const String16 name, const spIBinder service,bool allowIsolated){Parcel data, reply;data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());data.writeString16(name);data.writeStrongBinder(service);data.writeInt32(allowIsolated ? 1 : 0);status_t err remote()-transact(ADD_SERVICE_TRANSACTION, data, reply);return err NO_ERROR ? reply.readExceptionCode() : err;}virtual VectorString16 listServices(){VectorString16 res;int n 0;for (;;) {Parcel data, reply;data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());data.writeInt32(n);status_t err remote()-transact(LIST_SERVICES_TRANSACTION, data, reply);if (err ! NO_ERROR)break;res.add(reply.readString16());}return res;} };//实现接口 IMPLEMENT_META_INTERFACE(ServiceManager, android.os.IServiceManager);}; // namespace android//通过预处理器运算符##标记粘合符声明接口 #define DECLARE_META_INTERFACE(INTERFACE) \static const android::String16 descriptor; \static android::spI##INTERFACE asInterface( \const android::spandroid::IBinder obj); \virtual const android::String16 getInterfaceDescriptor() const; \I##INTERFACE(); \virtual ~I##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::spI##INTERFACE I##INTERFACE::asInterface( \const android::spandroid::IBinder obj) \{ \android::spI##INTERFACE intr; \if (obj ! NULL) { \intr static_castI##INTERFACE*( \obj-queryLocalInterface( \I##INTERFACE::descriptor).get()); \if (intr NULL) { \intr new Bp##INTERFACE(obj); \} \} \return intr; \} \I##INTERFACE::I##INTERFACE() { } \I##INTERFACE::~I##INTERFACE() { } ##INTERFACE用ServiceManager替换得到BpServiceManager对象BpBinder在BpServiceManager中如何存储 new BpServiceManager(new BpBinder(0))最终将BpBinder对象存储到了BpRefBase对象的mRemote成员中 //BpBinder对象传给了impl BpServiceManager(const spIBinder impl): BpInterfaceIServiceManager(impl){}//impl传给了remote templatetypename INTERFACE inline BpInterfaceINTERFACE::BpInterface(const spIBinder remote): BpRefBase(remote) { }//remote传给了mRemote BpRefBase::BpRefBase(const spIBinder o): mRemote(o.get()), mRefs(NULL), mState(0) {extendObjectLifetime(OBJECT_LIFETIME_WEAK);if (mRemote) {mRemote-incStrong(this); // Removed on first IncStrong().mRefs mRemote-createWeak(this); // Held for our entire lifetime.} }总结 defaultServiceManager方法构造了一个BpServiceManager对象它里面的mRemote new BpBinder(0)也就是mRmote-mHandle0 1.2 分析如何获得BpHelloServie对象 BpHelloServie继承关系图和上面讲到的BpServiceManager的继承关系类似。唯一不同的是BpServiceManager的handle是固定的0代表servicemanager服务进程而BpHelloServie的handle要通过BpServiceManager的getService方法获得。 BpHelloService是HelloService服务的代理通过BpHelloServie可以调用HelloServie服务中提供的服务函数sayhello/sayhello_toBpHelloService对象的获取过程有两步 通过BpServiceManager的getService方法获取指向hello服务的BpBinder对象。将BpBinder对象转换为BpServiceManager对象。 下面通过源码进行验证 int main(int argc, char **argv) {int cnt;if (argc 2){ALOGI(Usage:\n);ALOGI(%s readfile\n, argv[0]);ALOGI(%s hello|goodbye\n, argv[0]);ALOGI(%s hello|goodbye name\n, argv[0]);return -1;}/* getService *//* 打开驱动, mmap */spProcessState proc(ProcessState::self());/* 获得BpServiceManager */spIServiceManager sm defaultServiceManager();if (strcmp(argv[1], hello) 0){// 从servicemanager获得hello服务的BpBinder对象spIBinder binder sm-getService(String16(hello));if (binder 0){ALOGI(cant get hello service\n);return -1;}/* 将binder转换为BpHelloService对象这里的service肯定是BpHelloServie指针 */spIHelloService service interface_castIHelloService(binder);/* 调用Service的函数 */if (argc 3) {service-sayhello();ALOGI(client call sayhello);}else {cnt service-sayhello_to(argv[2]);ALOGI(client call sayhello_to, cnt %d, cnt);}}return 0; }sp binder sm-getService(String16(“hello”))源码分析这里binder是BpBinder对象里面含有HelloService的handle virtual spIBinder getService(const String16 name) const {unsigned n;for (n 0; n 5; n){// 从servicemanager获取服务spIBinder svc checkService(name);if (svc ! NULL) return svc;ALOGI(Waiting for service %s...\n, String8(name).string());sleep(1);}return NULL; }virtual spIBinder checkService( const String16 name) const {Parcel data, reply;//构造数据data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());data.writeString16(name);//name hello//发送数据给handle0即service_manager进程remote()-transact(CHECK_SERVICE_TRANSACTION, data, reply);//从收到的回复中取出HelloService的handle,构造BpBinderreturn reply.readStrongBinder(); }spIBinder Parcel::readStrongBinder() const {spIBinder val;readStrongBinder(val);return val; }status_t Parcel::readStrongBinder(spIBinder* val) const {return unflatten_binder(ProcessState::self(), *this, val); }status_t unflatten_binder(const spProcessState proc,const Parcel in, spIBinder* out) {const flat_binder_object* flat in.readObject(false);if (flat) {switch (flat-type) {case BINDER_TYPE_BINDER:*out reinterpret_castIBinder*(flat-cookie);return finish_unflatten_binder(NULL, *flat, in);case BINDER_TYPE_HANDLE:// flat-handle是hello服务handle客户端可以通过这个handle找到hello服务*out proc-getStrongProxyForHandle(flat-handle);return finish_unflatten_binder(static_castBpBinder*(out-get()), *flat, in);}}return BAD_TYPE; } spIBinder ProcessState::getStrongProxyForHandle(int32_t handle) {spIBinder result;AutoMutex _l(mLock);handle_entry* e lookupHandleLocked(handle);if (e ! NULL) {// We need to create a new BpBinder if there isnt currently one, OR we// are unable to acquire a weak reference on this current one. See comment// in getWeakProxyForHandle() for more info about this.IBinder* b e-binder;if (b NULL || !e-refs-attemptIncWeak(this)) {if (handle 0) {// Special case for context manager...// The context manager is the only object for which we create// a BpBinder proxy without already holding a reference.// Perform a dummy transaction to ensure the context manager// is registered before we create the first local reference// to it (which will occur when creating the BpBinder).// If a local reference is created for the BpBinder when the// context manager is not present, the driver will fail to// provide a reference to the context manager, but the// driver API does not return status.//// Note that this is not race-free if the context manager// dies while this code runs.//// TODO: add a driver API to wait for context manager, or// stop special casing handle 0 for context manager and add// a driver API to get a handle to the context manager with// proper reference counting.Parcel data;status_t status IPCThreadState::self()-transact(0, IBinder::PING_TRANSACTION, data, NULL, 0);if (status DEAD_OBJECT)return NULL;}//构造BpBinderhandle是ServiceManager的handleb new BpBinder(handle); e-binder b;if (b) e-refs b-getWeakRefs();result b;} else {// This little bit of nastyness is to allow us to add a primary// reference to the remote proxy when this team doesnt have one// but another team is sending the handle to us.result.force_set(b);e-refs-decWeak(this);}}return result; }sp service interface_cast(binder)使用BpBinder其中的handle是HelloService的handle获得一个IHelloService的接口其实是BpHelloService对象这个过程和上面将BpBinder对象转换为BpServiceManager对象的过程一致不再赘述。 1.3 代理类如何发送数据 代理类通过如下两个步骤发送数据 构造数据调用remote()-transact 如BpServiceManager发送数据源码 class BpServiceManager : public BpInterfaceIServiceManager { public:BpServiceManager(const spIBinder impl): BpInterfaceIServiceManager(impl){}virtual spIBinder getService(const String16 name) const{unsigned n;for (n 0; n 5; n){spIBinder svc checkService(name);if (svc ! NULL) return svc;ALOGI(Waiting for service %s...\n, String8(name).string());sleep(1);}return NULL;}virtual spIBinder checkService( const String16 name) const{Parcel data, reply;// 构造数据data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());data.writeString16(name);// 调用remote()-transactremote()-transact(CHECK_SERVICE_TRANSACTION, data, reply);return reply.readStrongBinder();}virtual status_t addService(const String16 name, const spIBinder service,bool allowIsolated){Parcel data, reply;// 构造数据data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());data.writeString16(name);data.writeStrongBinder(service);data.writeInt32(allowIsolated ? 1 : 0);// 调用remote()-transactstatus_t err remote()-transact(ADD_SERVICE_TRANSACTION, data, reply);return err NO_ERROR ? reply.readExceptionCode() : err;}...... };如BpHelloService发送数据源码 class BpHelloService: public BpInterfaceIHelloService { public:BpHelloService(const spIBinder impl): BpInterfaceIHelloService(impl){}void sayhello(void){/* 构造/发送数据 */Parcel data, reply;data.writeInt32(0);data.writeString16(String16(IHelloService));// 调用remote()-transactremote()-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()-transactremote()-transact(HELLO_SVR_CMD_SAYHELLO_TO, data, reply);exception reply.readInt32();if (exception)return -1;elsereturn reply.readInt32();}...... };我们来分析下remote()-transact remote()函数获得是BpRefBase中的mRemote而mRemote指向的是BpBinder这点从上面分析获得BpServiceManager和BpHelloService对象的时候可知。 class BpRefBase : public virtual RefBase { protected:BpRefBase(const spIBinder 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; // BpBinder对象RefBase::weakref_type* mRefs;std::atomicint32_t mState; };那么接着分析BpBinder中的transact函数 transact调用IPCThreadState::self()-transact方法接着调用waitForResponse方法接着调用talkWithDriver方法而talkWithDriver方法最终调用ioctl发送数据。 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) {//这儿的参数就和C的ioctl需要的参数差不多了mHandle是指目的进程code是指调用服务的哪个函数//data是携带的数据reply是要回复的数据status_t status IPCThreadState::self()-transact(mHandle, code, data, reply, flags);if (status DEAD_OBJECT) mAlive 0;return status;}return DEAD_OBJECT; }status_t IPCThreadState::transact(int32_t handle,uint32_t code, const Parcel data,Parcel* reply, uint32_t flags) {status_t err data.errorCheck();flags | TF_ACCEPT_FDS;IF_LOG_TRANSACTIONS() {TextOutput::Bundle _b(alog);alog BC_TRANSACTION thr (void*)pthread_self() / hand handle / code TypeCode(code) : indent data dedent endl;}if (err NO_ERROR) {LOG_ONEWAY( SEND from pid %d uid %d %s, getpid(), getuid(),(flags TF_ONE_WAY) 0 ? READ REPLY : ONE WAY);err writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);}if (err ! NO_ERROR) {if (reply) reply-setError(err);return (mLastError err);}if ((flags TF_ONE_WAY) 0) {#if 0if (code 4) { // relayoutALOGI( CALLING transaction 4);} else {ALOGI( CALLING transaction %d, code);}#endifif (reply) {err waitForResponse(reply);} else {Parcel fakeReply;err waitForResponse(fakeReply);}#if 0if (code 4) { // relayoutALOGI( RETURNING transaction 4);} else {ALOGI( RETURNING transaction %d, code);}#endifIF_LOG_TRANSACTIONS() {TextOutput::Bundle _b(alog);alog BR_REPLY thr (void*)pthread_self() / hand handle : ;if (reply) alog indent *reply dedent endl;else alog (none requested) endl;}} else {err waitForResponse(NULL, NULL);}return err; }status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) {uint32_t cmd;int32_t err;while (1) {if ((errtalkWithDriver()) NO_ERROR) break;err mIn.errorCheck();if (err NO_ERROR) break;if (mIn.dataAvail() 0) continue;cmd (uint32_t)mIn.readInt32();IF_LOG_COMMANDS() {alog Processing waitForResponse Command: getReturnString(cmd) endl;}switch (cmd) {case BR_TRANSACTION_COMPLETE:if (!reply !acquireResult) goto finish;break;case BR_DEAD_REPLY:err DEAD_OBJECT;goto finish;case BR_FAILED_REPLY:err FAILED_TRANSACTION;goto finish;case BR_ACQUIRE_RESULT:{ALOG_ASSERT(acquireResult ! NULL, Unexpected brACQUIRE_RESULT);const int32_t result mIn.readInt32();if (!acquireResult) continue;*acquireResult result ? NO_ERROR : INVALID_OPERATION;}goto finish;case BR_REPLY:{binder_transaction_data tr;err mIn.read(tr, sizeof(tr));ALOG_ASSERT(err NO_ERROR, Not enough command data for brREPLY);if (err ! NO_ERROR) goto finish;if (reply) {if ((tr.flags TF_STATUS_CODE) 0) {reply-ipcSetDataReference(reinterpret_castconst uint8_t*(tr.data.ptr.buffer),tr.data_size,reinterpret_castconst binder_size_t*(tr.data.ptr.offsets),tr.offsets_size/sizeof(binder_size_t),freeBuffer, this);} else {err *reinterpret_castconst status_t*(tr.data.ptr.buffer);freeBuffer(NULL,reinterpret_castconst uint8_t*(tr.data.ptr.buffer),tr.data_size,reinterpret_castconst binder_size_t*(tr.data.ptr.offsets),tr.offsets_size/sizeof(binder_size_t), this);}} else {freeBuffer(NULL,reinterpret_castconst uint8_t*(tr.data.ptr.buffer),tr.data_size,reinterpret_castconst binder_size_t*(tr.data.ptr.offsets),tr.offsets_size/sizeof(binder_size_t), this);continue;}}goto finish;default:err executeCommand(cmd);if (err ! NO_ERROR) goto finish;break;}}finish:if (err ! NO_ERROR) {if (acquireResult) *acquireResult err;if (reply) reply-setError(err);mLastError err;}return err; }status_t IPCThreadState::talkWithDriver(bool doReceive) {if (mProcess-mDriverFD 0) {return -EBADF;}binder_write_read bwr;// Is the read buffer empty?const bool needRead mIn.dataPosition() mIn.dataSize();// We dont want to write anything if we are still reading// from data left in the input buffer and the caller// has requested to read the next data.const size_t outAvail (!doReceive || needRead) ? mOut.dataSize() : 0;bwr.write_size outAvail;bwr.write_buffer (uintptr_t)mOut.data();// This is what well read.if (doReceive needRead) {bwr.read_size mIn.dataCapacity();bwr.read_buffer (uintptr_t)mIn.data();} else {bwr.read_size 0;bwr.read_buffer 0;}IF_LOG_COMMANDS() {TextOutput::Bundle _b(alog);if (outAvail ! 0) {alog Sending commands to driver: indent;const void* cmds (const void*)bwr.write_buffer;const void* end ((const uint8_t*)cmds)bwr.write_size;alog HexDump(cmds, bwr.write_size) endl;while (cmds end) cmds printCommand(alog, cmds);alog dedent;}alog Size of receive buffer: bwr.read_size , needRead: needRead , doReceive: doReceive endl;}// Return immediately if there is nothing to do.if ((bwr.write_size 0) (bwr.read_size 0)) return NO_ERROR;bwr.write_consumed 0;bwr.read_consumed 0;status_t err;do {IF_LOG_COMMANDS() {alog About to read/write, write size mOut.dataSize() endl;} #if defined(__ANDROID__)// 最终还是要调用ioctl发送数据if (ioctl(mProcess-mDriverFD, BINDER_WRITE_READ, bwr) 0)err NO_ERROR;elseerr -errno; #elseerr INVALID_OPERATION; #endifif (mProcess-mDriverFD 0) {err -EBADF;}IF_LOG_COMMANDS() {alog Finished read/write, write size mOut.dataSize() endl;}} while (err -EINTR);IF_LOG_COMMANDS() {alog Our err: (void*)(intptr_t)err , write consumed: bwr.write_consumed (of mOut.dataSize() ), read consumed: bwr.read_consumed endl;}if (err NO_ERROR) {if (bwr.write_consumed 0) {if (bwr.write_consumed mOut.dataSize())mOut.remove(0, bwr.write_consumed);elsemOut.setDataSize(0);}if (bwr.read_consumed 0) {mIn.setDataSize(bwr.read_consumed);mIn.setDataPosition(0);}IF_LOG_COMMANDS() {TextOutput::Bundle _b(alog);alog Remaining data size: mOut.dataSize() endl;alog Received commands from driver: indent;const void* cmds mIn.data();const void* end mIn.data() mIn.dataSize();alog HexDump(cmds, mIn.dataSize()) endl;while (cmds end) cmds printReturnCommand(alog, cmds);alog dedent;}return NO_ERROR;}return err; }2. test_server.cpp源码解析 启动一个binder服务有以下几个步骤 打开驱动注册服务死循环等待数据 其中打开驱动是通过ProcessState对象完成的循环等待数据是由IPCThreadState创建的主线程和ProcessState创建的子线程完成的。 2.1 分析数据传输机制ProcessState和IPCThreadState ProcessState对象打开驱动 /* usage : test_server */ int main(void) {/* 打开驱动, mmap */spProcessState proc(ProcessState::self());/* 获得BpServiceManager */spIServiceManager sm defaultServiceManager();sm-addService(String16(hello), new BnHelloService(sockets[1]));sm-addService(String16(goodbye), new BnGoodbyeService());/* 创建循环体等待被被唤醒读取数据解析数据处理数据回复数据 */ProcessState::self()-startThreadPool();//创建子线程的IPCThreadStateIPCThreadState::self()-joinThreadPool();//创建主线程的IPCThreadState并循环等待数据return 0; }ProcessState::self()打开驱动 spProcessState ProcessState::self() {Mutex::Autolock _l(gProcessMutex);if (gProcess ! NULL) {return gProcess;}gProcess new ProcessState;return gProcess; }ProcessState::ProcessState(): mDriverFD(open_driver())//打开驱动并将fd赋值给mDriverFD, mVMStart(MAP_FAILED), mThreadCountLock(PTHREAD_MUTEX_INITIALIZER), mThreadCountDecrement(PTHREAD_COND_INITIALIZER), mExecutingThreadsCount(0), mMaxThreads(DEFAULT_MAX_BINDER_THREADS), mStarvationStartTimeMs(0), mManagesContexts(false), mBinderContextCheckFunc(NULL), mBinderContextUserData(NULL), mThreadPoolStarted(false), mThreadPoolSeq(1) {if (mDriverFD 0) {// mmap提供一块虚拟地址空间来接收事务// mmap the binder, providing a chunk of virtual address space to receive transactions.mVMStart mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);if (mVMStart MAP_FAILED) {// *sigh*ALOGE(Using /dev/binder failed: unable to mmap transaction memory.\n);close(mDriverFD);mDriverFD -1;}}LOG_ALWAYS_FATAL_IF(mDriverFD 0, Binder driver could not be opened. Terminating.); }static int open_driver() {int fd open(/dev/binder, O_RDWR | O_CLOEXEC);if (fd 0) {int vers 0;status_t result ioctl(fd, BINDER_VERSION, vers);if (result -1) {ALOGE(Binder ioctl to obtain version failed: %s, strerror(errno));close(fd);fd -1;}if (result ! 0 || vers ! BINDER_CURRENT_PROTOCOL_VERSION) {ALOGE(Binder driver protocol does not match user space protocol!);close(fd);fd -1;}size_t maxThreads DEFAULT_MAX_BINDER_THREADS;result ioctl(fd, BINDER_SET_MAX_THREADS, maxThreads);if (result -1) {ALOGE(Binder ioctl to set max threads failed: %s, strerror(errno));}} else {ALOGW(Opening /dev/binder failed: %s\n, strerror(errno));}return fd; }IPCThreadState::self()-joinThreadPool();创建主线程IPCThreadState对象并循环等待客户端数据 补充知识点线程特有数据Thread Special Data 主线程创建多个子线程每个子线程有自己的IPCThreadState对象即该对象是线程特有的各自不同那么它应该存在线程的局部空间里。 那么如何实现呢 创建键k pthread_key_create (k,v)为键设置值每个线程为k设置不一样的value 如对于线程1可以调用pthread_setspecific(k, v1)设置value为v1后续可以在不同线程中获得不同的值 如在线程1中调用pthread_getspecific(k)就可以得到v1 // 保证每个线程只有一个IPCThreadState对象该对象通过pthread_getspecific函数获得 IPCThreadState* IPCThreadState::self() {if (gHaveTLS) { restart:const pthread_key_t k gTLS;//获得值IPCThreadState* st (IPCThreadState*)pthread_getspecific(k);if (st) return st;//创建IPCThreadState对象作为已经创建的键的值return new IPCThreadState;}if (gShutdown) {ALOGW(Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n);return NULL;}//多线程下也只会创建一个键pthread_mutex_lock(gTLSMutex);if (!gHaveTLS) {//创建键int key_create_value pthread_key_create(gTLS, threadDestructor);if (key_create_value ! 0) {pthread_mutex_unlock(gTLSMutex);ALOGW(IPCThreadState::self() unable to create TLS key, expect a crash: %s\n,strerror(key_create_value));return NULL;}gHaveTLS true;}pthread_mutex_unlock(gTLSMutex);goto restart; }IPCThreadState::IPCThreadState()//mProcess ProcessState::self(),里面含有open驱动的句柄 mDriverFD: mProcess(ProcessState::self()),mMyThreadId(gettid()),mStrictModePolicy(0),mLastTransactionBinderFlags(0) {//将IPCThreadState对象设置为已经创建的键的值pthread_setspecific(gTLS, this);clearCaller();mIn.setDataCapacity(256);mOut.setDataCapacity(256); }IPCThreadState::self()保证每个线程只有一个IPCThreadState对象该对象通过pthread_getspecific函数获得。IPCThreadState::self()-joinThreadPool()方法循环等待 读取解析处理返回数据 // 循环等待 读取解析处理返回数据 void IPCThreadState::joinThreadPool(bool isMain) {LOG_THREADPOOL(**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n, (void*)pthread_self(), getpid());mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);// This thread may have been spawned by a thread that was in the background// scheduling group, so first we will make sure it is in the foreground// one to avoid performing an initial transaction in the background.set_sched_policy(mMyThreadId, SP_FOREGROUND);status_t result;//循环等待数据do {processPendingDerefs();// now get the next command to be processed, waiting if necessaryresult getAndExecuteCommand();if (result NO_ERROR result ! TIMED_OUT result ! -ECONNREFUSED result ! -EBADF) {ALOGE(getAndExecuteCommand(fd%d) returned unexpected error %d, aborting,mProcess-mDriverFD, result);abort();}// Let this thread exit the thread pool if it is no longer// needed and it is not the main process thread.if(result TIMED_OUT !isMain) {break;}} while (result ! -ECONNREFUSED result ! -EBADF);LOG_THREADPOOL(**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err%p\n,(void*)pthread_self(), getpid(), (void*)result);mOut.writeInt32(BC_EXIT_LOOPER);talkWithDriver(false); }status_t IPCThreadState::getAndExecuteCommand() {status_t result;int32_t cmd;//调用ioctl获取数据result talkWithDriver();if (result NO_ERROR) {size_t IN mIn.dataAvail();if (IN sizeof(int32_t)) return result;cmd mIn.readInt32();IF_LOG_COMMANDS() {alog Processing top-level Command: getReturnString(cmd) endl;}pthread_mutex_lock(mProcess-mThreadCountLock);mProcess-mExecutingThreadsCount;if (mProcess-mExecutingThreadsCount mProcess-mMaxThreads mProcess-mStarvationStartTimeMs 0) {mProcess-mStarvationStartTimeMs uptimeMillis();}pthread_mutex_unlock(mProcess-mThreadCountLock);//处理数据result executeCommand(cmd);pthread_mutex_lock(mProcess-mThreadCountLock);mProcess-mExecutingThreadsCount--;if (mProcess-mExecutingThreadsCount mProcess-mMaxThreads mProcess-mStarvationStartTimeMs ! 0) {int64_t starvationTimeMs uptimeMillis() - mProcess-mStarvationStartTimeMs;if (starvationTimeMs 100) {ALOGE(binder thread pool (%zu threads) starved for % PRId64 ms,mProcess-mMaxThreads, starvationTimeMs);}mProcess-mStarvationStartTimeMs 0;}pthread_cond_broadcast(mProcess-mThreadCountDecrement);pthread_mutex_unlock(mProcess-mThreadCountLock);// After executing the command, ensure that the thread is returned to the// foreground cgroup before rejoining the pool. The driver takes care of// restoring the priority, but doesnt do anything with cgroups so we// need to take care of that here in userspace. Note that we do make// sure to go in the foreground after executing a transaction, but// there are other callbacks into user code that could have changed// our group so we want to make absolutely sure it is put back.set_sched_policy(mMyThreadId, SP_FOREGROUND);}return result; }status_t IPCThreadState::executeCommand(int32_t cmd) {BBinder* obj;RefBase::weakref_type* refs;status_t result NO_ERROR;switch ((uint32_t)cmd) {case BR_ERROR:result mIn.readInt32();break;case BR_OK:break;......//处理数据case BR_TRANSACTION:{binder_transaction_data tr;result mIn.read(tr, sizeof(tr));ALOG_ASSERT(result NO_ERROR,Not enough command data for brTRANSACTION);if (result ! NO_ERROR) break;Parcel buffer;buffer.ipcSetDataReference(reinterpret_castconst uint8_t*(tr.data.ptr.buffer),tr.data_size,reinterpret_castconst binder_size_t*(tr.data.ptr.offsets),tr.offsets_size/sizeof(binder_size_t), freeBuffer, this);const pid_t origPid mCallingPid;const uid_t origUid mCallingUid;const int32_t origStrictModePolicy mStrictModePolicy;const int32_t origTransactionBinderFlags mLastTransactionBinderFlags;mCallingPid tr.sender_pid;mCallingUid tr.sender_euid;mLastTransactionBinderFlags tr.flags;int curPrio getpriority(PRIO_PROCESS, mMyThreadId);if (gDisableBackgroundScheduling) {if (curPrio ANDROID_PRIORITY_NORMAL) {// We have inherited a reduced priority from the caller, but do not// want to run in that state in this process. The driver set our// priority already (though not our scheduling class), so bounce// it back to the default before invoking the transaction.setpriority(PRIO_PROCESS, mMyThreadId, ANDROID_PRIORITY_NORMAL);}} else {if (curPrio ANDROID_PRIORITY_BACKGROUND) {// We want to use the inherited priority from the caller.// Ensure this thread is in the background scheduling class,// since the driver wont modify scheduling classes for us.// The scheduling group is reset to default by the caller// once this method returns after the transaction is complete.set_sched_policy(mMyThreadId, SP_BACKGROUND);}}//ALOGI( TRANSACT from pid %d uid %d\n, mCallingPid, mCallingUid);Parcel reply;status_t error;IF_LOG_TRANSACTIONS() {TextOutput::Bundle _b(alog);alog BR_TRANSACTION thr (void*)pthread_self() / obj tr.target.ptr / code TypeCode(tr.code) : indent buffer dedent endl Data addr reinterpret_castconst uint8_t*(tr.data.ptr.buffer) , offsets addr reinterpret_castconst size_t*(tr.data.ptr.offsets) endl;}if (tr.target.ptr) {// We only have a weak reference on the target object, so we must first try to// safely acquire a strong reference before doing anything else with it.if (reinterpret_castRefBase::weakref_type*(tr.target.ptr)-attemptIncStrong(this)) {error reinterpret_castBBinder*(tr.cookie)-transact(tr.code, buffer,reply, tr.flags);reinterpret_castBBinder*(tr.cookie)-decStrong(this);} else {error UNKNOWN_TRANSACTION;}} else {error the_context_object-transact(tr.code, buffer, reply, tr.flags);}//ALOGI( TRANSACT from pid %d restore pid %d uid %d\n,// mCallingPid, origPid, origUid);if ((tr.flags TF_ONE_WAY) 0) {LOG_ONEWAY(Sending reply to %d!, mCallingPid);if (error NO_ERROR) reply.setError(error);sendReply(reply, 0);} else {LOG_ONEWAY(NOT sending reply to %d!, mCallingPid);}mCallingPid origPid;mCallingUid origUid;mStrictModePolicy origStrictModePolicy;mLastTransactionBinderFlags origTransactionBinderFlags;IF_LOG_TRANSACTIONS() {TextOutput::Bundle _b(alog);alog BC_REPLY thr (void*)pthread_self() / obj tr.target.ptr : indent reply dedent endl;}}break;......}if (result ! NO_ERROR) {mLastError result;}return result; }ProcessState::self()-startThreadPool()创建子线程的IPCThreadState并循序等待数据 void ProcessState::startThreadPool() {AutoMutex _l(mLock);if (!mThreadPoolStarted) {mThreadPoolStarted true;spawnPooledThread(true);} }void ProcessState::spawnPooledThread(bool isMain) {if (mThreadPoolStarted) {String8 name makeBinderThreadName();ALOGV(Spawning new pooled thread, name%s\n, name.string());//创建子线程spThread t new PoolThread(isMain);t-run(name.string());} }class PoolThread : public Thread { public:PoolThread(bool isMain): mIsMain(isMain){}protected:virtual bool threadLoop(){//为子线程创建IPCThreadState并进行循环等待数据IPCThreadState::self()-joinThreadPool(mIsMain);return false;}const bool mIsMain; };2.2 分析向servicemanager添加服务的具体过程 对于不同的服务构造flat_binder_object结构体里面的binder/cookie对于不同的服务它的值不一样 /* 获得BpServiceManager */ spIServiceManager sm defaultServiceManager();sm-addService(String16(hello), new BnHelloService());virtual status_t addService(const String16 name, const spIBinder service,bool allowIsolated) {Parcel data, reply;// 构造数据data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());data.writeString16(name);data.writeStrongBinder(service);// service BnHelloService对象data.writeInt32(allowIsolated ? 1 : 0);// 发送数据status_t err remote()-transact(ADD_SERVICE_TRANSACTION, data, reply);return err NO_ERROR ? reply.readExceptionCode() : err; }status_t writeStrongBinder(const spT val) {return writeStrongBinder(T::asBinder(val)); // val BnHelloService对象 }status_t Parcel::writeStrongBinder(const spIBinder val) {return flatten_binder(ProcessState::self(), val, this);// val BnHelloService对象 }status_t flatten_binder(const spProcessState /*proc*/,const spIBinder binder, Parcel* out)// binder BnHelloService对象 {//构造flat_binder_objectflat_binder_object obj;obj.flags 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;if (binder ! NULL) {IBinder *local binder-localBinder();//local 指向 BnHelloService对象if (!local) {BpBinder *proxy binder-remoteBinder();if (proxy NULL) {ALOGE(null proxy);}const int32_t handle proxy ? proxy-handle() : 0;obj.type BINDER_TYPE_HANDLE;obj.binder 0; /* Dont pass uninitialized stack data to a remote process */obj.handle handle;obj.cookie 0;} else {obj.type BINDER_TYPE_BINDER;obj.binder reinterpret_castuintptr_t(local-getWeakRefs());obj.cookie reinterpret_castuintptr_t(local); // 指向 BnHelloService对象}} else {obj.type BINDER_TYPE_BINDER;obj.binder 0;obj.cookie 0;}return finish_flatten_binder(binder, obj, out); }BBinder* BBinder::localBinder() {return this; }2.3 分析server如何分辨client想使用哪一个服务并调用对应的函数 server收到的数据里含有flat_binder_object结构体它可以根据binder/cookie分析client想使用哪一个服务把cookie转为BnXXX对象然后调用它的函数 void IPCThreadState::joinThreadPool(bool isMain) {LOG_THREADPOOL(**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n, (void*)pthread_self(), getpid());mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);// This thread may have been spawned by a thread that was in the background// scheduling group, so first we will make sure it is in the foreground// one to avoid performing an initial transaction in the background.set_sched_policy(mMyThreadId, SP_FOREGROUND);status_t result;do {processPendingDerefs();// now get the next command to be processed, waiting if necessaryresult getAndExecuteCommand();if (result NO_ERROR result ! TIMED_OUT result ! -ECONNREFUSED result ! -EBADF) {ALOGE(getAndExecuteCommand(fd%d) returned unexpected error %d, aborting,mProcess-mDriverFD, result);abort();}// Let this thread exit the thread pool if it is no longer// needed and it is not the main process thread.if(result TIMED_OUT !isMain) {break;}} while (result ! -ECONNREFUSED result ! -EBADF);LOG_THREADPOOL(**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err%p\n,(void*)pthread_self(), getpid(), (void*)result);mOut.writeInt32(BC_EXIT_LOOPER);talkWithDriver(false); }status_t IPCThreadState::getAndExecuteCommand() {status_t result;int32_t cmd;//调用ioctl获取数据result talkWithDriver();if (result NO_ERROR) {size_t IN mIn.dataAvail();if (IN sizeof(int32_t)) return result;cmd mIn.readInt32();IF_LOG_COMMANDS() {alog Processing top-level Command: getReturnString(cmd) endl;}pthread_mutex_lock(mProcess-mThreadCountLock);mProcess-mExecutingThreadsCount;if (mProcess-mExecutingThreadsCount mProcess-mMaxThreads mProcess-mStarvationStartTimeMs 0) {mProcess-mStarvationStartTimeMs uptimeMillis();}pthread_mutex_unlock(mProcess-mThreadCountLock);//处理数据result executeCommand(cmd);pthread_mutex_lock(mProcess-mThreadCountLock);mProcess-mExecutingThreadsCount--;if (mProcess-mExecutingThreadsCount mProcess-mMaxThreads mProcess-mStarvationStartTimeMs ! 0) {int64_t starvationTimeMs uptimeMillis() - mProcess-mStarvationStartTimeMs;if (starvationTimeMs 100) {ALOGE(binder thread pool (%zu threads) starved for % PRId64 ms,mProcess-mMaxThreads, starvationTimeMs);}mProcess-mStarvationStartTimeMs 0;}pthread_cond_broadcast(mProcess-mThreadCountDecrement);pthread_mutex_unlock(mProcess-mThreadCountLock);// After executing the command, ensure that the thread is returned to the// foreground cgroup before rejoining the pool. The driver takes care of// restoring the priority, but doesnt do anything with cgroups so we// need to take care of that here in userspace. Note that we do make// sure to go in the foreground after executing a transaction, but// there are other callbacks into user code that could have changed// our group so we want to make absolutely sure it is put back.set_sched_policy(mMyThreadId, SP_FOREGROUND);}return result; }status_t IPCThreadState::executeCommand(int32_t cmd) {BBinder* obj;RefBase::weakref_type* refs;status_t result NO_ERROR;switch ((uint32_t)cmd) {case BR_ERROR:result mIn.readInt32();break;case BR_OK:break;......//处理数据case BR_TRANSACTION:{binder_transaction_data tr;result mIn.read(tr, sizeof(tr));ALOG_ASSERT(result NO_ERROR,Not enough command data for brTRANSACTION);if (result ! NO_ERROR) break;Parcel buffer;buffer.ipcSetDataReference(reinterpret_castconst uint8_t*(tr.data.ptr.buffer),tr.data_size,reinterpret_castconst binder_size_t*(tr.data.ptr.offsets),tr.offsets_size/sizeof(binder_size_t), freeBuffer, this);const pid_t origPid mCallingPid;const uid_t origUid mCallingUid;const int32_t origStrictModePolicy mStrictModePolicy;const int32_t origTransactionBinderFlags mLastTransactionBinderFlags;mCallingPid tr.sender_pid;mCallingUid tr.sender_euid;mLastTransactionBinderFlags tr.flags;int curPrio getpriority(PRIO_PROCESS, mMyThreadId);if (gDisableBackgroundScheduling) {if (curPrio ANDROID_PRIORITY_NORMAL) {// We have inherited a reduced priority from the caller, but do not// want to run in that state in this process. The driver set our// priority already (though not our scheduling class), so bounce// it back to the default before invoking the transaction.setpriority(PRIO_PROCESS, mMyThreadId, ANDROID_PRIORITY_NORMAL);}} else {if (curPrio ANDROID_PRIORITY_BACKGROUND) {// We want to use the inherited priority from the caller.// Ensure this thread is in the background scheduling class,// since the driver wont modify scheduling classes for us.// The scheduling group is reset to default by the caller// once this method returns after the transaction is complete.set_sched_policy(mMyThreadId, SP_BACKGROUND);}}//ALOGI( TRANSACT from pid %d uid %d\n, mCallingPid, mCallingUid);Parcel reply;status_t error;IF_LOG_TRANSACTIONS() {TextOutput::Bundle _b(alog);alog BR_TRANSACTION thr (void*)pthread_self() / obj tr.target.ptr / code TypeCode(tr.code) : indent buffer dedent endl Data addr reinterpret_castconst uint8_t*(tr.data.ptr.buffer) , offsets addr reinterpret_castconst size_t*(tr.data.ptr.offsets) endl;}if (tr.target.ptr) {// We only have a weak reference on the target object, so we must first try to// safely acquire a strong reference before doing anything else with it.if (reinterpret_castRefBase::weakref_type*(tr.target.ptr)-attemptIncStrong(this)) {//reinterpret_castBBinder*(tr.cookie) 通过cookie构造指向BnHelloService对象的BBinder//然后调用BBinder的transact函数error reinterpret_castBBinder*(tr.cookie)-transact(tr.code, buffer,reply, tr.flags);reinterpret_castBBinder*(tr.cookie)-decStrong(this);} else {error UNKNOWN_TRANSACTION;}} else {error the_context_object-transact(tr.code, buffer, reply, tr.flags);}//ALOGI( TRANSACT from pid %d restore pid %d uid %d\n,// mCallingPid, origPid, origUid);if ((tr.flags TF_ONE_WAY) 0) {LOG_ONEWAY(Sending reply to %d!, mCallingPid);if (error NO_ERROR) reply.setError(error);sendReply(reply, 0);} else {LOG_ONEWAY(NOT sending reply to %d!, mCallingPid);}mCallingPid origPid;mCallingUid origUid;mStrictModePolicy origStrictModePolicy;mLastTransactionBinderFlags origTransactionBinderFlags;IF_LOG_TRANSACTIONS() {TextOutput::Bundle _b(alog);alog BC_REPLY thr (void*)pthread_self() / obj tr.target.ptr : indent reply dedent endl;}}break;......}if (result ! NO_ERROR) {mLastError result;}return result; }status_t BBinder::transact(uint32_t code, const Parcel data, Parcel* reply, uint32_t flags) {data.setDataPosition(0);status_t err NO_ERROR;switch (code) {case PING_TRANSACTION:reply-writeInt32(pingBinder());break;default://调用BnHelloService实现的onTransact方法err onTransact(code, data, reply, flags);break;}if (reply ! NULL) {reply-setDataPosition(0);}return err; }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 *//* 参考:* frameworks\base\core\jni\android_view_InputChannel.cpp* android_view_InputChannel_nativeWriteToParcel*/reply-writeDupFileDescriptor(fd);return NO_ERROR;} break;default:return BBinder::onTransact(code, data, reply, flags);} }
http://www.tj-hxxt.cn/news/223881.html

相关文章:

  • 做国外百科知识网站如何查询某个网站的设计公司
  • 设计公司网站域名重庆食品公司
  • seo网站收录工具网站背景怎么换
  • 杭州网站案列最新营销模式
  • 在哪个公司建设网站好网页设计与制作考试试题及答案
  • 安阳网站建设哪家专业济南网站APP
  • 可以做公众号封面图的网站dedecms插件
  • 多语言企业网站建设自动seo优化
  • 镇江网站建设方案泉州网站建设技术外包
  • 网站开发合同 附件企业运营管理案例分析
  • wap 手机网站建设cpa推广平台
  • 如何进行外贸网站建设西安稳定的seo
  • 建设网站外贸网站呼叫中心 建设工期
  • 泰兴网站建设吧自己做网站还是公众号
  • 网站设计文案上海网站建设专业公司哪家好
  • 做学校网站的内容做网站注册营业执照
  • 长沙seo网站网页设计页面大小
  • 福田做棋牌网站建设哪家技术好外网浏览入口
  • 网站 手机版 电脑版 怎么做的定向推广
  • 江苏建设网官方网站云主机软件
  • 怎样申请网站空间WordPress电子书模板模板
  • 长沙手机网站开发架子鼓谱那个网站做的好
  • 类似百度的网站wordpress文章无法中文
  • 建筑设计网站issuu定制app网站
  • 男女直接做视频教学视频网站wordpress代码高亮插件张戈
  • 城市分类信息网站建设网站模板 招聘
  • 手机app ui设计在线网站泰安网络安全工程师培训
  • 如何建设个人的网站网站开发地图板块浮动
  • 东莞市企业网站制作平台韩国网站
  • 上海 网站建设 外包it卷皮淘客网站怎么做