binder java端的测试程序可参考 binder java端测试程序 ,本文主要从以下两点来分析java成的传输过程
- client 发送数据的过程
- server端接收到数据之后的处理过程
数据发送流程分析
对于注册服务和获取服务,要先获取ServiceManager,再调用其addService和getService方法。
//frameworks\base\core\java\android\os\ServiceManager.java
//获取服务
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return getIServiceManager().getService(name);
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
//注册服务
public static void addService(String name, IBinder service) {
try {
getIServiceManager().addService(name, service, false);
} catch (RemoteException e) {
Log.e(TAG, "error in addService", e);
}
}
我们从获取ServiceManager开始分析
//frameworks\base\core\java\android\os\ServiceManager.java
private static IServiceManager sServiceManager;
private static IServiceManager getIServiceManager() {
//省略
// Find the service manager
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
}
ServiceManagerNative的asInterface方法比较简单,返回一个ServiceManagerProxy对象
//frameworks\base\core\java\android\os\ServiceManagerNative.java
static public IServiceManager asInterface(IBinder obj)
{
if (obj == null) {
return null;
}
IServiceManager in =
(IServiceManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ServiceManagerProxy(obj); //1
}
注释1处返回一个ServiceManagerProxy对象,传入的参数obj为 BinderInternal.getContextObject() 得到的返回值
//frameworks\base\core\java\android\os\ServiceManagerNative.java
class ServiceManagerProxy implements IServiceManager {
public ServiceManagerProxy(IBinder remote) {
mRemote = remote; //1
}
可以看到注释1处,mRemote 指向传进来的remote,而这个传进来的remote就是BinderInternal.getContextObject()的返回值,接下来看看BinderInternal.getContextObject()返回的是什么
//frameworks\base\core\java\com\android\internal\os\BinderInternal.java
public static final native IBinder getContextObject();
getContextObject是一个native方法,肯定要进行JNI调用
//frameworks\base\core\jni\android_util_Binder.cpp
static const JNINativeMethod gBinderInternalMethods[] = {
/* name, signature, funcPtr */
{ "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },
//省略
};
调用getContextObject,就会调用android_os_BinderInternal_getContextObject 函数
//frameworks\base\core\jni\android_util_Binder.cpp
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);//1
return javaObjectForIBinder(env, b);//2
}
注释1处得到的是一个BpBinder对象,其中的mHandle值为0,这个在之前c++ binder中已经分析过了。注释2处将javaObjectForIBinder的返回值retrun出去,注意传入的是注释1处得到的BpBinder对象
//frameworks\base\core\jni\android_util_Binder.cpp
const char* const kBinderProxyPathName = "android/os/BinderProxy";
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
//省略
object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);//1
if (object != NULL) {
LOGDEATH("objectForBinder %p: created new proxy %p !\n", val.get(), object);
// The proxy holds a reference to the native object.
env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());//2
//省略
return object;
}
注释1处gBinderProxyOffsets.mClass指向的是java的BinderProxy类,调用BinderProxy.java的构造函数。注释二处将BinderProxy类中的mObject指向前面传进来的BpBinder对象。所以javaObjectForIBinder函数返回的是一个java层的BinderProxy对象,其中的mObject指向了c++层的BpBinder对象。
综上,获取ServiceManager得到的是一个ServiceManagerProxy对象,它的mRemote指向的是一个BinderProxy对象,此BinderProxy对象中的mObject指向了c++层的BpBinder对象,BpBinder对象中的mHandle值为0,addService和getService就是通过这个mRemote来发送数据
class ServiceManagerProxy implements IServiceManager {
//省略
public IBinder getService(String name) throws RemoteException {
//省略
mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
//省略
return binder;
}
public void addService(String name, IBinder service, boolean allowIsolated)
throws RemoteException {
//省略
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
reply.recycle();
data.recycle();
}
//省略
对于使用服务
IBinder binder = ServiceManager.getService("hello");//1
IHelloService service = IHelloService.Stub.asInterface(binder);//2
service.say_hello();//3
注释1处通过上面说的ServiceManagerProxy中的mRemote发送数据后,得到一个IBinder对象,等等再看这个IBinder对象是啥。注释2处得到一个IHelloService.Stub.Proxy对象
public static IHelloService asInterface(android.os.IBinder obj)
{
//省略
return new IHelloService.Stub.Proxy(obj);
}
可以看出注释2处确实是返回的一个IHelloService.Stub.Proxy对象,注释3处调用IHelloService.Stub.Proxy对象的方法
@Override public void say_hello() throws android.os.RemoteException
{
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_say_hello, _data, _reply, 0);
_reply.readException();
}
可以看出和addService和getService一样,也是通过mRemote来发送数据,那么这个mRemote又是什么呢,这个mRemote就是注释1处得到的IBinder对象,然后传进来的
private static class Proxy implements IHelloService
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) //在上面的asInterface方法中调用这个构造函数,传进来的obj就是注释1处得到的IBinder对象
{
mRemote = remote;
}
//省略
所以要知道这个mRemote是什么,只要知道前面注释1处得到的是什么对象就可以了
IBinder binder = ServiceManager.getService("hello");//1
public IBinder getService(String name) throws RemoteException {
//省略
IBinder binder = reply.readStrongBinder();//1
reply.recycle();
data.recycle();
return binder;
}
getService返回的IBinder 对象就是调用Parcel的readStrongBinder方法返回的。注意,获取服务时,binder驱动回复的数据中包含一个flat_binder_obj结构体,其中的有一个handle值。这部分内容可以去看binder驱动情景分析文章。
//frameworks\base\core\java\android\os\Parcel.java
public final IBinder readStrongBinder() {
return nativeReadStrongBinder(mNativePtr);
}
也是一个native方法,对应native层的android_os_Parcel_readStrongBinder函数
//frameworks\base\core\jni\android_os_Parcel.cpp
static const JNINativeMethod gParcelMethods[] = {
//省略
{"nativeReadStrongBinder", "(J)Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder},
//省略
}
static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);//1
if (parcel != NULL) {
return javaObjectForIBinder(env, parcel->readStrongBinder());//2
}
return NULL;
}
注释1处将java层的Parcel对象转化成c++层的Parcel对象。注释2处调用javaObjectForIBinder并返回,还记得前面分析过这个函数吗,这个函数返回的是一个BinderProxy对象,该对象中的mObject指向传入的 是 parcel->readStrongBinder()函数的返回值。readStrongBinder函数在c++相关的文章中分析过。得到的是一个BpBinder对象,该BpBinder对象中的mHandle是flat_binder_obj中的handle。所以IHelloService.Stub.Proxy中的mRemote也是一个BinderProxy对象。
综上,不管是ServiceManagerProxy还是IHelloService.Stub.Proxy,它们中的mRemote都是一个BinderProxy对象,BinderProxy对象中的mObject指向c++层的BpBinder,区别只是BpBinder中的mHandle不同而已。
知道了mRemote是什么,就可以开始分析数据传输过程了。前面说过,传输都是通过mRemote的transact方法进行。即调用BinderProxy的transact方法
//frameworks\base\core\java\android\os\Binder.java
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
if (Binder.isTracingEnabled()) { Binder.getTransactionTracker().addTrace(); }
return transactNative(code, data, reply, flags);
}
transactNative是一个native方法,指向的是android_os_BinderProxy_transact函数
//frameworks\base\core\jni\android_util_Binder.cpp
static const JNINativeMethod gBinderProxyMethods[] = {
/* name, signature, funcPtr */
{"transactNative", "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},
};
android_os_BinderProxy_transact
//frameworks\base\core\jni\android_util_Binder.cpp
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
Parcel* data = parcelForJavaObject(env, dataObj);//1
Parcel* reply = parcelForJavaObject(env, replyObj);//2
IBinder* target = (IBinder*)
env->GetLongField(obj, gBinderProxyOffsets.mObject); //3
//省略
//printf("Transact from Java code to %p sending: ", target); data->print();
status_t err = target->transact(code, *data, reply, flags);//4
//if (reply) printf("Transact from Java code to %p received: ", target); reply->print();
//省略
return JNI_FALSE;
}
注释1和注释2处将java成的parcel对象转化成c++的parcel对象,注释3处取出BinderProxy中的mObject,即得到BpBinder对象,注释4处调用BpBinder的transact函数。后续的调用过程在binder通讯c++篇都已分析过。
server接收数据后的处理流程
在binder通讯c++篇我们知道,在注册服务时,将该服务的实现函数,写入到flat_binder_obj中。来看一下java写入的处理过程
public void addService(String name, IBinder service, boolean allowIsolated)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
data.writeStrongBinder(service);//1
data.writeInt(allowIsolated ? 1 : 0);
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
reply.recycle();
data.recycle();
}
注释1处调用writeStrongBinder写入,service就是服务的实现,如HelloService.java
//frameworks\base\core\java\android\os\Parcel.java
public final void writeStrongBinder(IBinder val) {
nativeWriteStrongBinder(mNativePtr, val);
}
nativeWriteStrongBinder是一个native方法,对应android_os_Parcel_writeStrongBinder函数
//frameworks\base\core\jni\android_os_Parcel.cpp
static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
if (err != NO_ERROR) {
signalExceptionForError(env, clazz, err);
}
}
}
可以看出,最终也是调用writeStrongBinder写入到flat_binder_obj中,只不过和c++不同的是,这里写入的是一个JavaBBinder对象,JavaBBinder对象中的mObject指向服务的实现HelloService.java。具体可去分析ibinderForJavaObject函数。
再来看一下接收到数据之后,如何调用到HelloService.java中的方法的。在Zygote fork进程后,会创建binder线程池
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
这些函数前面分析过,就是打开binder驱动,创建子线程。在子线程中,循环的获取数据,然后调用executeCommand来处理,处理过程就是取出binder驱动返回的cookie(就是前面addService放入的),转化为BBinder,调用其transact函数。具体查看binder c++ 服务端处理流程 一文。
//frameworks\native\libs\binder\Binder.cpp
status_t BBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
data.setDataPosition(0);
status_t err = NO_ERROR;
switch (code) {
case PING_TRANSACTION:
reply->writeInt32(pingBinder());
break;
default:
err = onTransact(code, data, reply, flags);//1
break;
}
if (reply != NULL) {
reply->setDataPosition(0);
}
return err;
}
注释1处调用onTransact函数。因为取出的cookie是JavaBBinder对象,JavaBBinder继承BBinder,所以会调用JavaBBinder对象的onTransact函数
//frameworks\base\core\jni\android_util_Binder.cpp
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
{
JNIEnv* env = javavm_to_jnienv(mVM);
ALOGV("onTransact() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM);
IPCThreadState* thread_state = IPCThreadState::self();
const int32_t strict_policy_before = thread_state->getStrictModePolicy();
//printf("Transact from %p to Java code sending: ", this);
//data.print();
//printf("\n");
jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);//1
//省略
HelloService继承IHelloService.Stub,IHelloService.Stub又继承自Binder。注释1处,mObject指向的是HelloService,就是调用HelloService的execTransact方法。execTransact在其父类Binder中实现
//frameworks\base\core\java\android\os\Binder.java
private boolean execTransact(int code, long dataObj, long replyObj,
int flags) {
Parcel data = Parcel.obtain(dataObj);
Parcel reply = Parcel.obtain(replyObj);
// theoretically, we should call transact, which will call onTransact,
// but all that does is rewind it, and we just got these from an IPC,
// so we'll just call it directly.
boolean res;
// Log any exceptions as warnings, don't silently suppress them.
// If the call was FLAG_ONEWAY then these exceptions disappear into the ether.
try {
res = onTransact(code, data, reply, flags);
//省略
调用onTransact方法,IHelloService.Stub实现了onTransact,在IHelloService.Stub方法中,直接调用了HelloService中的方法。
总结
- java层客户端传输数据,是使用mRemote.transact发起传输,而这个mRemote是BinderProxy对象,BinderProxy中的mObject指向的是c++的BpBinder对象。调用BinderProxy的transact函数,进而调用到BpBinder的transact函数中,后续就跟c++层传输数据的流程一样了
- addService方法,会导致在flat_binder_obj中的cookie中存入一个JavaBBinder对象,JavaBBinder中的mObject指向的是addService方法传入的HelloService
- 服务端收到数据后,先调用BBinder的transact函数,进而调用到JavaBBinder的onTransact,Binder的execTransact,IHelloService.Stub的onTransact方法。在IHelloService.Stub的onTransact方法中调用HelloService中相关的方法