(O)ServiceManager分析(一)之BinderInternal.getContextObject

本文详细探讨了Android中Binder机制的内部实现,从JNI函数注册开始,逐步剖析BinderInternal的getContextObject函数。通过分析,揭示了Binder、BinderInternal和BinderProxy在C++和Java层之间的交互过程,特别是如何创建并返回BinderProxy对象的过程。

1. Binder, JNI函数的注册

在分析BinderInternal的getContextObject函数之前,我们有必要先看一下Binder中JNI函数的注册情况

android_os_Binder.cpp

int register_android_os_Binder(JNIEnv* env)
{
	// Leo, 注册Binder的相关JNI函数
    if (int_register_android_os_Binder(env) < 0)
        return -1;
    // Leo, 注册Binderinternal的相关JNI函数
    if (int_register_android_os_BinderInternal(env) < 0)
        return -1;
    // Leo, 注册BinderProxy的相关JNI函数
    if (int_register_android_os_BinderProxy(env) < 0)
        return -1;

    jclass clazz = FindClassOrDie(env, "android/util/Log");
    gLogOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
    gLogOffsets.mLogE = GetStaticMethodIDOrDie(env, clazz, "e",
            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I");

    clazz = FindClassOrDie(env, "android/os/ParcelFileDescriptor");
    gParcelFileDescriptorOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
    gParcelFileDescriptorOffsets.mConstructor = GetMethodIDOrDie(env, clazz, "<init>",
                                                                 "(Ljava/io/FileDescriptor;)V");

    clazz = FindClassOrDie(env, "android/os/StrictMode");
    gStrictModeCallbackOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
    gStrictModeCallbackOffsets.mCallback = GetStaticMethodIDOrDie(env, clazz,
            "onBinderStrictModePolicyChange", "(I)V");

    return 0;
}
至于为什么会开始走到这个方法,我们在此不讨论

这个方法,主要是,调用了各个register方法,注册了一些JNI函数,那么具体怎么注册的,我们进入方法中查看,先看int_register_android_os_Binder

static const JNINativeMethod gBinderMethods[] = {
     /* name, signature, funcPtr */
    { "getCallingPid", "()I", (void*)android_os_Binder_getCallingPid },
    { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid },
    { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity },
    { "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity },
    { "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy },
    { "getThreadStrictModePolicy", "()I", (void*)android_os_Binder_getThreadStrictModePolicy },
    { "flushPendingCommands", "()V", (void*)android_os_Binder_flushPendingCommands },
    { "init", "()V", (void*)android_os_Binder_init },
    { "destroy", "()V", (void*)android_os_Binder_destroy },
    { "blockUntilThreadAvailable", "()V", (void*)android_os_Binder_blockUntilThreadAvailable }
};

const char* const kBinderPathName = "android/os/Binder";

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));
}
static struct bindernative_offsets_t
{
    // Class state.
    jclass mClass;
    jmethodID mExecTransact;

    // Object state.
    jfieldID mObject;

} gBinderOffsets;
那么,从这个方法,我们可以看到,将gBinderOffsets和Java世界android.os.Binder类,进行关联,并且指定

gBinderOffsets.mClass为android.os.Binder类

gBinderOffsets.mExecTransact为android.os.Binder.execTransact方法

gBinderOffsets.mObject对应为android.os.Binder的mObject对象所对应的值

并且,将gBinderMethods中所对应的Java世界的方法和C世界的相对应的方法一一对应

那么上述的其他两个方法,所达到的目的也是和上述方法一致,我们可以得出如下的其他结论

<think>我们正在分析Android系统中的`getIServiceManager()`方法。该方法用于获取`IServiceManager`接口的实例,该接口是Android服务管理器的核心接口,负责服务的注册(addService)和查询(getService)等操作。由于服务管理器本身也是个Binder服务,因此获取其代理对象的过程涉及Binder IPC机制。 根据引用[1]和引用[3]的上下文,我们可以推断`getIServiceManager()`的实现通常位于`ServiceManager`类中(可能在不同的包路径下,例如`android/os/ServiceManager`或`com/android/internal/os/ServiceManager`等)。下面我们将分析其典型实现并添加注释。 ### 函数实现分析:`getIServiceManager()` 在Android源代码中,`getIServiceManager()`通常是个静态方法,内部使用单例模式缓存`IServiceManager`代理对象。以下是个典型的实现(基于Android源码): ```java // 文件路径:frameworks/base/core/java/android/os/ServiceManager.java private static IServiceManager sServiceManager; public static IServiceManager getIServiceManager() { if (sServiceManager != null) { return sServiceManager; } // 通过Binder接口获取ServiceManager的代理对象 sServiceManager = ServiceManagerNative.asInterface(Binder.allowBlocking(BinderInternal.getContextObject())); return sServiceManager; } ``` #### 代码注释说明 ```java /** * 获取系统服务管理器(ServiceManager)的代理对象。 * 该对象是个单例,用于后续的服务注册(addService)和查询(getService)等操作。 * * 实现步骤: * 1. 检查静态变量sServiceManager是否已初始化,若已初始化则直接返回。 * 2. 若未初始化,则通过Binder机制获取ServiceManager的Binder代理对象。 * - 先通过BinderInternal.getContextObject()获取原始的Binder代理对象(即指向ServiceManager的Binder引用)。 * - 使用Binder.allowBlocking()允许该Binder调用在同步传输时阻塞线程(Android 8.0以上引入)。 * - 再通过ServiceManagerNative.asInterface()将原始Binder对象转换为IServiceManager接口的代理对象。 * 3. 将代理对象缓存到静态变量sServiceManager中并返回。 * * 注意:该方法内部使用单例模式,确保整个进程内只有ServiceManager代理实例。 * * @return IServiceManager接口的代理对象,用于与服务管理器进行IPC通信。 */ public static IServiceManager getIServiceManager() { // 单例检查:如果已经初始化,直接返回缓存的对象 if (sServiceManager != null) { return sServiceManager; } // 获取ServiceManager的Binder代理对象: // 1. BinderInternal.getContextObject():获取个指向ServiceManager的Binder代理对象的原始引用。 // 在native层,这个函数返回的是BpBinder对象(代理对象),其handle值为0(因为ServiceManager是特殊的Binder服务,handle为0)。 // 2. Binder.allowBlocking():允许该Binder进行阻塞调用(在异步调用中不需要,但同步调用需要)。 // 3. ServiceManagerNative.asInterface():将原始的Binder对象(BpBinder)包装成IServiceManager.Stub.Proxy代理对象。 sServiceManager = ServiceManagerNative.asInterface( Binder.allowBlocking(BinderInternal.getContextObject())); return sServiceManager; } ``` ### 关键点解析 1. **`BinderInternal.getContextObject()`**: - 这是个native方法,返回个指向ServiceManager的Binder代理对象(即`BpBinder`)。在Binder机制中,ServiceManager的handle值固定为0,因此这个调用返回的是handle=0的`BpBinder`对象[^1][^3]。 2. **`Binder.allowBlocking()`**: - 在Android 8.0(API 26)及以上版本中,Binder调用默认不允许阻塞主线程。此方法用于标记该Binder对象允许进行可能阻塞的同步调用。由于服务管理器的调用通常发生在系统启动阶段(非主线程)或后台线程,因此允许阻塞[^3]。 3. **`ServiceManagerNative.asInterface()`**: - 该方法将原始的`IBinder`对象(即`BpBinder`)转换为`IServiceManager`接口的代理对象(`IServiceManager.Stub.Proxy`)。转换逻辑如下: - 如果传入的`IBinder`对象是本地服务(即位于同进程),则尝试转换为`IServiceManager.Stub`(本地服务实现)。 - 否则,创建并返回个`IServiceManager.Stub.Proxy`代理对象,该对象负责将方法调用打包成Parcel并通过Binder发送。 - 由于ServiceManager运行在单独进程(`servicemanager`),因此这里总是返回代理对象(Proxy)[^1][^3]。 ### 底层Binder通信流程 引用[1]中描述了服务注册的完整流程,其中第步就是获取ServiceManager代理: > service 作为servicemanager 的client 端,需要通过defaultServiceManager 获取servicemanager 的代理[^1]。 `getIServiceManager()`即实现了这功能。后续的`addService()`调用(如用户之前的问题)会通过这个代理对象发起IPC调用,具体流程如下: 1. 客户端(服务提供者进程)调用`IServiceManager.addService()`(实际是`IServiceManager.Stub.Proxy.addService()`)。 2. 代理对象将方法名、参数(服务名、Binder对象等)打包成Parcel。 3. 通过`BpBinder.transact()`发送`ADD_SERVICE_TRANSACTION`请求。 4. 请求通过Binder驱动转发到ServiceManager进程。 5. ServiceManager进程中的`BnServiceManager.onTransact()`处理请求,调用真正的`addService()`方法将服务注册到内部哈希表[^1][^3]。 ### 总结 `getIServiceManager()`是Android服务管理机制中的关键入口,它提供了与系统服务管理器通信的代理对象。其实现依赖于Binder IPC机制,通过handle=0的特殊Binder代理连接到ServiceManager进程。该方法的单例设计确保了进程内仅有个代理实例,提高了效率。 §§相关问题§§ 1. `BinderInternal.getContextObject()` 的底层实现原理是什么? 2. 为什么ServiceManager的Binder句柄(handle)是0? 3. `IServiceManager.Stub.Proxy` 类是如何封装Binder调用的? 4. 在Android高版本中,服务管理器的架构有哪些变化?</think>### Android中`getIServiceManager()`方法实现分析 `getIServiceManager()`是Android服务管理系统的核心入口方法,用于获取系统服务管理器(ServiceManager)的代理对象。以下是其典型实现代码及详细注释: ```java // 文件路径:frameworks/base/core/java/android/os/ServiceManager.java private static IServiceManager sServiceManager; public static IServiceManager getIServiceManager() { if (sServiceManager != null) { return sServiceManager; } // 获取ServiceManager的Binder代理对象 sServiceManager = ServiceManagerNative.asInterface( Binder.allowBlocking(BinderInternal.getContextObject())); return sServiceManager; } ``` #### 代码注释说明: ```java /** * 获取系统服务管理器(ServiceManager)的代理对象。 * 该对象采用单例模式缓存,确保进程内唯访问点。 * * 实现流程: * 1. 检查静态变量sServiceManager是否已初始化(单例模式) * 2. 通过Binder机制获取ServiceManager的原始Binder引用 * 3. 将原始Binder对象转换为IServiceManager接口代理 * * @return IServiceManager接口的代理对象,用于服务注册/查询 */ public static IServiceManager getIServiceManager() { // 单例检查:避免重复创建代理对象 if (sServiceManager != null) { return sServiceManager; } // 核心步骤: // a) BinderInternal.getContextObject(): // 获取指向ServiceManager的Binder代理对象(handle=0的特殊Binder) // b) Binder.allowBlocking(): // 允许该Binder进行阻塞调用(Android 8.0+的安全机制) // c) ServiceManagerNative.asInterface(): // 将原始Binder包装成IServiceManager.Stub.Proxy代理对象 sServiceManager = ServiceManagerNative.asInterface( Binder.allowBlocking(BinderInternal.getContextObject())); return sServiceManager; } ``` ### 关键组件解析 1. **`BinderInternal.getContextObject()`** - 本地方法(JNI实现),返回指向ServiceManager的`IBinder`对象 - 对应Native层:`android_os_BinderInternal_getContextObject()`[^1] - 始终返回handle=0的`BpBinder`(ServiceManager是特权Binder服务) 2. **`Binder.allowBlocking()`** - Android 8.0(Oreo)引入的同步调用安全机制 - 解除Binder调用的非阻塞限制(系统服务需要同步IPC) 3. **`ServiceManagerNative.asInterface()`** - 核心转换方法,创建类型安全的接口代理: ```java public static IServiceManager asInterface(IBinder obj) { if (obj == null) return null; // 检查是否为本地对象(通常不是) if (obj instanceof IServiceManager) { return (IServiceManager) obj; } // 创建代理对象处理跨进程调用 return new ServiceManagerProxy(obj); } ``` ### 底层通信流程 1. **Binder驱动交互** - 通过`BpBinder.transact()`发送`GET_SERVICE_TRANSACTION`请求 - 使用`Parcel`封装服务名称和参数[^1] 2. **ServiceManager响应** - 接收`BR_TRANSACTION`指令并解析请求 - 在服务注册表`mNameToService`中查询对应Binder引用[^3] 3. **代理对象创建** - 将返回的Binder句柄封装为类型安全的Java代理 - 生成动态代理处理接口方法调用 ### 架构演进说明 - **Android 8.0前**:直接通过`ServiceManagerNative`获取静态实例 - **Android 8.0+**:引入`Binder.allowBlocking()`增强同步调用安全性 - **Android 10+**:服务管理器改造为AIDL实现(更规范的接口定义)[^3] > 该方法作为系统服务访问的起点,在Android启动阶段被`SystemServer`频繁调用,用于注册AMS/PMS等核心服务[^1]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值