Java实现中client端的RPC层(java实现)如何通过JNI来调用IPC层(C++实现)发送数据

TestServer通过addService向Service_manager注册的时候TestServer是Client端,Service_manager是Server端;

TestClient通过getService向Service_manager请求服务的时候TestClient是Client端,Service_manager是Server端;

TestClient调用RPC层的sayhello或者sayhello_to把请求发送给TestServer,TestClient是Client端,TestServer是Server端;

(1)addService

  getIServiceManager().addService

getService

  getIServiceManager().getService

getIServiceManager()返回的是ServiceManagerProxy对象,对象里的addService 和getService函数都是构造好数据后调用mRemote.transact来发送数据

(2)sayhello和sayhello_to

 也都是构造好数据后使用mRemote.transact来发送数据,这时的mRemote是在IHelloService.Stub.Proxy类中

(3)统一使用mRemote.transact来发送数据,mRemote表示目的,源是函数的调用者,数据保存在transact函数的参数中;

对于addService/getService,其mRemote是一个Java BinderProxy对象,它的mObject指向一个C++的BpBinder对象,这个BpBinder的mHandle=0;

对应sayhello/sayhello_to,其mRemote是一个Java BinderProxy对象,它的mObject指向一个C++的BpBinder对象,这个BpBinder的mHandle=1;这个1来至于getService("hello")

5.1 ServiceManagerProxy中mRemote的构造 (用于addService/getService)
猜测:使用0直接构造出一个java BinderProxy对象

getIServiceManager().addService /getIServiceManager().getService

getIServiceManager()
  return ServiceManagerNative.asInterface(BinderInternal.getContextObject())

a. BinderInternal.getContextObject() // 得到了一个Java BinderProxy对象, 其中mObject指向new BpBinder(0);
getContextObject它是一个JNI调用,对应 android_os_BinderInternal_getContextObject, // android_util_Binder.cpp

android_os_BinderInternal_getContextObject
  sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
                   return   getStrongProxyForHandle(0);
                        b = new BpBinder(handle); // mHandle = 0
  return javaObjectForIBinder(env, b); // b = new BpBinder(0), mHandle = 0

// 使用c代码调用NewObject来创建JAVA BinderProxy对象

javaObjectForIBinder(env, b)
  object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);

  // 设置该对象的mObject = val.get = b = new BpBinder(0)
  env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());

  return object;

b. ServiceManagerNative.asInterface
  new ServiceManagerProxy(obj); // obj = BinderProxy对象
    mRemote = obj = BinderProxy对象, 其中mObject指向new BpBinder(0);

5.2 在TestClient中hello服务里的mRemote如何构造
a. IBinder binder = ServiceManager.getService("hello");
猜测: 它的返回值就是一个java BinderProxy对象, 其中的mObject=new BpBinder(handle)
new ServiceManagerProxy().getService("hello")
  ....
  IBinder binder = reply.readStrongBinder();//得到返回结果
          nativeReadStrongBinder // Parcel.java

nativeReadStrongBinder是一个JNI调用, 对应的代码是 android_os_Parcel_readStrongBinder
android_os_Parcel_readStrongBinder
  // 把java Parce对象转换为c++ Parcel对象
  // client程序向sevice_manager发出getService请求,
  // 得到一个回复reply, 它里面含有flat_binder_object
  // 它被封装成一个c++ Parcel对象
  Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);

  /* parcel->readStrongBinder()应该根据flat_binder_object返回一个 new BpBinder(handle)
  *       unflatten_binder(ProcessState::self(), *this, &val);
  * *       out = proc->getStrongProxyForHandle(flat->handle);
  *            b = new BpBinder(handle);
  */

  // 它会创建一个java BinderProxy对象, 其中的mObject=new BpBinder(handle)对象
  return javaObjectForIBinder(env, parcel->readStrongBinder());

b. IHelloService svr = IHelloService.Stub.asInterface(binder);
          new IHelloService.Stub.Proxy(obj); // obj = 步骤a得到的binder
            mRemote = remote;

5.3 现在知道了:mRemote就是一个java BinderProxy 对象
看一下mRemote.transact()
      transactNative(code, data, reply, flags);
它是一个JNI调用,对应android_os_BinderProxy_transact

android_os_BinderProxy_transact
   // 从java BinderProxy对象中把mObject取出, 它就是一个BpBinder对象
   IBinder* target = (IBinder*)env->GetLongField(obj, gBinderProxyOffsets.mObject);

   // 然后调用BpBinder的transact
   status_t err = target->transact(code, *data, reply, flags);

怎么发:

对于getService/addService,会得到一个ServiceManagerProxy代理类;

对于hello服务,也会得到一个代理类IHelloService.Stub.Proxy

这些代理类中都有一个mRemote成员,它是一个Java BInderProxy,它的mObject成员指向一个C++ BpBinder对象,BpBinder中有一个mHandle,对于addService和getService的mHandle为0,表示发给ServiceManager,对于hello服务,mHandle的值来自getService的结果

发送数据时,调用mRemote.transact,它会从mObject中取出Bpbinder对象,调用它的transact函数,实现了Java写的RPC层对C++写的IPC层通过ioctl访问

9.12 Binder系统_Java实现_内部机制_Client端的更多相关文章

  1. 9.13 Binder系统_Java实现_内部机制_Server端

    logcat TestServer:* TestClient:* HelloService:* *:S &CLASSPATH=/mnt/android_fs/TestServer.jar ap ...

  2. 9.8 Binder系统_c++实现_内部机制1

    1. 内部机制_回顾binder框架关键点 binder进程通讯过程情景举例: test_server通过addservice向service_manager注册服务 test_client通过get ...

  3. 9.10 Binder系统_Java实现_hello服务

    怎么做?2.1 定义接口: 写IHelloService.aidl文件, 上传, 编译, 得到IHelloService.java 里面有Stub : onTransact, 它会分辨收到数据然后调用 ...

  4. 9.9 Binder系统_Java实现_Android里java程序的编译启动

    如果知道了进程号:通过ls /proc/进程号/task 可以看到所有线程    cat /proc/进程号/task/线程号/comm  可以达到线程名字(主线程是main,主线程号就是进程号) d ...

  5. 9.7 Binder系统_c++实现_编写程序

    参考文件:frameworks\av\include\media\IMediaPlayerService.h (IMediaPlayerService,BnMediaPlayerService)fra ...

  6. 9.2 Binder系统_驱动情景分析_服务注册过程

    1. 几个重要结构体的引入给test_server添加一个goodbye服务, 由此引入以下概念: 进程间通信其实质也是需要三要素:源.目的.数据,源是自己,目的用handle表示:通讯的过程是源向实 ...

  7. Android驱动学习-内部机制_回顾binder框架关键点

    内部机制_回顾binder框架关键点server注册服务时, 对每个服务都提供不同的ptr/cookie,在驱动程序里对每个服务都构造一个binder_node, 它也含有ptr/cookie cli ...

  8. 9.11 Binder系统_分层

    1.Binder系统过程分析,情景分析 server提供服务 (1)addService(服务名称,xxx)执行后会导致binder驱动在server的内核空间为服务创建一个binder_node结构 ...

  9. 012_STM32程序移植之_内部flash开机次数管理lib库建立

    012_STM32程序移植之_内部flash开机次数管理lib库建立 1. 测试环境:STM32C8T6 2. 测试接口: 3. 串口使用串口一,波特率9600 单片机引脚------------CH ...

随机推荐

  1. eclispe中如何创建web项目

    xian 1.从file中点击---->new----->other---->javaEE----->web---->Dynamic  Web project----&g ...

  2. 66.app.use(express.static)

    转自:https://blog.csdn.net/u010977147/article/details/60956502

  3. win7禁用启用本地连接bat及vbs

    平台:Windows 7 .8.1 目的:用bat启用禁用网卡 操作: cls @ECHO OFFtitle 启用或禁用本地连接 CLS color 0a GOTO MENU:MENU ECHO. E ...

  4. mkfs---创建Linux文件系统

    [root@xiaolizi ~]# mkfsmkfs mkfs.btrfs mkfs.cramfs mkfs.ext2 mkfs.ext3 mkfs.ext4 mkfs.minix mkfs.xfs ...

  5. LAMP+YII框架配置中遇到的问题

    以下列出了不同问题及答案: 1. 在yii框架中,改动数据库信息,主要有main.php和database.php两个文件. 2. 问题: watermark/2/text/aHR0cDovL2Jsb ...

  6. 分组的listview——ExpandableListView

    开发使用到的数据统计时可以用分组的ExpandablelistView 效果:

  7. 2.vector数组

    创建vector数组 vector<,,,, }; 尾部插入 ; i < ; i++) { myint.push_back(i); } 读取头部和尾部 cout << myin ...

  8. golang标准包中文手册

    golang标准包中文手册 http://files.cnblogs.com/files/rojas/liudiwu-pkgdoc-master.zip

  9. Flask项目之手机端租房网站功能测试(完结)

    说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! 目录 一丶注册和登录以及用户退出功能 二丶上传头像功能和修改用户名功能测试 三丶发布房源以及实名认证功能测试 四丶网站房屋搜索功能 ...

  10. 【Uva 11080】Place the Guards

    [Link]: [Description] 一些城市,之间有道路相连,现在要安放警卫,警卫能看守到当前点周围的边,一条边只能有一个警卫看守,问是否有方案,如果有最少放几个警卫. [Solution] ...