binder java层数据传输过程

binder java端的测试程序可参考 binder java端测试程序 ,本文主要从以下两点来分析java成的传输过程

  1. client 发送数据的过程
  2. 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中的方法。

总结

  1. java层客户端传输数据,是使用mRemote.transact发起传输,而这个mRemote是BinderProxy对象,BinderProxy中的mObject指向的是c++的BpBinder对象。调用BinderProxy的transact函数,进而调用到BpBinder的transact函数中,后续就跟c++层传输数据的流程一样了
  2. addService方法,会导致在flat_binder_obj中的cookie中存入一个JavaBBinder对象,JavaBBinder中的mObject指向的是addService方法传入的HelloService
  3. 服务端收到数据后,先调用BBinder的transact函数,进而调用到JavaBBinder的onTransact,Binder的execTransact,IHelloService.Stub的onTransact方法。在IHelloService.Stub的onTransact方法中调用HelloService中相关的方法
  • 17
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值