Binder Java 层服务注册过程分析

1. Java 层全体结构

在剖析之前,咱们要理解,Java 仅仅一层便利 Java 程序运用的接口,Binder 的核心功用完成都是经过 JNI 调用到 Native 层来完成的,这儿先给出 Java 层的全体结构图:

Binder Java 层服务注册过程分析

接下来几篇文章咱们逐步剖析,解密整张结构图。

2. 服务注册

在 Binder 程序示例之 Java 篇 中介绍的示例程序中,Server 端咱们运用如下代码注册咱们界说的服务:

ServiceManager.addService("hello", new HelloService());

addService 是 frameworks/base/core/java/android/os/ServiceManager.java 中界说的静态办法:

@UnsupportedAppUsage
public static  void addService(String name, IBinder service) {
    addService(name, service, false, IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT);
}
 @UnsupportedAppUsage
public static void addService(String name, IBinder service, boolean allowIsolated) {
    addService(name, service, allowIsolated, IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT);
}
@UnsupportedAppUsage
public static void addService(String name, IBinder service, boolean allowIsolated,int dumpPriority) {
    try {
            getIServiceManager().addService(name, service, allowIsolated, dumpPriority);
        } catch (RemoteException e) {
            Log.e(TAG, "error in addService", e);
        }
}

经过层层调用,调用到 getIServiceManager().addService(name, service, allowIsolated, dumpPriority); :

2.1 getIServiceManager()

咱们先看看 getIServiceManager,该办法是界说在 ServiceManager 类中的静态办法:

//frameworks/base/core/java/android/os/ServiceManager.java
    @UnsupportedAppUsage
    private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }
        // 等价于 new ServiceManagerProxy(new BinderProxy(0))
        // 可是实践过程有点曲折
        sServiceManager = ServiceManagerNative
                .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
        return sServiceManager;
    }

接着咱们逐一剖析三个办法调用:

BinderInternal.getContextObject()
Binder.allowBlocking
ServiceManagerNative.asInterface

2.1.1 BinderInternal.getContextObject

//frameworks/base/core/java/com/android/internal/os/BinderInternal.java
// 回来一个 BinderProxy 目标
@UnsupportedAppUsage
public static final native IBinder getContextObject();

getContextObject 是一个 native 办法,在之前的文章中咱们说到 BinderInternal 在进程启动时注册了其 native 办法,其 native 完成在 frameworks/base/core/jni/android_util_Binder.cpp 中:

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
    //此处回来的是 new BpBinder(0)
    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
    //此处回来的是 new BinderProxy()
    return javaObjectForIBinder(env, b);
}

接着看 getContextObject 的完成:

sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
    return getStrongProxyForHandle(0);
}
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp<IBinder> result;
    AutoMutex _l(mLock);
    handle_entry* e = lookupHandleLocked(handle);
    if (e != nullptr) {
        IBinder* b = e->binder;
        if (b == nullptr || !e->refs->attemptIncWeak(this)) {
            if (handle == 0) {
                Parcel data;
                status_t status = IPCThreadState::self()->transact(
                        0, IBinder::PING_TRANSACTION, data, nullptr, 0);
                if (status == DEAD_OBJECT)
                   return nullptr;
            }
            //走这儿
            b = BpBinder::create(handle);
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }
    return result;
}
BpBinder* BpBinder::create(int32_t handle) {
    int32_t trackedUid = -1;
    if (sCountByUidEnabled) {
        trackedUid = IPCThreadState::self()->getCallingUid();
        AutoMutex _l(sTrackingLock);
        uint32_t trackedValue = sTrackingMap[trackedUid];
        if (CC_UNLIKELY(trackedValue & LIMIT_REACHED_MASK)) {
            if (sBinderProxyThrottleCreate) {
                return nullptr;
            }
        } else {
            if ((trackedValue & COUNTING_VALUE_MASK) >= sBinderProxyCountHighWatermark) {
                ALOGE("Too many binder proxy objects sent to uid %d from uid %d (%d proxies held)",
                      getuid(), trackedUid, trackedValue);
                sTrackingMap[trackedUid] |= LIMIT_REACHED_MASK;
                if (sLimitCallback) sLimitCallback(trackedUid);
                if (sBinderProxyThrottleCreate) {
                    ALOGI("Throttling binder proxy creates from uid %d in uid %d until binder proxy"
                          " count drops below %d",
                          trackedUid, getuid(), sBinderProxyCountLowWatermark);
                    return nullptr;
                }
            }
        }
        sTrackingMap[trackedUid]++;
    }
    //走这儿
    return new BpBinder(handle, trackedUid);
}

代码看着很繁琐,实践流程其实很简单便是 new BpBinder(0)

接着看 javaObjectForIBinder 的完成:

//frameworks/base/core/jni/android_util_Binder.cpp
//当前情形下, val 的类型是 BpBinder
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
    if (val == NULL) return NULL;
    if (val->checkSubclass(&gBinderOffsets)) {
        // It's a JavaBBinder created by ibinderForJavaObject. Already has Java object.
        jobject object = static_cast<JavaBBinder*>(val.get())->object();
        LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
        return object;
    }
    //构造 BinderProxyNativeData 结构体
    BinderProxyNativeData* nativeData = new BinderProxyNativeData();
    nativeData->mOrgue = new DeathRecipientList;
    nativeData->mObject = val;
    //gBinderProxyOffsets 中保存了 BinderProxy 类相关的信息
    //调用 Java 层 GetInstance 办法获得一个 BinderProxy 目标
    jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
            gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get());
    if (env->ExceptionCheck()) { //异常处理
        // In the exception case, getInstance still took ownership of nativeData.
        return NULL;
    }
    BinderProxyNativeData* actualNativeData = getBPNativeData(env, object);
    if (actualNativeData == nativeData) {
        // Created a new Proxy
        uint32_t numProxies = gNumProxies.fetch_add(1, std::memory_order_relaxed);
        uint32_t numLastWarned = gProxiesWarned.load(std::memory_order_relaxed);
        if (numProxies >= numLastWarned + PROXY_WARN_INTERVAL) {
            // Multiple threads can get here, make sure only one of them gets to
            // update the warn counter.
            if (gProxiesWarned.compare_exchange_strong(numLastWarned,
                        numLastWarned + PROXY_WARN_INTERVAL, std::memory_order_relaxed)) {
                ALOGW("Unexpectedly many live BinderProxies: %d\n", numProxies);
            }
        }
    } else {
        delete nativeData;
    }
    //回来 BinderProxy
    return object;
}

native 代码调用了 BinderProxy 的 getInstance 办法:

// frameworks/base/core/java/android/os/BinderProxy.java
 private static BinderProxy getInstance(long nativeData, long iBinder) {
        BinderProxy result;
        synchronized (sProxyMap) {
            try {
                result = sProxyMap.get(iBinder);
                if (result != null) {
                    return result;
                }
                result = new BinderProxy(nativeData);
            } catch (Throwable e) {
                // We're throwing an exception (probably OOME); don't drop nativeData.
                NativeAllocationRegistry.applyFreeFunction(NoImagePreloadHolder.sNativeFinalizer,
                        nativeData);
                throw e;
            }
            NoImagePreloadHolder.sRegistry.registerNativeAllocation(result, nativeData);
            // The registry now owns nativeData, even if registration threw an exception.
            sProxyMap.set(iBinder, result);
        }
        return result;
    }

代码很繁琐,可是从结果上来说仍是比较简单的:

  • getContextObject 函数 new 了一个 BpBinder(c++结构体),其内部的 handle 是 0
  • javaObjectForIBinder 函数 new 了一个 BinderProxy(Java 目标),其内部成员 mNativeData 是一个 native 层指针,指向一个 BinderProxyNativeData,BinderProxyNativeData 的成员 mObject 指向上述的 BpBinder。

全体结构用一个图表示如下:

Binder Java 层服务注册过程分析

2.1.2 Binder.allowBlocking

    //这儿传入的是 BinderProxy 目标
    public static IBinder allowBlocking(IBinder binder) {
        try {
            if (binder instanceof BinderProxy) { //走这儿
                ((BinderProxy) binder).mWarnOnBlocking = false;
            } else if (binder != null && binder.getInterfaceDescriptor() != null
                    && binder.queryLocalInterface(binder.getInterfaceDescriptor()) == null) {
                Log.w(TAG, "Unable to allow blocking on interface " + binder);
            }
        } catch (RemoteException ignored) {
        }
        return binder;
    }

这个办法比较简单,主要是设置 binder 的成员变量 mWarnOnBlocking 为 false。从姓名来看,作用是答应阻塞调用。

2.1.3 ServiceManagerNative.asInterface

    //frameworks/base/core/java/android/os/ServiceManagerNative.java
    //传入的参数是 BinderProxy
    @UnsupportedAppUsage
    static public IServiceManager asInterface(IBinder obj)
    {
        if (obj == null) {
            return null;
        }
        //回来 null
        IServiceManager in =
            (IServiceManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }
        //走这儿,构建一个 ServiceManagerProxy
        return new ServiceManagerProxy(obj);
    }
    //从姓名来看,原本要做缓存的,可是没有做
    // frameworks/base/core/java/android/os/BinderProxy.java
    public IInterface queryLocalInterface(String descriptor) {
        return null;
    }

最终是构建一个 ServiceManagerProxy 结构体。其内部持有一个 BinderProxy 。

至此,getIServiceManager 的全体流程就剖析完了。

2.2 addService

    // frameworks/base/core/java/android/os/ServiceManagerNative.java
    public void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority)
            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);
        data.writeInt(dumpPriority);
        mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
        reply.recycle();
        data.recycle();
    }

构造两个 Parcel 结构,然后调用 mRemote.transact 发起远程过程调用。

mRemote 便是 new ServiceManagerProxy 时传入的 BinderProxy:

 public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;
}

进入 frameworks/base/core/java/android/os/BinderProxy.java 检查:

public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
        //......
        try {
            //重视这儿
            return transactNative(code, data, reply, flags);
        } finally {
           //......
        }
}
//native 办法
public native boolean transactNative(int code, Parcel data, Parcel reply,int flags) throws RemoteException;

transact 会调用 transactNative 发起远程调用,transactNative 是一个 native 办法,具体完成在 frameworks/base/core/jni/android_util_Binder.cpp

// obj 对应类型为 BinderProxy
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;
    }
    // Java 目标 转为 c++ 目标
    Parcel* reply = parcelForJavaObject(env, replyObj);
    if (reply == NULL && replyObj != NULL) {
        return JNI_FALSE;
    }
    //拿到 BinderProxyNativeData 成员的 mObject,实践是一个 BpBinder
    IBinder* target = getBPNativeData(env, obj)->mObject.get();
    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);
    bool time_binder_calls;
    int64_t start_millis;
    if (kEnableBinderSample) {
        // Only log the binder call duration for things on the Java-level main thread.
        // But if we don't
        time_binder_calls = should_time_binder_calls();
        if (time_binder_calls) {
            start_millis = uptimeMillis();
        }
    }
    //BpBinder 发起远程调用
    status_t err = target->transact(code, *data, reply, flags);
    if (kEnableBinderSample) {
        if (time_binder_calls) {
            conditionally_log_binder_call(start_millis, target, code);
        }
    }
    if (err == NO_ERROR) {
        return JNI_TRUE;
    } else if (err == UNKNOWN_TRANSACTION) {
        return JNI_FALSE;
    }
    signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/, data->dataSize());
    return JNI_FALSE;
}

能够看出,绕了一圈仍是经过 native 层的 BpBinder 发起远程调用,native 层的调用过程能够参阅之前的文章Binder 服务注册过程情形剖析之 C++ 篇

关于

我叫阿豪,2015 年本科毕业于国防科技大学指挥自动化专业,毕业后,从事信息化配备的研发工作。主要研讨方向为 Android Framework 与 Linux Kernel,2023年春节后开始做 Android Framework 相关的技术分享。

如果你对 Framework 感兴趣或许正在学习 Framework,能够参阅我总结的Android Framework 学习路线指南,也可重视我的微信公众号,我会在公众号上继续分享我的经历,帮助正在学习的你少走一些弯路。学习过程中如果你有疑问或许你的经历想要分享给大家能够添加我的微信,我拉你进技术交流群。

Binder Java 层服务注册过程分析