Java层到Native层Binder的流程

我们在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 get(JNIEnv* env, jobject obj)
    {
        AutoMutex _l(mLock);
        sp b = mBinder.promote();
        if (b == NULL) {
            b = new JavaBBinder(env, obj);//[1.1]
            mBinder = b;
        }
        return b;
    }
    sp getExisting()
    {
        AutoMutex _l(mLock);
        return mBinder.promote();
    }
private:
    Mutex           mLock;
    wp 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(&data), reinterpret_cast(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& 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 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 sm(defaultServiceManager());方法得到的.

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

sp 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到底层完成了整个流程的创建。

你可能感兴趣的:(Android系统)