ServiceManager的一次获取服务调用之一

18 阅读2分钟

ServiceManager 是怎么获取的

1. Java 入口

ServiceManager.getService(name) 先查本进程缓存,没命中就走 rawGetService(name)

//ServiceManager.java

public static IBinder getService(String name) {
    try {
        IBinder service = sCache.get(name);
        if (service != null) {
            return service;
        } else {
            return Binder.allowBlocking(rawGetService(name));
        }

rawGetService 实际调的是:

//ServiceManager.java

private static IBinder rawGetService(String name) throws RemoteException {
    final long start = sStatLogger.getTime();

    final IBinder binder =
            getIServiceManager().getService2(name).getServiceWithMetadata().service;

2. getIServiceManager() 怎么拿到 servicemanager

第一次会调用:

//ServiceManager.java

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

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

关键是 BinderInternal.getContextObject()。它进 JNI 后:

// android_util_binder.cpp

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

Native 里 getContextObject() 固定拿 handle 0

// ProcessState.cpp

sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
    sp<IBinder> context = getStrongProxyForHandle(0);

    if (context) {
        // The root object is special since we get it directly from the driver, it is never
        // written by Parcell::writeStrongBinder.
        internal::Stability::markCompilationUnit(context.get());
    }

handle 0 是 Binder 驱动约定的 context manager,也就是 servicemanager。

3. BpBinder 在哪里出现

getStrongProxyForHandle(0) 如果本进程还没有 handle 0 的代理,就创建一个 BpBinder

// ProcessState.cpp

Parcel data;
status_t status = ipc->transact(
        0, IBinder::PING_TRANSACTION, data, nullptr, 0);

// ...

sp<BpBinder> b = BpBinder::PrivateAccessor::create(handle, &postTask);

你当前看到的这行就是创建远端 Binder 代理:

// ProcessState.cpp

return sp<BpBinder>::make(BinderHandle{handle}, trackedUid);

所以 client 进程里拿到的 servicemanager 不是 servicemanager 对象本体,而是:

Java BinderProxy -> native BinderProxyNativeData.mObject -> sp<BpBinder(handle=0)>

JNI 包装点在这里:

    
   //android_util_Binder.cpp
  
   return javaObjectForIBinder(env, b);
   //...
   
   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();
        LOG_DEATH_FREEZE("objectForBinder %p: it's our own %p!\n", val.get(), object);
        return object;
    }

    BinderProxyNativeData* nativeData = new BinderProxyNativeData();
    nativeData->mOrgue = sp<DeathRecipientList>::make();
    nativeData->mFrozenStateChangeCallbackList = sp<FrozenStateChangeCallbackList>::make();
    nativeData->mObject = val;

    jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
            gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get());

我们再看看这个gBinderProxyOffsets,具体是个什么,这个得到了一个什么样的java对象,谜底就快解开了


//android_util_Binder.cpp

static struct binderproxy_offsets_t
{
    // Class state.
    jclass mClass;
    jmethodID mGetInstance;
    jmethodID mSendDeathNotice;
    jmethodID mInvokeFrozenStateChangeCallback;

    // Object state.
    jfieldID mNativeData;  // Field holds native pointer to BinderProxyNativeData.
} gBinderProxyOffsets;


const char* const kBinderProxyPathName = "android/os/BinderProxy";

static int int_register_android_os_BinderProxy(JNIEnv* env)
{
    jclass clazz = FindClassOrDie(env, kBinderProxyPathName);
    gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
    gBinderProxyOffsets.mGetInstance = GetStaticMethodIDOrDie(env, clazz, "getInstance",
            "(JJ)Landroid/os/BinderProxy;");
    gBinderProxyOffsets.mSendDeathNotice =
            GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice",
                                   "(Landroid/os/IBinder$DeathRecipient;Landroid/os/IBinder;)V");
    gBinderProxyOffsets.mInvokeFrozenStateChangeCallback =
            GetStaticMethodIDOrDie(env, clazz, "invokeFrozenStateChangeCallback",
                                   "(Landroid/os/IBinder$FrozenStateChangeCallback;Landroid/os/"
                                   "IBinder;I)V");
    gBinderProxyOffsets.mNativeData = GetFieldIDOrDie(env, clazz, "mNativeData", "J");
}


原来这个gBinderProxyOffsets 中保存的就是Java 中BinderProxy

image.png

4. Client 怎么“连到” servicemanager

Client 打开 /dev/binder,然后向 handle 0 发 transaction。

BpBinder::transact()

// BpBinder.cpp

status_t BpBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    // ...

    status = IPCThreadState::self()->transact(binderHandle(), code, data, reply, flags);

IPCThreadState::transact() 把目标 handle、code、Parcel 写成 BC_TRANSACTION

// IPCThreadState.cpp

status_t IPCThreadState::transact(int32_t handle,
                                  uint32_t code, const Parcel& data,
                                  Parcel* reply, uint32_t flags)
{
    // ...

    err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, nullptr);
    
                            ...
    

真正进驱动是这里:


#if defined(BINDER_WITH_KERNEL_IPC)
        if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
            err = NO_ERROR;
        else
            err = -errno;

驱动看到 target handle 是 0,就把请求投递给注册为 context manager 的 servicemanager 进程。

下篇文章我们再看看 servicemanager 是如何接收数据并返回的。