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访问