• Android : 跟我学Binder --- (5) C++实现



    目录:

    一、程序实现

    参考文件:
    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] = '';
                ALOGI("%s
    ", buf);
                
                /* 向 test_client 发出: Hello, test_client */
                len = sprintf(buf, "Hello, test_client, cnt = %d", cnt++);
                write(fd, buf, len);
            }
            
               return true;  
        }
      
    };  
    
    
    /* usage : test_server  */
    int main(void)
    {
    
        int sockets[2];
    
        socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets);
    
        int bufferSize = SOCKET_BUFFER_SIZE;
        setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
        setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
        setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
        setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
    
        /* 创建一个线程, 用于跟test_client使用socketpiar通信 */
        sp<MyThread> th = new MyThread(sockets[0]);
        th->run();  
    
    
        /* addService */
    
        /* while(1){ read data, 解析数据, 调用服务函数 } */
    
        /* 打开驱动, mmap */
        sp<ProcessState> proc(ProcessState::self());
    
        /* 获得BpServiceManager */
        sp<IServiceManager> sm = defaultServiceManager();
    
        sm->addService(String16("hello"), new BnHelloService(sockets[1]));
        sm->addService(String16("goodbye"), new BnGoodbyeService());
    
        /* 循环体 */
        ProcessState::self()->startThreadPool();
        IPCThreadState::self()->joinThreadPool();
    
        return 0;
    }

      ②test_client.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 <unistd.h>
    
    #include "IHelloService.h"
    #include "IGoodbyeService.h"
    
    using namespace android;
    
    /* ./test_client <hello|goodbye>
     * ./test_client <readfile>
     * ./test_client <hello|goodbye> <name>
     */
    int main(int argc, char **argv)
    {
        int cnt;
        
        if (argc < 2){
            ALOGI("Usage:
    ");
            ALOGI("%s <readfile>
    ", argv[0]);
            ALOGI("%s <hello|goodbye>
    ", argv[0]);
            ALOGI("%s <hello|goodbye> <name>
    ", argv[0]);
            return -1;
        }
    
        /* getService */
        /* 打开驱动, mmap */
        sp<ProcessState> proc(ProcessState::self());
    
        /* 获得BpServiceManager */
        sp<IServiceManager> sm = defaultServiceManager();
    
        if (strcmp(argv[1], "hello") == 0)
        {
    
            sp<IBinder> binder =
                sm->getService(String16("hello"));
    
            if (binder == 0)
            {
                ALOGI("can't get hello service
    ");
                return -1;
            }
    
            /* service肯定是BpHelloServie指针 */
            sp<IHelloService> service =
                interface_cast<IHelloService>(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);
            }
        }
        else if (strcmp(argv[1], "readfile") == 0)
        {
    
            sp<IBinder> binder =
                sm->getService(String16("hello"));
    
            if (binder == 0)
            {
                ALOGI("can't get hello service
    ");
                return -1;
            }
    
            /* service肯定是BpHelloServie指针 */
            sp<IHelloService> service =
                interface_cast<IHelloService>(binder);
    
    
            /* 调用Service的函数 */
            int fd = service->get_fd();
    
            ALOGI("client call get_fd = %d", fd);
    
            char buf[500];
            int len;
            int cnt = 0;
            
            while (1)
            {
                /* 向 test_server 进程发出: Hello, test_server    */
                len = sprintf(buf, "Hello, test_server, cnt = %d", cnt++);
                write(fd, buf, len);
            
                /* 读取数据(test_server进程发回的数据) */
                len = read(fd, buf, 500);
                buf[len] = '';
                ALOGI("%s
    ", buf);
            
                sleep(5);
            }
        }
        else
        {
    
            sp<IBinder> binder =
                sm->getService(String16("goodbye"));
    
            if (binder == 0)
            {
                ALOGI("can't get goodbye service
    ");
                return -1;
            }
    
            /* service肯定是BpGoodbyeServie指针 */
            sp<IGoodbyeService> service =
                interface_cast<IGoodbyeService>(binder);
    
    
            /* 调用Service的函数 */
            if (argc < 3) {
                service->saygoodbye();
                ALOGI("client call saygoodbye");
            }
            else {
                cnt = service->saygoodbye_to(argv[2]);
                ALOGI("client call saygoodbye_to, cnt = %d", cnt);
            }
        }
        
        return 0;
    }

    (4)Android.mk:

    LOCAL_PATH:= $(call my-dir)
    
    include $(CLEAR_VARS)
    
    LOCAL_SRC_FILES:= 
        BnHelloService.cpp 
        BpHelloService.cpp 
        BnGoodbyeService.cpp 
        BpGoodbyeService.cpp 
        test_server.cpp
    
    LOCAL_SHARED_LIBRARIES := 
        libcutils 
        libutils 
        liblog 
        libbinder 
    
    
    LOCAL_MODULE:= test_server
    LOCAL_32_BIT_ONLY := true
    
    include $(BUILD_EXECUTABLE)
    
    include $(CLEAR_VARS)
    
    LOCAL_SRC_FILES:= 
        BpHelloService.cpp 
        BpGoodbyeService.cpp 
        test_client.cpp
    
    LOCAL_SHARED_LIBRARIES := 
        libcutils 
        libutils 
        liblog 
        libbinder 
    
    
    LOCAL_MODULE:= test_client
    LOCAL_32_BIT_ONLY := true
    
    include $(BUILD_EXECUTABLE)

    二、内部机制

    1.回顾binder框架关键点

      test_server向service_manager添加服务,test_client通过service_manager获取服务,具体流程如下:

    ①add_service:
      a.test_server为每个服务构造 struct flat_binder_object 结构体,其中void *binder 或 void* cookie 对应不同服务;
      b.调用ioctl发送数据:
        b1. 数据:flat_binder_object + 服务名称;
        b2.数据中含有"目的地":handle=0,则代表 service_manager;
      c.驱动程序对每一个flat_binder_object构造一个binder_node结构体,其中 void __user *ptr 和 void __user *cookie即来自flat_binder_object;
      d.驱动程序根据handle=0找到service_manager,把数据发送给service_manager并且创建一个 struct binder_ref结构体到链表,其中node指针指向binder_node结构体;
      e.service_manager中记录服务名(“hello”、“goodbye”)称和desc值(binder_ref结构体中的desc值);

    ②get_service: 
      a.test_client构造数据:名称 + "目的"(handle=0);
      b.调ioctl发送数据;
      c.驱动程序根据handle=0找到service_manager把数据给service_manager;
      d.service_manager从service list中找到对应项,比如根据服务名"hello"找到第一项,handle=1;
      e.service_manager调用ioctl返回数据(flat_binder_object);
      f.驱动发现数据中含有flat_binder_object,且type为引用,从service_manager的binder_ref表中找到对应项(传入的handle=binder_ref.desc)再找到binder_node,最后为test_client建立binder_ref,即对应service_manager里构造的binder_ref链表;

    ③test_client使用服务: hello->sayhello(code=1), hello->sayhello_to(code=2)
      a.构造数据,code定义要执行的函数、参数、目的(handle=1);
      b.使用ioctl发送数据;
      c.驱动从数据中取出handle=1,根据handle找到binder_ref,根据binder_ref找到binder_node,再根据binder_node找到目的进程(.proc->test_server),最后把数据传给test_server,并且在数据中设置.ptr/.cookie 等于binder_node的.ptr/.cookie;
      d.test_server根据.ptr/.cookie获知test_client想调用的服务,再根据code等参数调用具体的函数操作;

    小结:

      server注册服务时, 对每个服务都提供不同的ptr/cookie,在驱动程序里对每个服务都构造一个binder_node, 它也含有ptr/cookie,client使用服务前要先getService,在驱动程序里对该服务构造一个binder_ref,binder_ref含有desc, node成员, desc是整数, node指向对应服务的binder_node,使用服务时, client调用ioctl发送构造数据,数据里含有handle,驱动程序根据handle找到binder_ref(desc==handle), 再通过binder_ref找到binder_node, 再根据binder_node找到对应server,最后从binder_node取出ptr/cookie连同那些数据发给server,server根据数据中的ptr/cookie信息调用对应服务,再根据code调用对应函数。

    Binder系统最核心的函数: ioclt;

    client最核心的数据:handle;

    server最核心的数据:.ptr/.cookie

    2.代理类BpXXX分析

      test_server向service_manager添加服务时,首先获得BpServiceManager(handle=0)成为一个client与之通信,test_client同样获得BpServiceManager和service_manager通信,然后test_client再获得BpHelloService(handle=BpServiceManager->getService("Hello")==1)和test_server通信。

     UML展示BpServiceManager的继承关系

                                    (1)

                                    (2)

                                    (3)

       2.1 获得BpServiceManager对象的过程:
        defaultServiceManager构造了一个BpServiceManager对象(派生自BpRefBase,含有IBinder *mRemote, mRemote指向BpBinder对象,它含有mHandle),
     其中它的mRemote = new BpBinder(0); // mRemote->mHandle=0

     defaultServiceManager // IServiceManager.cpp
                                   // 把BpBinder(mHandle=0)对象转换为IServiceManager接口(BpServiceManager)                           
        gDefaultServiceManager = interface_cast<IServiceManager>(
                    ProcessState::self()->getContextObject(NULL));
     分析:
     ProcessState::self()->getContextObject(NULL)
         getStrongProxyForHandle(0);
             b = new BpBinder(handle);   // mHandle=handle=0

     interface_cast<IServiceManager>(new BpBinder(0))  // IInterface.h
         IServiceManager::asInterface(obj);
                return new BpServiceManager(obj); // mRemote=obj=new BpBinder(0);


       2.2 获得BpHelloService对象的过程:
        调用BpServiceManager的getService函数获得一个flat_binder_object,
        从中取出handle, 创建一个BpBinder(handle),
        然后使用interface_cast使用这个BpBinder创建一个BpHelloService对象

     // binder是BpBinder对象, 里面含有HelloService的handle
     sp<IBinder> binder =
            sm->getService(String16("hello")); // IServiceManager.cpp
                        // 构造数据: 数据中肯定含有"hello"
                        // 发送数据: 给handle 0, 即 service_manager进程
                        // 从收到的回复中取出HelloService的handle
                                 return reply.readStrongBinder();
                                                         unflatten_binder(ProcessState::self(), *this, &val);
                                                                 *out = proc->getStrongProxyForHandle(flat->handle);
                                                                                     new BpBinder(handle);  //handle来自service_manager进程的回复
            
                                // 把binder转换为IHelloService接口(BpHelloService对象)
                                // binder是BpBinder对象, 里面含有HelloService的handle
     sp<IHelloService> service = interface_cast<IHelloService>(binder);


       2.3 代理类如何发送数据: ioctl, 数据里含有handle, 含有其他构造的参数
            构造好数据之后,调用:
            remote()->transact(...)  //addService、checkService、getService 以及sayhello/sayhello_to等函数最终都会调用这里,remote()返回一个BpBinder对象,其中实现了transact;
                 IPCThreadState::self()->transact(mHandle, code, data, reply, flags); //该线程中实现了waitForResponse()、talkWithDriver(其中通过mDriverFD句柄进行ioctl操作) 等函数。

    3.数据传输:ProcessState 和 IPCThreadState 类 (单例模式)

     ProcessState::self()->startThreadPool(); //创建子线程,最终执行:IPCThreadState ::self()->joinThreadPool();

     IPCThreadState ::self()->joinThreadPool(); //循环,读取数据、解析、处理、回复。


       3.1 addService
        前面介绍过,对于不同服务构造的flat_binder_object结构体,里面的.binder/.cookie对于不同的服务它的值不一样
                                                            
     sm->addService(String16("hello"), new BnHelloService());
                data.writeStrongBinder(service);  // service = new BnHelloService();
                                flatten_binder(ProcessState::self(), val, this); // val = service = new BnHelloService();
                                        flat_binder_object obj;  // 参数 binder = val = service = new BnHelloService();
                                        IBinder *local = binder->localBinder(); // =this = new BnHelloService();
                            obj.type = BINDER_TYPE_BINDER;
                            obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
                            obj.cookie = reinterpret_cast<uintptr_t>(local);  // new BnHelloService();
                                       
       3.2 server如何分辨client想使用哪一个服务?
        server收到数据里含有flat_binder_object结构体,
        它可以根据.binder/.cookie分析client想使用哪一个服务
        
        把.cookie转换为BnXXXX对象,然后调用它的函数:
                // 根据cookie构造了一个BBinder指针, 实际上是指向某个BnXXX对象
                sp<BBinder> b((BBinder*)tr.cookie);
                // 然后调用它的transact函数
                error = b->transact(tr.code, buffer, &reply, tr.flags);
                                            err = onTransact(code, data, reply, flags);  // 就会调用到BnXXX里实现的onTransact
                                    // 它就会根据code值来调用不同的函数 

    -end-

  • 相关阅读:
    很多的技术招聘面试方式不务实-导致不仅难以招聘到人,而且严重损害公司形象
    技术工作者上升到思想,哲学层面也许更好
    程序员与架构师的区别
    (转载)创业型公司如何管理-吸引人才
    C#图片转成流,流转成图片,字节转图片,图片转字节的方法
    C# Linq获取两个List或数组的差集交集
    C# List排序,附加使用Linq排序
    C#Qrcode生成二维码支持中文,带图片,带文字
    C#判断本地文件,网络文件是否存在是否存在
    C#WebBrowser控件使用教程与技巧收集
  • 原文地址:https://www.cnblogs.com/blogs-of-lxl/p/10501920.html
Copyright © 2020-2023  润新知