现在要搞明白JAVA层app调用跨进程的Service接口时,它的binder是怎样从Java->jni-->native--->binder驱动的这条链路:就是上图中的左半部分从上至下的流程。所以切入点在于,如app调用另一个进程的Service接口的getString()进行分析,如下:
myService.getString(); //调用服务接口-->进入aidl的getString():即IMyAidlInterface.Stub.Proxy.getString()-->mRemote.transact();-->IBinder.java->transact();-->BinderProxy.java->transact(); //还有一个是Binder.java那个是服务端的,所以这边要看BinderProxy客户端这边-->transactNative(code, data, reply, flags); //感觉到头了没路了,进入了JNI层(Zygote启动->JNI的注册,在那里面)先来看看ZygoteInit.java做什么事。
app_main.cpp: //启动zygote-->runtime.start("...ZygoteInit", args,zygote); -->startReg() //注册JNI-->register_jni_procs(gRegJNI,...); //注册了很多jNI接口 来看看gRegJNI[]={...REG_JNI(register_android_os_Binder), //在这边注册,就是前面的-->android_util_Binder.cpp->int_register_android_os_BinderProxy():-->gBinderProxyMethods[]={//对应上面的transactNative的本地接口。{"transactNaive", "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z",(void*)android_os_BinderProxy_transact} }...} 所以,前面调用到transactNative之后,就进入到JNI层的android_util_Binder.cpp中的android_os_BinderProxy_transact(.., jObject obj)处理。 -->这个obj是Binder Proxy.//将java的数据转成C++层的对象Parcel* data = parcelForJavaObject(env, dataObj);Parcel* reply = parcelForJavaObject(env, replyObj);//重要:调用getBPNativeData函数获得BinderProxy在Native中对应的BinderProxyNativeData//target本质上就是Native的BpBinder.IBinder *target = getBPNativeData(env, obj)->mObject.get();//下面这个语句就是反射。-->return (BinderProxyNativeData*)env->GetLongField(obj, gBinderProxyOffset.mNative);target->transact(code, *data, replay, flags);//这个直接进入了BpBinder.cpp的代码
即: BpBinder.cpp->transact()//进入调用下面:创建并维持一个线程单例并调用transact接口-->IPCThreadState::self()->transact(mHandle, code, data, reply, flags);-->IPCThreadState.cpp->WaitForResponse();talkWithDriver();-->bwr.write_buffer = mOut.data();//设置缓存ioctl(FD, BINDER_WRITE_READ, &bwr); //读写驱动-->case BR_REPLY:-->mIn.Read();
上面就是整体的调用流程,非常的清晰明了。