从app bindService分析binder客户端

从 bindService() 分析 Binder 客户端

大家都知道的是 Binder 采用的是 C/S 架构思想,由 Client 端发起调用请求,由 Server 执行请求并返回结果(没有结果)。

写 App 程序进行 IPC 调用时,需要在调用端中 bindService 获取服务端的 Binder 接口对象,再调用方法。这篇文章尝试通过 bindService 方法的核心调用过程,分析Binder客户端的流程。

bindService()

我们在 Activity 中写到的 bindService(Intent service, ServiceConnection conn, BindServiceFlags flags) 调用到的是 ContextWrapper 中的方法。

// frameworks/base/core/java/android/content/ContextWrapper.java

@UnsupportedAppUsage
Context mBase;

@Override
public boolean bindService(@NonNull Intent service, @NonNull ServiceConnection conn,
        @NonNull BindServiceFlags flags) {
    return mBase.bindService(service, conn, flags);
}

ContextWrapper.bindService 调用到了 mBase.bindService(service, conn, flags),最终会调用到 ContextImpl.bindService() 方法。

@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
    warnIfCallingFromSystemProcess();
    return bindServiceCommon(service, conn, Integer.toUnsignedLong(flags), null,
            mMainThread.getHandler(), null, getUser());
}

private boolean bindServiceCommon(Intent service, ServiceConnection conn, long flags,
        String instanceName, Handler handler, Executor executor, UserHandle user) {

    IServiceConnection sd;
    // ......
    try {
        IBinder token = getActivityToken();
        // ......
        service.prepareToLeaveProcess(this);  // 同一进程内,内部的比较 leavingPackage=false
        // 下面是执行的 bindService 过程中的一个关键方法调用
        int res = ActivityManager.getService().bindServiceInstance(
                mMainThread.getApplicationThread(), getActivityToken(), service,
                service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, instanceName, getOpPackageName(), user.getIdentifier());
        // ......
        return res != 0;
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

获取 AMS binder对象

主要关注主要流程的实现,因此移除一些代码,全部的代码放开很占篇幅。很多更深层源码的理解,涉及到更深的知识,也有超出我理解的范围的地方,请不吝赐教。

bindServiceCommon() 方法中,主要流程调用到了

int res = ActivityManager.getService().bindServiceInstance(
                mMainThread.getApplicationThread(), getActivityToken(), service,
                service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, instanceName, getOpPackageName(), user.getIdentifier());

这条语句中,先通过 ActivityManager.getService() 获取到 ActivityManagerServiceBinder 对象。

// frameworks/base/core/java/android/app/ActivityManager.java

@UnsupportedAppUsage
public static IActivityManager getService() {
    return IActivityManagerSingleton.get();
}

// 定义 singleton 对象。
@UnsupportedAppUsage
private static final Singleton<IActivityManager> IActivityManagerSingleton =
        new Singleton<IActivityManager>() {
            @Override
            protected IActivityManager create() {
                // 从  ServiceManager 中获取 AMS 的 binder 对象
                final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                final IActivityManager am = IActivityManager.Stub.asInterface(b);
                return am;
            }
        };

基于当前分析的流程,getService(String name) 的参数值是 Context.ACTIVITY_SERVICE

// frameworks/base/core/java/android/os/ServiceManager.java

@UnsupportedAppUsage
private static IServiceManager sServiceManager;

// IServiceManager 这是接口类型,对应的是 IServiceManager.aidl 文件编译后得到的java类型。
@UnsupportedAppUsage
private static IServiceManager getIServiceManager() {
    if (sServiceManager != null) {
        return sServiceManager;
    }

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

// 执行的逻辑比较简单,在缓存列表中查找 name 对应的 Binder 对象,
@UnsupportedAppUsage
public static IBinder getService(String name) { // 此时这里的值是 Context.ACTIVITY_SERVICE
    try {
        IBinder service = sCache.get(name);
        if (service != null) {
            return service;
        } else {
            return Binder.allowBlocking(rawGetService(name));  // 这是获取 Binder 对象的关键。
        }
    } catch (RemoteException e) {
        Log.e(TAG, "error in getService", e);
    }
    return null;
}

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

    final IBinder binder = getIServiceManager().getService(name);

    final int time = (int) sStatLogger.logDurationStat(Stats.GET_SERVICE, start);

    final int myUid = Process.myUid();
    final boolean isCore = UserHandle.isCore(myUid);

    // ......  后续的代码中,并没有对 binder 对象作出关键的修改。
    return binder;
}

getService() 调用到 Binder.allowBloking()

// frameworks/base/core/java/android/os/Binder.java

// 方法的返回还是传入的 binder
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;
}

allowBlocking 方法中,没有处理具体的修改,针对传入的 binder 也没有作出影响执行流程的修改。因此,回到 ServiceManager.getService() 方法中,关键的执行流程在 rawGetService(name) 方法中。

ServiceManager.rawGetService(String name) 方法中,关键在

final IBinder binder = getIServiceManager().getService(name); // 这个 binder 对象值最终方法返回的对象。

getIServiceManager() 返回的是 IServiceManager 类型,对应的是 IServiceManager.aidl 文件编译后得到的java接口类型。在它的实现中,调用 ServiceManagerNative.asInterface() 方法。

// frameworks/base/core/java/android/os/ServiceManagerNative.java

public final class ServiceManagerNative {
    private ServiceManagerNative() {
    }

    // 参数 obj 将是获取到的服务端的 Binder 对象,整个设计是 代理模式 。
    @UnsupportedAppUsage
    public static IServiceManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }

        // ServiceManager is never local
        return new ServiceManagerProxy(obj);
    }
} 

ServiceManagerNative 的方法中返回的是带有 Binder 对象的 ServiceManagerProxy 代理类。

紧接着:要知道 ServiceManagerNative.asInterface(IBinder) 是从怎么获取到的?

从方法调用上,返回到 ServiceManager.getIServiceManager() 方法中,之前分析到 Binder.allowBlocking(IBinder) 方法内并没有对参数作出关键的修改,因此 Binder 需要从BinderInternal.getContextObject() 的调用中获取。

// frameworks/base/core/java/com/android/internal/os/BinderInternal.java

@UnsupportedAppUsage
public static final native IBinder getContextObject();

从上面这个方法定义可知,这是一个 JNI 调用,需要知道 getContextObject() 方法对应的 C/C++ 层的具体实现函数。

要在 Android 系统中找 JNI 接口定义的注册位置, jni 接口是属于java虚拟机的一部分,因此大概的位置应该要在 VM 相关的代码中查找,就查找到 AndroidRuntime.cpp 看看是不是会有与 Binder 注册有关的函数。

static const RegJNIRec gRegJNI[] = {
     // ....
}

可以看到这个数组的声明,在这里可以看到很多 register_* 的函数注册,可以搜索到 register_android_os_Binder 的注册,进而查找到文件 android_util_Binder.cpp 文件,对应的 register_android_os_Binder 函数定义也有。

另一个查找方式就是全局搜索文件内容 getContextObject,再过滤信息找到 JNI 定义位置。

在查找到 Binder 相关注册函数在文件 android_util_Binder.cpp 文件。

// frameworks/base/core/jni/android_util_Binder.cpp

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)  // 看到 BinderInternal 类的注册函数
        return -1;
    if (int_register_android_os_BinderProxy(env) < 0)
        return -1;
     // ......

    return 0;
}


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

static int int_register_android_os_BinderProxy(JNIEnv* env)
{
    // ...... 加载 Java 层的异常类。
    // JNI调用,找到 Java 层类 android.os.BinderProxy,得到 jclass 对象。
    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.mNativeData = GetFieldIDOrDie(env, clazz, "mNativeData", "J");

    clazz = FindClassOrDie(env, "java/lang/Class");
    gClassOffsets.mGetName = GetMethodIDOrDie(env, clazz, "getName", "()Ljava/lang/String;");

    return RegisterMethodsOrDie(
        env, kBinderProxyPathName,
        gBinderProxyMethods, NELEM(gBinderProxyMethods));
}

static const JNINativeMethod gBinderInternalMethods[] = { // BinderInternal 方法对应关系
     /* name, signature, funcPtr */
    { "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },
    // ...... 其他要注册的函数
};

// BidnerInternal java类的包限定名的目录形式
const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal";

static int int_register_android_os_BinderInternal(JNIEnv* env)
{
    jclass clazz = FindClassOrDie(env, kBinderInternalPathName); // 找到java类

    // ......
    BpBinder::setLimitCallback(android_os_BinderInternal_proxyLimitcallback);

    return RegisterMethodsOrDie(
        env, kBinderInternalPathName,
        gBinderInternalMethods, NELEM(gBinderInternalMethods));
}

在函数 int_register_android_os_BinderInternal() 中进行了函数的注册,在函数数组 gBinderInternalMethods[] 的第一个看到了要查找的目标 getContextObject ,对应的函数是 android_os_BinderInternal_getContextObject (实现在 android_util.Binder.cpp 文件)。

// frameworks/base/core/jni/android_util_Binder.cpp

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

ProcessState 是每一个进程创建起都有的进程对象。

// frameworks/native/libs/binder/ProcessState.cpp

sp ProcessState::getContextObject(const sp& /*caller*/)
{
    // 获取 IBinder 对象并返回。
    sp context = getStrongProxyForHandle(0); // 参数 0 是 servicemanager 进程id

    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());
    } else {
        ALOGW("Not able to get context object on %s.", mDriverName.c_str());
    }

    return context;
}

sp ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp result;
    std::unique_lock _l(mLock);
    if (handle == 0 && the_context_object != nullptr) return the_context_object;
    // 在数组Vector在中查找 handle_entry,若刚开始数组大小是 0,系统会创建一个 handle_entry,放入到数组中。
    handle_entry* e = lookupHandleLocked(handle); 
    if (e != nullptr) {
        IBinder* b = e->binder;  // 在数组是大小是0的情况下,这里的 binder=nullptr。
        if (b == nullptr || !e->refs->attemptIncWeak(this)) {
            if (handle == 0) {  // 本篇幅中,这个 handle 传入的就是 0。
                IPCThreadState* ipc = IPCThreadState::self();
                CallRestriction originalCallRestriction = ipc->getCallRestriction();
                ipc->setCallRestriction(CallRestriction::NONE);
                Parcel data;
                status_t status = ipc->transact(
                        0, IBinder::PING_TRANSACTION, data, nullptr, 0);
                ipc->setCallRestriction(originalCallRestriction);
                if (status == DEAD_OBJECT)
                   return nullptr;
            }
			// 创建 BpBinder 对象。
            sp b = BpBinder::PrivateAccessor::create(handle);
            e->binder = b.get();
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }

    return result;
}

这里获取到了 C/C++ 层的 IBinder(实际是 BpBinder) 对象。

Binder 客户端 获取 Binder 对象执行到这里获取到 IBinder 对象。我们再往回逐步查看ProcessState::getContextObject() -> android_util_Binder::android_os_BinderInternal_getContextObject() 。 在 C/C++层获取到 IBinder 对象之后,调用了 javaObjectForIBinder() 函数。

// frameworks/base/core/jni/android_util_Binder.cpp

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

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

    BinderProxyNativeData* nativeData = new BinderProxyNativeData();
    nativeData->mOrgue = new DeathRecipientList;
    nativeData->mObject = val;

    // 通过JNI调用 android.os.BinderProxy::getInstance() 方法,创建Java层 BinderProxy 对象。
    jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
            gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get());
    if (env->ExceptionCheck()) {
        return NULL;
    }
    BinderProxyNativeData* actualNativeData = getBPNativeData(env, object);
    if (actualNativeData != nativeData) {
        delete nativeData;
    }

    return object;
}

这个函数的作用即是将 C/C++ 层的 BpBinder 对象的数据转换成 Java 层 BinderProxy 对象数据。

执行完这个函数后,就会将 android.os.BinderProxy 对象作为 Java 层 getContextObject() 的返回值返回。这样ServiceManager::getIServiceManager() 执行完成,返回到 ServiceManager::rawGetService() 方法。

private static IBinder rawGetService(String name) throws RemoteException {
    final long start = sStatLogger.getTime();
    // 上述一切的重点在于 getIServiceManager() 任何获取 Client 端的 BinderProxy(BpBidner)。
    // 它返回的就是 ServiceManagerProxy,其中封装有 BinderProxy 对象。
    final IBinder binder = getIServiceManager().getService(name);

    // ......
    return binder;
}

在这里将 binder 返回,再返回到 ActivityManager.getService() 的最初位置,接着调用 bindServiceInstance() 方法。

// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

final ActiveServices mServices;

public int bindServiceInstance(IApplicationThread caller, IBinder token, Intent service,
        String resolvedType, IServiceConnection connection, long flags, String instanceName,
        String callingPackage, int userId) throws TransactionTooLargeException {
    return bindServiceInstance(caller, token, service, resolvedType, connection, flags,
            instanceName, false, INVALID_UID, null, null, callingPackage, userId);
}

private int bindServiceInstance(IApplicationThread caller, IBinder token, Intent service,
        String resolvedType, IServiceConnection connection, long flags, String instanceName,
        boolean isSdkSandboxService, int sdkSandboxClientAppUid,
        String sdkSandboxClientAppPackage,
        IApplicationThread sdkSandboxClientApplicationThread,
        String callingPackage, int userId)
        throws TransactionTooLargeException {
    // ......

    try {
        // ......
        synchronized (this) {
            return mServices.bindServiceLocked(caller, token, service, resolvedType, connection,
                    flags, instanceName, isSdkSandboxService, sdkSandboxClientAppUid,
                    sdkSandboxClientAppPackage, sdkSandboxClientApplicationThread,
                    callingPackage, userId);
        }
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    }
}

这样来完成从 Client 端获取到 Server 端的 Binder 代理,从而调用到 Server 端的方法。

后续会上一张图

你可能感兴趣的:(Android,Binder机制,binder,Android)