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. rtsp和sdp协议简介

    RTSP是由Real network 和Netscape共同提出的如何有效地在IP网络上传输流媒体数据的应用层协议. 实时流协议(RTSP)建立并控制一个或几个时间同步的连续流媒体,如音频和视频.尽管 ...

  2. Looksery Cup 2015

    A题水 C题 博弈论,如果不是CF有WA具体哪个点错了和数据的话,AC要难许多. 如果D的操作数大于奇数个数直接Win 偶数个数大于等于n – k 时,S直接Win 偶数个数小于n – k时,若D操作 ...

  3. Glide二次封装库的使用

    更多代码可以查询本人GitHub:欢迎阅读,star点起来. Glide二次封装库源码 前言 为什么选择Glide? Glide 轻量级 速度快 可以根据所需加载图片的大小自动适配所需分辨率的图 支持 ...

  4. 计算加班类型以及小时数(js)

    function GetDateDiff(startTime, endTime, diffType) { //将xxxx-xx-xx的时间格式,转换为 xxxx/xx/xx的格式 startTime ...

  5. python3 时间处理

    1 标记当前时间 import datetime from dateutil import tz #标记当前时间为中国时间 注意(replace 只有标记的意思没有转化的意思) datetime.da ...

  6. 托管非托管Dll动态调用

    原文:托管非托管Dll动态调用 最近经常看到有人问托管非托管Dll调用的问题.对于动态库的调用其实很简单.网上很多代码都实现了Dll的静态调用方法.我主要谈论下动态库的动态加载. 对于托管动态库,实现 ...

  7. 洛谷 P1358 扑克牌

    P1358 扑克牌 题目描述 组合数学是数学的重要组成部分,是一门研究离散对象的科学,它主要研究满足一定条件的组态(也称组合模型)的存在.计数以及构造等方面的问题.组合数学的主要内容有组合计数.组合设 ...

  8. C# wpf程序获取当前程序版本

    C# wpf程序获取当前程序版本 /// <summary>         /// 获取当前系统的版本         /// </summary>         /// ...

  9. js12---闭包,原型,继承

    <html> <body> <script type="text/javascript"> //闭包实现了函数层面多个子函数共享父类函数的属性. ...

  10. 2.Java实现基于SOAP的XML文档网络传输及远程过程调用(RPC)-

    转自:https://blog.csdn.net/a214919447/article/details/55260411 SOAP(Simple Object Access Protocol,简单对象 ...