Android AIDL实现服务注册分析

每天一篇系列:
强化知识体系,查漏补缺。
欢迎指正,共同学习!

目标:注册一个自定义的服务,实现跨进程通信。

JAVA方法:

先定义一个AIDL接口:

package com.test.lib;
interface IMyService {
  void setValue(int val);
  int getValue();
}

继承接口Stub:

package com.test.myservice;
import android.os.RemoteException;
import com.test.lib.IMyService;
public class MyService extends IMyService.Stub {
  private int value;

  @Override
  public void setValue(int val) throws RemoteException {
    this.value = val;
  }
  @Override
  public int getValue() throws RemoteException {
    return value;
  }
}

通过ServiceManager注册服务:

package com.test.myservice;
import android.app.Application;
import android.os.ServiceManager;
public class MyServiceApplication extends Application{
  @Override
  public void onCreate() {
    super.onCreate();
    ServiceManager.addService("MYSERVICE", new MyService());
  }
}

服务注册后,就可以通过以下方式获得这个自定义的Service:

IMyService myservice = IMyService.Stub.asInterface(ServiceManager.getService("MYSERVICE"));

那么为什么可以这样做到跨进程通信呢?
首先分析服务的注册:

    public static void addService(String name, IBinder service) {
        try {
            getIServiceManager().addService(name, service, false);
        } catch (RemoteException e) {
            Log.e(TAG, "error in addService", e);
        }
    }

    private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }

        // Find the service manager
        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
        return sServiceManager;
    }

从这里看的话,有两个知识点需要分析。
ServiceManagerNative.asInterface:

    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);
    }

另外一个知识点BinderInternal.getContextObject():

    public static final native IBinder getContextObject();

getContextObject是一个native方法,在android_util_Binder.cpp中创建了Java层Binder和Native层Bindler的通信,在JNI层需要先注册Binder相关函数:

int register_android_os_Binder(JNIEnv* env)
{
    if (int_register_android_os_Binder(env) < 0)
        return -1;
    if (int_register_android_os_BinderInternal(env) < 0)
        return -1;
    if (int_register_android_os_BinderProxy(env) < 0)
        return -1;

    jclass clazz;

    clazz = env->FindClass("android/util/Log");
    LOG_FATAL_IF(clazz == NULL, "Unable to find class android.util.Log");
    gLogOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
    gLogOffsets.mLogE = env->GetStaticMethodID(
        clazz, "e", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I");
    assert(gLogOffsets.mLogE);

    clazz = env->FindClass("android/os/ParcelFileDescriptor");
    LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor");
    gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
    gParcelFileDescriptorOffsets.mConstructor
        = env->GetMethodID(clazz, "", "(Ljava/io/FileDescriptor;)V");

    clazz = env->FindClass("android/os/StrictMode");
    LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.StrictMode");
    gStrictModeCallbackOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
    gStrictModeCallbackOffsets.mCallback = env->GetStaticMethodID(
        clazz, "onBinderStrictModePolicyChange", "(I)V");
    LOG_FATAL_IF(gStrictModeCallbackOffsets.mCallback == NULL,
                 "Unable to find strict mode callback.");
    return 0;
}
const char* const kBinderPathName = "android/os/Binder";
static int int_register_android_os_Binder(JNIEnv* env)
{
    jclass clazz;

    clazz = env->FindClass(kBinderPathName);
    LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Binder");

    gBinderOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
    gBinderOffsets.mExecTransact
        = env->GetMethodID(clazz, "execTransact", "(IJJI)Z");
    assert(gBinderOffsets.mExecTransact);

    gBinderOffsets.mObject
        = env->GetFieldID(clazz, "mObject", "J");
    assert(gBinderOffsets.mObject);

    return AndroidRuntime::registerNativeMethods(
        env, kBinderPathName,
        gBinderMethods, NELEM(gBinderMethods));
}
static void android_os_Binder_init(JNIEnv* env, jobject obj)
{
    JavaBBinderHolder* jbh = new JavaBBinderHolder();
    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);
}
static int int_register_android_os_BinderProxy(JNIEnv* env)
{
    jclass clazz;

    clazz = env->FindClass("java/lang/Error");
    LOG_FATAL_IF(clazz == NULL, "Unable to find class java.lang.Error");
    gErrorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);

    clazz = env->FindClass(kBinderProxyPathName);
    LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.BinderProxy");

    gBinderProxyOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
    gBinderProxyOffsets.mConstructor
        = env->GetMethodID(clazz, "", "()V");
    assert(gBinderProxyOffsets.mConstructor);
    gBinderProxyOffsets.mSendDeathNotice
        = env->GetStaticMethodID(clazz, "sendDeathNotice", "(Landroid/os/IBinder$DeathRecipient;)V");
    assert(gBinderProxyOffsets.mSendDeathNotice);

    gBinderProxyOffsets.mObject
        = env->GetFieldID(clazz, "mObject", "J");
    assert(gBinderProxyOffsets.mObject);
    gBinderProxyOffsets.mSelf
        = env->GetFieldID(clazz, "mSelf", "Ljava/lang/ref/WeakReference;");
    assert(gBinderProxyOffsets.mSelf);
    gBinderProxyOffsets.mOrgue
        = env->GetFieldID(clazz, "mOrgue", "J");
    assert(gBinderProxyOffsets.mOrgue);

    clazz = env->FindClass("java/lang/Class");
    LOG_FATAL_IF(clazz == NULL, "Unable to find java.lang.Class");
    gClassOffsets.mGetName = env->GetMethodID(clazz, "getName", "()Ljava/lang/String;");
    assert(gClassOffsets.mGetName);

    return AndroidRuntime::registerNativeMethods(
        env, kBinderProxyPathName,
        gBinderProxyMethods, NELEM(gBinderProxyMethods));
}

来看BinderInternal:

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
    sp b = ProcessState::self()->getContextObject(NULL);
    return javaObjectForIBinder(env, b);
}

ProcessState::self()->getContextObject(NULL);返回的是service_manager创建的BpBinder(0)。javaObjectForIBinder如下:

jobject javaObjectForIBinder(JNIEnv* env, const sp& val)
{
    //安全检查,BpBinder(0)创建一次后就不会为NULL
    if (val == NULL) return NULL;
    //注意gBinderOffsets,在通过反射JAVA类,如果是Java的Binder类,则val.get()的是JavaBBinder?
    if (val->checkSubclass(&gBinderOffsets)) {
        jobject object = static_cast(val.get())->object();
        LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
        return object;
    }

    AutoMutex _l(mProxyLock);
    //注意gBinderProxyOffsets,如果之前已经创建过BinderProxy并且把BinderProxy保存到val的Object中,就先删掉
    jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
    if (object != NULL) {
        jobject res = jniGetReferent(env, object);
        if (res != NULL) {
            ALOGV("objectForBinder %p: found existing %p!\n", val.get(), res);
            return res;
        }
        LOGDEATH("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get());
        android_atomic_dec(&gNumProxyRefs);
        val->detachObject(&gBinderProxyOffsets);
        env->DeleteGlobalRef(object);
    }

    //注意gBinderProxyOffsets初始化,创建一个新的BinderProxy对象。并将它注册到Native BpBinder对象的ObjectManager中
    object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
    if (object != NULL) {
        LOGDEATH("objectForBinder %p: created new proxy %p !\n", val.get(), object);
        // The proxy holds a reference to the native object.
        //把Native层的BpProxy的指针保存到BinderProxy对象的成员字段mObject中。于是BinderProxy对象的Native方法可以通过mObject获取BpProxy对象的指针。这个操作是将BinderProxy与BpProxy联系起来的纽带
        env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
        val->incStrong((void*)javaObjectForIBinder);

        // The native object needs to hold a weak reference back to the
        // proxy, so we can retrieve the same proxy if it is still active.
        jobject refObject = env->NewGlobalRef(
                env->GetObjectField(object, gBinderProxyOffsets.mSelf));
        // 将这个新创建的BinderProxy对象注册(attach)到BpBinder的ObjectManager中,同时注册一个回收函数proxy_cleanup。当BinderProxy对象撤销(detach)的时候,该函数会被调用,以释放一些资源。
        val->attachObject(&gBinderProxyOffsets, refObject,
                jnienv_to_javavm(env), proxy_cleanup);

        // Also remember the death recipients registered on this proxy
        sp drl = new DeathRecipientList;
        drl->incStrong((void*)javaObjectForIBinder);
        env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast(drl.get()));

        // Note that a new object reference has been created.
        android_atomic_inc(&gNumProxyRefs);
        incRefsCreated(env);
    }
    //这里的object就是创建出来的BinderProxy
    return object;
}

创建了一个BinderProxy对象,通过JNI,把BinderProxy对象和一个Native的BpProxy(在这里是BpBinder(0))对象挂钩,而该BpProxy对象的通信目标就是ServiceManager。
再来分析IServiceManager的asInterface:

sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
public abstract class ServiceManagerNative extends Binder implements IServiceManager
{
    static public IServiceManager asInterface(IBinder obj)
    {
        if (obj == null) {
            return null;
        }
        //这里的obj实际上就是native层通过JNI创建的BinderProxy,因此这里返回为null
        IServiceManager in =
            (IServiceManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }
        return new ServiceManagerProxy(obj);
    }
    ...

class ServiceManagerProxy implements IServiceManager {
    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;
    }
    
    public IBinder asBinder() {
        return mRemote;
    }
  
    ...
    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);
        data.writeInt(allowIsolated ? 1 : 0);
        mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
        reply.recycle();
        data.recycle();
    }
    ...

传递给ServiceManagerProxy的参数正是BinderInternal.getContextObject()创建的BinderProxy,也就是说mRemote的调用就是BinderProxy的调用。
[特别留意:在addService方法中data.writeStrongBinder(service)后面会使用到]
继续分析transact:

final class BinderProxy implements IBinder {
    ...
    public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
        return transactNative(code, data, reply, flags);
    }

    public native boolean transactNative(int code, Parcel data, Parcel reply,
            int flags) throws RemoteException;
    ...
  static void checkParcel(IBinder obj, int code, Parcel parcel, String msg) {
        if (CHECK_PARCEL_SIZE && parcel.dataSize() >= 800*1024) {
            // Trying to send > 800k, this is way too much
            StringBuilder sb = new StringBuilder();
            sb.append(msg);
            sb.append(": on ");
            sb.append(obj);
            sb.append(" calling ");
            sb.append(code);
            sb.append(" size ");
            sb.append(parcel.dataSize());
            sb.append(" (data: ");
            parcel.setDataPosition(0);
            sb.append(parcel.readInt());
            sb.append(", ");
            sb.append(parcel.readInt());
            sb.append(", ");
            sb.append(parcel.readInt());
            sb.append(")");
            Slog.wtfStack(TAG, sb.toString());
        }
    }

可以看到Binder在的CHECK_PARCEL_SIZE开关打开的情况下,可以校验Binder传输最大字节数是800K。transactNative是JNI方法:

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
        jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
    if (dataObj == NULL) {
        jniThrowNullPointerException(env, NULL);
        return JNI_FALSE;
    }
    // java的参数转换为c层的参数类型
    Parcel* data = parcelForJavaObject(env, dataObj);
    if (data == NULL) {
        return JNI_FALSE;
    }
    Parcel* reply = parcelForJavaObject(env, replyObj);
    if (reply == NULL && replyObj != NULL) {
        return JNI_FALSE;
    }
    // 从obj(在BinderInternal.getContextObject()创建的BinderProxy)中获取BpProxy,因为之前已经把BpBinder(0)保存在gBinderProxyOffsets.mObject中
    IBinder* target = (IBinder*)
        env->GetLongField(obj, gBinderProxyOffsets.mObject);
    if (target == NULL) {
        jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");
        return JNI_FALSE;
    }

    ALOGV("Java code calling transact on %p in Java object %p with code %" PRId32 "\n",
            target, obj, code);

#if ENABLE_BINDER_SAMPLE
    // Only log the binder call duration for things on the Java-level main thread.
    // But if we don't
    const bool time_binder_calls = should_time_binder_calls();

    int64_t start_millis;
    if (time_binder_calls) {
        start_millis = uptimeMillis();
    }
#endif
    //printf("Transact from Java code to %p sending: ", target); data->print();
    // 从mObject中获取的BpProxy即BpBinder(0),调用transact ,那么就会在service_manager处理。
    status_t err = target->transact(code, *data, reply, flags);
    //if (reply) printf("Transact from Java code to %p received: ", target); reply->print();
#if ENABLE_BINDER_SAMPLE
    if (time_binder_calls) {
        conditionally_log_binder_call(start_millis, target, code);
    }
#endif

    if (err == NO_ERROR) {
        return JNI_TRUE;
    } else if (err == UNKNOWN_TRANSACTION) {
        return JNI_FALSE;
    }

    signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/);
    return JNI_FALSE;
}

这样就把Java层Service的注册交给了Native层的service_manager。
服务的注册:

ServiceManager.addService("MYSERVICE", new MyService());

addService时data.writeStrongBinder(service)这个参数需要是IBinder,而MyService继承了Binder,Binder又继承于IBinder:

public class MyService extends IMyService.Stub {
  ...
}

AIDL文件编译后如下:

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: F:\\Eclipse_ThinkAndroid\\ApitestDemo\\src\\com\\test\\lib\\IMyService.aidl
 */
package com.test.lib;

public interface IMyService extends android.os.IInterface {
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements
            com.test.lib.IMyService {
        private static final java.lang.String DESCRIPTOR = "com.test.lib.IMyService";

        /** Construct the stub at attach it to the interface. */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an com.test.lib.IMyService interface,
         * generating a proxy if needed.
         */
        public static com.test.lib.IMyService asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.test.lib.IMyService))) {
                return ((com.test.lib.IMyService) iin);
            }
            return new com.test.lib.IMyService.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_setValue: {
                data.enforceInterface(DESCRIPTOR);
                int _arg0;
                _arg0 = data.readInt();
                this.setValue(_arg0);
                reply.writeNoException();
                return true;
            }
            case TRANSACTION_getValue: {
                data.enforceInterface(DESCRIPTOR);
                int _result = this.getValue();
                reply.writeNoException();
                reply.writeInt(_result);
                return true;
            }
            }
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements com.test.lib.IMyService {
            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 setValue(int val) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeInt(val);
                    mRemote.transact(Stub.TRANSACTION_setValue, _data, _reply,
                            0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            @Override
            public int getValue() 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);
                    mRemote.transact(Stub.TRANSACTION_getValue, _data, _reply,
                            0);
                    _reply.readException();
                    _result = _reply.readInt();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }

        static final int TRANSACTION_setValue = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_getValue = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    }

    public void setValue(int val) throws android.os.RemoteException;

    public int getValue() throws android.os.RemoteException;
}
    public void attachInterface(IInterface owner, String descriptor) {
        mOwner = owner;
        mDescriptor = descriptor;
    }

可以看到IMyService继承了IInterface,IMyService.Stub继承了Binder并且实现了IMyService接口。Proxy是Stub抽象类的代理,Proxy实际实现了IMyService接口的处理,作用是从service_manager获取IMyService的BpProxy。new MyService()可以认为等同于new Stub()。所以在addService时data.writeStrongBinder(service)传入的参数就是这个Stub。
经过上面的分析,Java层通过的服务注册还是要借助C层service_manager [ProcessState::self()->getContextObject(NULL);] 的Binder机制。BpBinder(0)如何注册服务这里不分析了。

服务注册后,需要在客户端使用:

IMyService myservice = IMyService.Stub.asInterface(ServiceManager.getService("MYSERVICE"));

首先看看ServiceManager.getService:

    public static IBinder getService(String name) {
        try {
            //看cache中是否有,比如同一段时间内连续调用AIDL接口,这里就能提交效率
            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;
    }

和addService流程一样,通过JNI调用后获得BinderProxy:

    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 IBinder getService(String name) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
        IBinder binder = reply.readStrongBinder();
        reply.recycle();
        data.recycle();
        return binder;
    }

和addService的writeStrongBinder对应,getService中对应的是IBinder binder = reply.readStrongBinder();这里有一个问题需要思考,addSevice时是给native service_manager注册的一个Stub,那么getSevice应该是什么?可以先大胆的假设getService就是add时的Stub。
writeStrongBinder和readStrongBinder调用的都是native层方法:

public final class Parcel {
...
    public final void writeStrongBinder(IBinder val) {
        nativeWriteStrongBinder(mNativePtr, val);
    }
    private static native void nativeWriteStrongBinder(long nativePtr, IBinder val);
    private static native IBinder nativeReadStrongBinder(long nativePtr);
...
}

对应的JNI实现:

static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
{
    Parcel* parcel = reinterpret_cast(nativePtr);
    if (parcel != NULL) {
        const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
        if (err != NO_ERROR) {
            signalExceptionForError(env, clazz, err);
        }
    }
}
static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
{
    Parcel* parcel = reinterpret_cast(nativePtr);
    if (parcel != NULL) {
        return javaObjectForIBinder(env, parcel->readStrongBinder());
    }
    return NULL;
}

ibinderForJavaObject和javaObjectForIBinder这是相对的方法。介绍ibinderForJavaObject之前先看以下方法:

    public Binder() {
        init();

        if (FIND_POTENTIAL_LEAKS) {
            final Class klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Binder class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }
    }

新建一个Binder的时候都会被调用。

static void android_os_Binder_init(JNIEnv* env, jobject obj)
{
    JavaBBinderHolder* jbh = new JavaBBinderHolder();
    if (jbh == NULL) {
        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
        return;
    }
    ALOGV("Java Binder %p: acquiring first ref on holder %p", obj, jbh);
     //自增作为句柄,并且把JavaBBinderHolder写入到Binder对象的mObject,之后会需要使用
    jbh->incStrong((void*)android_os_Binder_init); 
    env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);
}

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);
            mBinder = b;
            ALOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%" PRId32 "\n",
                 b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount());
        }

        return b;
    }

    sp getExisting()
    {
        AutoMutex _l(mLock);
        return mBinder.promote();
    }

private:
    Mutex           mLock;
    wp mBinder;
}

了解了以上几点后,再来看ibinderForJavaObject:

sp ibinderForJavaObject(JNIEnv* env, jobject obj)
{
    if (obj == NULL) return NULL;
    //gBinderOffsets.mClass对应的是android/os/Binder,例如在Java层添加自定义的Service时就继承的android/os/Binder,因此会在此处理
    if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
        JavaBBinderHolder* jbh = (JavaBBinderHolder*)
            //这里是获取JAVA层Binder对象的句柄?这个值是在android_os_Binder_init时写入的
            env->GetLongField(obj, gBinderOffsets.mObject);
        return jbh != NULL ? jbh->get(env, obj) : NULL;
    }
    //gBinderProxyOffsets.mClass对应的是android/os/BinderProxy
    if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
        return (IBinder*)
            //这里返回的就是从BinderProxy中获取的BpBinder(0)
            env->GetLongField(obj, gBinderProxyOffsets.mObject);
    }

    ALOGW("ibinderForJavaObject: %p is not a Binder object", obj);
    return NULL;
}

在Java层添加自定义的Service时继承的android/os/Binder,因此会默认创建出一个句柄JavaBBinderHolder,此时在addService时,会调用JavaBBinderHolder的get函数,返回一个创建出来的JavaBBinder:

class JavaBBinder : public BBinder
{
public:
    JavaBBinder(JNIEnv* env, jobject object)
        : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))
    {
        ALOGV("Creating JavaBBinder %p\n", this);
        android_atomic_inc(&gNumLocalRefs);
        incRefsCreated(env);
    }
    ...

此时Java层的Stub已经保存在JavaBBinder的mObject中。 也就是在这个流程里addService的时候ibinderForJavaObject返回的是一个JavaBBinder的指针。写入到service_manager的就是一个JavaBBinder,JavaBBinder持有了Java层创建的Binder对象。

status_t Parcel::writeStrongBinder(const sp& val)
{
    return flatten_binder(ProcessState::self(), val, this);
}
status_t flatten_binder(const sp& /*proc*/,
    const sp& binder, Parcel* out)
{
    flat_binder_object obj;

    obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
    if (binder != NULL) {
        IBinder *local = binder->localBinder();
        if (!local) {
            BpBinder *proxy = binder->remoteBinder();
            if (proxy == NULL) {
                ALOGE("null proxy");
            }
            const int32_t handle = proxy ? proxy->handle() : 0;
            obj.type = BINDER_TYPE_HANDLE;
            obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
            obj.handle = handle;
            obj.cookie = 0;
        } else {
            obj.type = BINDER_TYPE_BINDER;
            obj.binder = reinterpret_cast(local->getWeakRefs());
            obj.cookie = reinterpret_cast(local);
        }
    } else {
        obj.type = BINDER_TYPE_BINDER;
        obj.binder = 0;
        obj.cookie = 0;
    }

    return finish_flatten_binder(binder, obj, out);
}

从Parcel::writeStrongBinder中可以看到,binder是localBinder时,保存的是binder的指针引用,而binder是remoteBinder时,保存的是binder的句柄。
JavaBBinder是继承BBinder的,我们看BBinder的localBinder:

BBinder* BBinder::localBinder()
{
    return this;
}

那么很明显的,我们能知道在native中我们保存的是JavaBBinder的指针引用。
在来看看对应的javaObjectForIBinder方法:

jobject javaObjectForIBinder(JNIEnv* env, const sp& val)
{
    if (val == NULL) return NULL;

    if (val->checkSubclass(&gBinderOffsets)) {
        // One of our own!
        jobject object = static_cast(val.get())->object();
        LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
        return object;
    }
    ...
}

首先我们需要清楚javaObjectForIBinder参数中的val具体是什么?
他是parcel->readStrongBinder()读取出来的,应该也是JavaBBinder:

sp Parcel::readStrongBinder() const
{
    sp val;
    unflatten_binder(ProcessState::self(), *this, &val);
    return val;
}
status_t unflatten_binder(const sp& proc,
    const Parcel& in, sp* out)
{
    const flat_binder_object* flat = in.readObject(false);

    if (flat) {
        switch (flat->type) {
            case BINDER_TYPE_BINDER:
                *out = reinterpret_cast(flat->cookie);
                return finish_unflatten_binder(NULL, *flat, in);
            case BINDER_TYPE_HANDLE:
                *out = proc->getStrongProxyForHandle(flat->handle);
                return finish_unflatten_binder(
                    static_cast(out->get()), *flat, in);
        }
    }
    return BAD_TYPE;
}

在Write时保存的是BINDER_TYPE_BINDER,Read的时候当然也是这个类型,那么返回的就是reinterpret_cast(flat->cookie),再回去看Write,flat->cookie不正是JavaBBinder嘛。
至此也就是说javaObjectForIBinder传入的val是JavaBBinder,那么我们再来分析getService时,IBinder binder = reply.readStrongBinder();到底返回了一个什么:

val->checkSubclass(&gBinderOffsets)

因为val返回的是JavaBBinder:

class JavaBBinder : public BBinder
{
    ...
    bool    checkSubclass(const void* subclassID) const
    {
        return subclassID == &gBinderOffsets;
    }
    jobject object() const
    {
        return mObject;
    }
    ...
}

那么返回的正好也就是:

jobject object = static_cast(val.get())->object();

JavaBBinder在创建的时候把Java层的Stub保存到mObject过,所以这里不就是在addService的时候new MyService()的对象嘛。那么客户端就可以通过getService获取这个引用,可以看到这个mOwner就是add时的Stub,客户端在使用是通过asInterface创建一个Proxy,Proxy实现了IMyService的接口且持有mRemote(Stub),最终都会通过Proxy中的mRemote去调用。

技巧:没发现嘛?使用writeStrongBinder和readStrongBinder是可以达到双端通信的,具体内容需要思考。

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

mRemote不就是分析就是创建时的JavaBBinder嘛,JavaBBinder继承BBinder,但是没有重写transact,所以在JNI调用的时候会调用BBinder的transact:

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);
            break;
    }

    if (reply != NULL) {
        reply->setDataPosition(0);
    }

    return err;
}

进而调用到onTransact方法,而JavaBBinder重写了onTransact:

    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");

        //会去调用mObject的mExecTransact,而这个mObject就是之前绑定的JAVA的Binder对象,
        jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
            code, reinterpret_cast(&data), reinterpret_cast(reply), flags);
        jthrowable excep = env->ExceptionOccurred();

        if (excep) {
            report_exception(env, excep,
                "*** Uncaught remote exception!  "
                "(Exceptions are not yet supported across processes.)");
            res = JNI_FALSE;

            /* clean up JNI local ref -- we don't return to Java code */
            env->DeleteLocalRef(excep);
        }

        // Check if the strict mode state changed while processing the
        // call.  The Binder state will be restored by the underlying
        // Binder system in IPCThreadState, however we need to take care
        // of the parallel Java state as well.
        if (thread_state->getStrictModePolicy() != strict_policy_before) {
            set_dalvik_blockguard_policy(env, strict_policy_before);
        }

        jthrowable excep2 = env->ExceptionOccurred();
        if (excep2) {
            report_exception(env, excep2,
                "*** Uncaught exception in onBinderStrictModePolicyChange");
            /* clean up JNI local ref -- we don't return to Java code */
            env->DeleteLocalRef(excep2);
        }

        // Need to always call through the native implementation of
        // SYSPROPS_TRANSACTION.
        if (code == SYSPROPS_TRANSACTION) {
            BBinder::onTransact(code, data, reply, flags);
        }

        //aout << "onTransact to Java code; result=" << res << endl
        //    << "Transact from " << this << " to Java code returning "
        //    << reply << ": " << *reply << endl;
        return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;
    }

会去调用mObject的mExecTransact,而这个mObject就是之前绑定的JAVA的Binder对象,因此会调用到Java层的Binder方法execTransact:

    // Entry point from android_util_Binder.cpp's onTransact
    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);
        } 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) {
                Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);
            } else {
                reply.setDataPosition(0);
                reply.writeException(e);
            }
            res = true;
        } catch (OutOfMemoryError e) {
            // Unconditionally log this, since this is generally unrecoverable.
            Log.e(TAG, "Caught an OutOfMemoryError from the binder stub implementation.", 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();
        ...
    }
}

其中又调用了onTransact方法,onTransact是在Binder子类中实现的,子类就可以重写该方法,实现方法处理了。而AIDL是自动生成了onTransact的实现:

   @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_setValue: {
                data.enforceInterface(DESCRIPTOR);
                int _arg0;
                _arg0 = data.readInt();
                this.setValue(_arg0);
                reply.writeNoException();
                return true;
            }
            case TRANSACTION_getValue: {
                data.enforceInterface(DESCRIPTOR);
                int _result = this.getValue();
                reply.writeNoException();
                reply.writeInt(_result);
                return true;
            }
        }
        return super.onTransact(code, data, reply, flags);
    }

可以看到onTransact方法里分别对setValue和getValue作了处理,并从服务端MyService返回处理结果,这也是为什么MyService要重写setValue,getValue接口。

Binder模块我还会持续更新文章,Native层的我现在还没有整理完整,后续更新。

你可能感兴趣的:(Android AIDL实现服务注册分析)