Java层到Native层Binder的流程

来源:互联网 发布:百度搜索软件 编辑:程序博客网 时间:2024/05/17 23:51

我们在SystemServer分析这个文章中已经知道通过ServiceManager.addService("xx", new XXBinder(this));已经添加了很多服务,这些都是继承Binder的服务,需要跨进程操作。包括我们自己声明的服务也是一个道理,都是继承Binder。

并且我们上一章已经介绍了添加服务和查询服务的底层流程,但是问题来了,他们都是native层的,没有java的代码出现,那么Binder的通信是怎么和Java层建立联系的呢?

带着这个问题,我们就从Binder的构造方法追寻下去。

    public Binder() {        init();        ...    }

其中private native final void init();
然后进入到android_utils_Binder.cpp中


这个分享一个小技巧,我是用Source Insight3查看的源代码,所以使用快捷键Ctrl+?搜索,由于jni文件有个规则,就比如:这个Binder中的init(),进行搜索的内容是包名+类名+方法名称只不过要把.号换成_,所以就是android_os_Binder_init().

static void android_os_Binder_init(JNIEnv* env, jobject obj){    JavaBBinderHolder* jbh = new JavaBBinderHolder();//[1]    if (jbh == NULL) {        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);        return;    }    ALOGV("Java Binder %p: acquiring first ref on holder %p", obj, jbh);    jbh->incStrong((void*)android_os_Binder_init);    env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);//将JavaBBinderHolder对象设置给gBinderOffsets.mObject}

1 JavaBBinderHolder()

class JavaBBinderHolder : public RefBase{public:    sp<JavaBBinder> get(JNIEnv* env, jobject obj)    {        AutoMutex _l(mLock);        sp<JavaBBinder> b = mBinder.promote();        if (b == NULL) {            b = new JavaBBinder(env, obj);//[1.1]            mBinder = b;        }        return b;    }    sp<JavaBBinder> getExisting()    {        AutoMutex _l(mLock);        return mBinder.promote();    }private:    Mutex           mLock;    wp<JavaBBinder> mBinder;};

1.1 JavaBBinder()

这里的object是Java层继承Binder的服务类

我们在这里看到了gBinderOffsets.mExecTransact这个是java层方法名字,我们找到赋值的对应代码

static int int_register_android_os_Binder(JNIEnv* env){    jclass clazz = FindClassOrDie(env, kBinderPathName);    gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz);    gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z");    gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");    return RegisterMethodsOrDie(        env, kBinderPathName,        gBinderMethods, NELEM(gBinderMethods));}

也就是说在调用int_register_android_os_Binder的时候execTransact这个java层的方法的id会存到gBinderOffsets.mExecTransac变量中。

class JavaBBinder : public BBinder{public:    JavaBBinder(JNIEnv* env, jobject object)        : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))    {        android_atomic_inc(&gNumLocalRefs);        incRefsCreated(env);    }    bool checkSubclass(const void* subclassID) const    {        return subclassID == &gBinderOffsets;    }    jobject object() const    {        return mObject;    }protected:    virtual ~JavaBBinder()    {        android_atomic_dec(&gNumLocalRefs);        JNIEnv* env = javavm_to_jnienv(mVM);        env->DeleteGlobalRef(mObject);    }    virtual status_t onTransact(        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)    {        JNIEnv* env = javavm_to_jnienv(mVM);        IPCThreadState* thread_state = IPCThreadState::self();        const int32_t strict_policy_before = thread_state->getStrictModePolicy();        //这个代码调用的是execTransact方法将这些数据传递。        jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,            code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);        if (code == SYSPROPS_TRANSACTION) {            BBinder::onTransact(code, data, reply, flags);        }        return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;    }    virtual status_t dump(int fd, const Vector<String16>& args)    {        return 0;    }private:    JavaVM* const   mVM;    jobject const   mObject;//对应的是Java层的Binder};

到了这里,我们已经将Java层的Binder服务和Native层的BBinder联系起来。,从驱动层上来调用onTransact()方法就可以到达Java层的execTransact()方法。


在这里我们也注意一个问题,由于onTransact()方法是BBinder的函数,而现在JavaBBinder覆写了这个函数,所以调用的时候会调用到execTransact(),那么在那块才调用onTransact()呢?

BpBinder::transact()->
IPCThreadState::transact()->
IPCThreadState::waitForResponse()->
IPCThreadState::executeCommand()


status_t IPCThreadState::executeCommand(int32_t cmd){    BBinder* obj;    RefBase::weakref_type* refs;    status_t result = NO_ERROR;    switch ((uint32_t)cmd) {    ...    case BR_TRANSACTION:        if (tr.target.ptr) {            sp<BBinder> b((BBinder*)tr.cookie);            error = b->transact(tr.code, buffer, &reply, tr.flags);        }    }    ...}

status_t BBinder::transact(    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){    status_t err = NO_ERROR;    switch (code) {        case PING_TRANSACTION:            reply->writeInt32(pingBinder());            break;        default:            err = onTransact(code, data, reply, flags);            break;    }  ...}

此时的BBinder的派生类是JavaBBinder类,然后调用它的onTransact()这个方法会调用java层的execTransact()方法。

在使用IPCThreadState::transact发送数据的时候会调用waitForResponse()然后调用executeCommand()然后调用transact()然后调用onTransact()

也就是说在native层回复数据的时候会调用到onTransact()方法。


Binder.java中
下面我们看一看Java层的execTransact()

    private boolean execTransact(int code, long dataObj, long replyObj,            int flags) {        Parcel data = Parcel.obtain(dataObj);        Parcel reply = Parcel.obtain(replyObj);        boolean res;        try {            res = onTransact(code, data, reply, flags);//回调继承java层Binder的onTransact()方法        } catch (RemoteException e) {            if ((flags & FLAG_ONEWAY) != 0) {                Log.w(TAG, "Binder call failed.", e);            } else {                reply.setDataPosition(0);                reply.writeException(e);            }            res = true;        } catch (RuntimeException e) {            if ((flags & FLAG_ONEWAY) != 0) {            } else {                reply.setDataPosition(0);                reply.writeException(e);            }            res = true;        } catch (OutOfMemoryError e) {            RuntimeException re = new RuntimeException("Out of memory", e);            reply.setDataPosition(0);            reply.writeException(re);            res = true;        }        checkParcel(this, code, reply, "Unreasonably large binder reply buffer");        reply.recycle();        data.recycle();        StrictMode.clearGatheredViolations();        return res;    }

我们下面将会看到对应java层Binder的方法

应用在Java层的Binder引用是通过Binder的代理完成的。

我们首先看一个aidl产生的文件,然后进行分析:

public interface IHelloService extends android.os.IInterface{    public static abstract class Stub extends android.os.Binder implements IHelloService    {        private static final java.lang.String DESCRIPTOR = "IHelloService";        public Stub()        {            this.attachInterface(this, DESCRIPTOR);        }        public static IHelloService asInterface(android.os.IBinder obj)        {            if ((obj==null)) {            return null;            }            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);            if (((iin!=null)&&(iin instanceof IHelloService))) {            return ((IHelloService)iin);            }            return new IHelloService.Stub.Proxy(obj);        }        @Override public android.os.IBinder asBinder()        {            return this;        }        @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException        {            switch (code)            {                case INTERFACE_TRANSACTION:                {                    reply.writeString(DESCRIPTOR);                    return true;                }                case TRANSACTION_sayhello:                {                    data.enforceInterface(DESCRIPTOR);                    this.sayhello();                    reply.writeNoException();                    return true;                }                case TRANSACTION_sayhello_to:                {                    data.enforceInterface(DESCRIPTOR);                    java.lang.String _arg0;                    _arg0 = data.readString();                    int _result = this.sayhello_to(_arg0);                    reply.writeNoException();                    reply.writeInt(_result);                    return true;                }            }            return super.onTransact(code, data, reply, flags);        }        private static class Proxy implements IHelloService        {            private android.os.IBinder mRemote;            Proxy(android.os.IBinder remote)            {                mRemote = remote;            }            @Override public android.os.IBinder asBinder()            {                return mRemote;            }            public java.lang.String getInterfaceDescriptor()            {                return DESCRIPTOR;            }            @Override public void sayhello() throws android.os.RemoteException            {                android.os.Parcel _data = android.os.Parcel.obtain();                android.os.Parcel _reply = android.os.Parcel.obtain();                try {                    _data.writeInterfaceToken(DESCRIPTOR);                    mRemote.transact(Stub.TRANSACTION_sayhello, _data, _reply, 0);                    _reply.readException();                }                finally {                    _reply.recycle();                    _data.recycle();                }            }            @Override public int sayhello_to(java.lang.String name) throws android.os.RemoteException            {                android.os.Parcel _data = android.os.Parcel.obtain();                android.os.Parcel _reply = android.os.Parcel.obtain();                int _result;                try {                    _data.writeInterfaceToken(DESCRIPTOR);                    _data.writeString(name);                    mRemote.transact(Stub.TRANSACTION_sayhello_to, _data, _reply, 0);                    _reply.readException();                    _result = _reply.readInt();                }                finally {                    _reply.recycle();                    _data.recycle();                }                    return _result;            }        }        static final int TRANSACTION_sayhello = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);        static final int TRANSACTION_sayhello_to = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);    }    public void sayhello() throws android.os.RemoteException;    public int sayhello_to(java.lang.String name) throws android.os.RemoteException;}

下面是调用方法:

/* 1. getService */IBinder binder = ServiceManager.getService("hello");if (binder == null){    System.out.println("can not get hello service");    Slog.i(TAG, "can not get hello service");    return;}IHelloService svr = IHelloService.Stub.asInterface(binder);

我们通过aidl产生的java文件可以看出来通过asInterface方法

public static IHelloService asInterface(android.os.IBinder obj){    if ((obj==null)) {    return null;    }    android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);    if (((iin!=null)&&(iin instanceof IHelloService))) {    return ((IHelloService)iin);    }    return new IHelloService.Stub.Proxy(obj);}private static class Proxy implements IHelloService{    private android.os.IBinder mRemote;    Proxy(android.os.IBinder remote)    {        mRemote = remote;    }    ...}

当调用的时候svr.sayhello();

就会调用:

@Override public void sayhello() throws android.os.RemoteException{    android.os.Parcel _data = android.os.Parcel.obtain();    android.os.Parcel _reply = android.os.Parcel.obtain();    try {        _data.writeInterfaceToken(DESCRIPTOR);        mRemote.transact(Stub.TRANSACTION_sayhello, _data, _reply, 0);        _reply.readException();    }    finally {        _reply.recycle();        _data.recycle();    }}

我们都知道mRemote其实就是BpBinder对象。

所以调用BpBinder对象的transact方法

status_t BpBinder::transact(    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){    if (mAlive) {        status_t status = IPCThreadState::self()->transact(            mHandle, code, data, reply, flags);        if (status == DEAD_OBJECT) mAlive = 0;        return status;    }    return DEAD_OBJECT;}

这个方法我们之前已经分析过了,是通过BpBinder的写数据,读数据

总结:

我们先从Binder的构造出发,因为Binder服务可以是SystemServer添加的服务,也可以是自己创建的匿名服务,但是都会调用构造方法。发现构造方法中调用native层的init方法,init()方法做的事情就是创建JavaBBinderHolder对象这个对象中get方法会得到JavaBBinder对象,JavaBBinder对象继承BBinder类。并且重写BBinder的onTransact()方法,onTransact()会调用java层的execTransact(),这样就可以将Java层和native层的连接起来。

然后我们分析了从驱动如何调用到BBinder的onTransact()方法,我们的调用顺序是:
BpBinder::transact()-> IPCThreadState::transact()-> IPCThreadState::waitForResponse()-> IPCThreadState::executeCommand()
我们上篇文章分析了BpBinder是BpServiceManager成员变量mRemote也就是native层通过sp<IServiceManager> sm(defaultServiceManager());方法得到的.

其中BpBinder可以调用到BpBinder::transact()->IPCThreadState::self()->transact()和驱动进行通信.这个方法会调用到IPCThreadState::executeCommand()这个方法会调用

sp<BBinder> b((BBinder*)tr.cookie);error = b->transact(tr.code, buffer, &reply, tr.flags);

其中b->transact()会调用onTransact()这里注意b是BBinder我们在java代码中看到是JavaBBinder继承与BBinder,所以此时会调用JavaBBinder的onTransact(),在这个回调函数中我们将可以看到调用execTransact(),然后我们在Binder.java的execTransact()方法中看到又调用Binder.java的onTransact()方法,所以回调了我们生成的aidl文件中的onTransact()方法。

最后我们也从java层出发看了是如何通信到底层的,我们在aidl产生的文件中可以看到

sayhello():    mRemote.transact(Stub.TRANSACTION_sayhello, _data, _reply, 0);

其中mRemote就是BpBinder。

这样我们就从java到底层完成了整个流程的创建。

1 0
原创粉丝点击