Java层的ServiceManager和Native层的ServiceManager的对应过程

天王盖地虎626 2020-11-08 16:12:41
Android c++


转自:https://blog.csdn.net/moonshine2016/article/details/54378358

参考:https://www.jianshu.com/p/9c023701c261

 

几天前一个同事问Java层的Binder和Java层的ServiceManager和C++层的ServiceManager是如何对应起来的,竟然一时语噻,一段时间不关注就会感到陌生啊,现在再总结一下,只写Java层的,C++层的不写,C++ Binder的知识需掌握,java和native的基本概念及对应关系不讲。

Java层Binder的初始化过程
Binder最终是要和它的驱动打交道,Java层要调Linux内核层的东西必然要通过native方法,而对于android的系统服务,native和java的对应,总会有一个注册过程,先看这个注册是在哪实现的

JNI Binder的注册
Zygote在启动时:

app_main.cpp
int main(int argc, char* const argv[])
{
    ......
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    ......
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    }
    ......
}
AppRuntime是AndroidRuntime的子类,它本身没有覆盖start方法,所以要去看AndroidRuntime类中的start方法

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ......
    /*
     * Register android functions.
     */
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }
    ......
}
 
/*
 * Register android native functions with the VM.
 */
/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
{
    ......
    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }
    ......
}
gRegJNI是个数组:

static const RegJNIRec gRegJNI[] = {
    ......
    REG_JNI(register_android_os_Binder),
    ......
};
REG_JNI是一个宏定义

#ifdef NDEBUG
    #define REG_JNI(name)      { name }
    struct RegJNIRec {
        int (*mProc)(JNIEnv*);
    };
#else
    #define REG_JNI(name)      { name, #name }
    struct RegJNIRec {
        int (*mProc)(JNIEnv*);
        const char* mName;
    };
#endif
gRegJNI是一个RegJNIRec的数组,所以gRegJNI的定义就变成了这样:

static const RegJNIRec gRegJNI[] = {
    ......
    { register_android_os_Binder },
    ......
};
register_jni_procs函数如下:

static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
    for (size_t i = 0; i < count; i++) {
        if (array[i].mProc(env) < 0) {
#ifndef NDEBUG
            ALOGD("----------!!! %s failed to load\n", array[i].mName);
#endif
            return -1;
        }
    }
    return 0;
}
就是循环调用gRegJNI数组中的函数,这时register_android_os_Binder(env)就被调用了。

register_android_os_Binder在AndroidRuntime.cpp中被声明为extern:

extern int register_android_os_Binder(JNIEnv* env);
1
实现它的地方是在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)
        return -1;
    if (int_register_android_os_BinderProxy(env) < 0)
        return -1;
    ......
    return 0;
}
从名字上看,它要关联3个Java的类,分别是Binder, BinderInternal和BinderProxy,一个一个看来:

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));
}
关联了android.os.Binder类,并会用到该类的mExecTransact域和execTransact方法,将其保存到gBinderOffsets对象中,也就意味着native会将某值保存到mExecTransact中,也会回调execTransact方法。

const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal";
 
static int int_register_android_os_BinderInternal(JNIEnv* env)
{
    jclass clazz = FindClassOrDie(env, kBinderInternalPathName);
 
    gBinderInternalOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
    gBinderInternalOffsets.mForceGc = GetStaticMethodIDOrDie(env, clazz, "forceBinderGc", "()V");
 
    return RegisterMethodsOrDie(
        env, kBinderInternalPathName,
        gBinderInternalMethods, NELEM(gBinderInternalMethods));
}
关联了java的com.android.internal.os.BinderInternal类,保存了其forceBinderGc方法。

const char* const kBinderProxyPathName = "android/os/BinderProxy";
 
static int int_register_android_os_BinderProxy(JNIEnv* env)
{
    jclass clazz = FindClassOrDie(env, "java/lang/Error");
    gErrorOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
 
    clazz = FindClassOrDie(env, kBinderProxyPathName);
    gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
    gBinderProxyOffsets.mConstructor = GetMethodIDOrDie(env, clazz, "<init>", "()V");
    gBinderProxyOffsets.mSendDeathNotice = GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice",
            "(Landroid/os/IBinder$DeathRecipient;)V");
 
    gBinderProxyOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");
    gBinderProxyOffsets.mSelf = GetFieldIDOrDie(env, clazz, "mSelf",
                                                "Ljava/lang/ref/WeakReference;");
    gBinderProxyOffsets.mOrgue = GetFieldIDOrDie(env, clazz, "mOrgue", "J");
 
    clazz = FindClassOrDie(env, "java/lang/Class");
    gClassOffsets.mGetName = GetMethodIDOrDie(env, clazz, "getName", "()Ljava/lang/String;");
 
    return RegisterMethodsOrDie(
        env, kBinderProxyPathName,
        gBinderProxyMethods, NELEM(gBinderProxyMethods));
}
这个方法比较长,保存的Java的东西也比较多,值得注意的是,它还保存了BinderProxy的构造函数,也就是说它可能会主动new一个BinderProxy实例出来。

看到目前为止,native的Binder要对应到Java的3个类中,分别是android.os.Binder,com.android.internal.os.BinderInternal和android.os.BinderProxy。为了方便阅读,将它们的对应关系以类图的形式总结下:

将Java层的服务注册到ServiceManager中的过程
我们知道,native层的Binder有Bn和Bp之说,Bn应该是Binder Native的缩写,就是本地实现Binder的意思也可以说是C/S中的S,Bp是Binder Proxy的缩写,相当于C。

以PackageManagerService为例:

    public static PackageManagerService main(Context 
        ......
        PackageManagerService m = new PackageManagerService(context, installer,
                factoryTest, onlyCore);
        ......
        ServiceManager.addService("package", m);
        return m;
    }
    public static void addService(String name, IBinder service) {
        try {
            getIServiceManager().addService(name, service, false);
        } catch (RemoteException e) {
            Log.e(TAG, "error in addService", e);
        }
    }
getIServiceManager返回的是一个IServiceManager类,且是个单例,最后调用的就是

    private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }
 
        // Find the service manager
        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
        return sServiceManager;
    }
以上代码带来 三个问题,一个是BinderInternal.getContextObject(),一个是ServiceManagerNative.asInterface,另一个是addService的作用:

BinderInternal.getContextObject()的实质
ServiceManagerNative.asInterface中的参数是BinderInternal.getContextObject(),看它是native方法,对应的native代码就在刚刚看到的android_util_Binder.cpp文件中:

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
    // 是一个BpBinder
    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
    return javaObjectForIBinder(env, b);
}
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
    if (val == NULL) return NULL;
 
    if (val->checkSubclass(&gBinderOffsets)) {
        // One of our own!
        jobject object = static_cast<JavaBBinder*>(val.get())->object();
        LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
        return object;
    }
 
    // For the rest of the function we will hold this lock, to serialize
    // looking/creation/destruction of Java proxies for native Binder proxies.
    AutoMutex _l(mProxyLock);
 
    // Someone else's...  do we know about it?
    // 1
    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);
    }
 
    //2
    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.
        //3
        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));
        ......
        // Note that a new object reference has been created.
        //4
        android_atomic_inc(&gNumProxyRefs);
        incRefsCreated(env);
    }
 
    return object;
}
首先判断下和Java层关联的Native层的BpBinder是否存在,如果存在,删除。
接着创建一个Java层的BinderProxy实例。
将Native层的BpBinder指针保存到java BinderProxy实例的mObject字段中,这样通过BinderProxy的mObject字段就可以操作Native层的BpBinder了。
原子增加gNumProxyRefs和gNumRefsCreated的数量,当gNumRefsCreated的值超过200,将会调用BinderInternal的forceBinderGc方法。
总结下:

创建了一个Native层的BpBinder;
将BpBinder的指针保存到BinderProxy的mObject,而BpBinder的通信对象就是Native的ServiceManager,这为Java和Native的ServiceManager的通信埋下了伏笔。
可以将BinderProxy说成Java层的Bp端。
ServiceManagerNative.asInterface的作用
    static public IServiceManager asInterface(IBinder obj)
    {
        if (obj == null) {
            return null;
        }
        //1
        IServiceManager in =
            (IServiceManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }
 
        //2
        return new ServiceManagerProxy(obj);
    }
obj是Native实例化的BinderProxy对象,BinderProxy的代码在Binder.java中,和Binder位于同一个文件中。queryLocalInterface的返回值为null。
实例化一个ServiceManagerProxy对象,该实例中有一个IBinder类型的mRemote字段,该字段保存BinderProxy实例。
    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;
    }
总结:

ServiceManagerNative.asInterface返回的是ServiceManagerProxy的实例,该实例实现IServiceManager的接口。
ServiceManagerProxy中通过mRemote字段保存了BinderProxy,也就是Java层的Bp端。
addService的作用
有上分析,当调用ServiceManager.addService时,实际上调用的是ServiceManagerProxy类中的addService,ServiceManagerProxy类位于ServiceManagerNative.java文件中。

    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);
        //1
        mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
        reply.recycle();
        data.recycle();
    }
mRemote即为BinderProxy,它会调用transactNative,transactNative是个native方法,接着看这个方法。
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
    //1
    IBinder* target = (IBinder*)
        env->GetLongField(obj, gBinderProxyOffsets.mObject);
    if (target == NULL) {
        jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");
        return JNI_FALSE;
    }
 
    //2
    status_t err = target->transact(code, *data, reply, flags);
    ......
    return JNI_FALSE;
}
取出保存在BinderProxy中的BpBinder对象的指针
向Native层的ServiceManager发送请求
总结:

Java层调用ServiceManger.addService后,最终是向Native层的ServiceManager请求增加服务的。
Native层的ServiceManager是只有一个的,而java层的ServiceManager相对于Native的ServiceManager也只是个C端,这样,不管是通过Native add service还是通过java add service,整个Android都可以拿到这个service的Binder。
Java Service端的Bp在哪里
这时候还有个疑问,当调用ServiceManager.addService时传入的Service应该对应到Native的BnBinder啊,现在对应关系如何体现呢?这个关系要重看下addService了。

addService第二个参数的类型是IBinder,它是个接口,而它的实现类是Binder,java上层能调用addService添加服务时,所有的实例都是Binder,根据java的规则,只要实例化,其父类的相应的构造函数必被调用:

    public Binder() {
        init();
        ......
    }
init()是native方法,其实现在android_util_Binder.cpp中:

static void android_os_Binder_init(JNIEnv* env, jobject obj)
{
    JavaBBinderHolder* jbh = new JavaBBinderHolder();
    ...
    env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);
}
new一个native层的JavaBBinderHolder,并将其保存到Binder的mObject中。注意哦,虽然native层的gBinderOffsets.mObject是个static的,但java层的Binder的mObject可不是static的哦,就是说每个Binder实例都有一个Native的JavaBBinderHolder对象指针。

JavaBBinderHolder类的声明如下:

class JavaBBinderHolder : public RefBase
{
}
没有继承BBinder,还是没发现作为Bn端的踪影,需要再review下前面的流程,看下ServiceManagerProxy添加服务时发生了什么:

    public void addService(String name, IBinder service, boolean allowIsolated)
            throws RemoteException {
        Parcel data = Parcel.obtain();
        ......
        data.writeStrongBinder(service);
        ......
    }
writeStrongBinder值得怀疑

writeStrongBinder发生了什么
Parcel的这个函数如下:

    public final void writeStrongBinder(IBinder val) {
        nativeWriteStrongBinder(mNativePtr, val);
    }
nativeWriteStrongBinder的实现在android_os_Parcel.cpp中:

static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
{
    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    if (parcel != NULL) {
        const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
        if (err != NO_ERROR) {
            signalExceptionForError(env, clazz, err);
        }
    }
}
调用了一个ibinderForJavaObject函数,该函数位于android_util_Binder.cpp中

sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
    if (obj == NULL) return NULL;
 
    if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
        JavaBBinderHolder* jbh = (JavaBBinderHolder*)
            env->GetLongField(obj, gBinderOffsets.mObject);
        return jbh != NULL ? jbh->get(env, obj) : NULL;
    }
 
    if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
        return (IBinder*)
            env->GetLongField(obj, gBinderProxyOffsets.mObject);
    }
 
    ALOGW("ibinderForJavaObject: %p is not a Binder object", obj);
    return NULL;
}
传入的obj是Binder实例,所以刚刚创建的JavaBBinderHolder的get函数会被调用:

    sp<JavaBBinder> get(JNIEnv* env, jobject obj)
    {
        AutoMutex _l(mLock);
        sp<JavaBBinder> 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;
    }
返回的是JavaBBinder实例,

JavaBBinder继承了BBinder,所以最终添加到Native ServiceManager中的是这个对象,总结下它们的类图:

Java层的Binder对象拥有Native JavaBBinderHolder对象的指针,JavaBBinderHolder有JavaBBinder的对象,而JavaBBinder又有Java层Binder的对象。

版权声明
本文为[天王盖地虎626]所创,转载请带上原文链接,感谢
https://my.oschina.net/u/920274/blog/4706973

  1. 【计算机网络 12(1),尚学堂马士兵Java视频教程
  2. 【程序猿历程,史上最全的Java面试题集锦在这里
  3. 【程序猿历程(1),Javaweb视频教程百度云
  4. Notes on MySQL 45 lectures (1-7)
  5. [computer network 12 (1), Shang Xuetang Ma soldier java video tutorial
  6. The most complete collection of Java interview questions in history is here
  7. [process of program ape (1), JavaWeb video tutorial, baidu cloud
  8. Notes on MySQL 45 lectures (1-7)
  9. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  10. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  11. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  12. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  13. 【递归,Java传智播客笔记
  14. [recursion, Java intelligence podcast notes
  15. [adhere to painting for 386 days] the beginning of spring of 24 solar terms
  16. K8S系列第八篇(Service、EndPoints以及高可用kubeadm部署)
  17. K8s Series Part 8 (service, endpoints and high availability kubeadm deployment)
  18. 【重识 HTML (3),350道Java面试真题分享
  19. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  20. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  21. [re recognize HTML (3) and share 350 real Java interview questions
  22. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  23. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  24. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  25. RPC 1: how to develop RPC framework from scratch
  26. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  27. RPC 1: how to develop RPC framework from scratch
  28. 一次性捋清楚吧,对乱糟糟的,Spring事务扩展机制
  29. 一文彻底弄懂如何选择抽象类还是接口,连续四年百度Java岗必问面试题
  30. Redis常用命令
  31. 一双拖鞋引发的血案,狂神说Java系列笔记
  32. 一、mysql基础安装
  33. 一位程序员的独白:尽管我一生坎坷,Java框架面试基础
  34. Clear it all at once. For the messy, spring transaction extension mechanism
  35. A thorough understanding of how to choose abstract classes or interfaces, baidu Java post must ask interview questions for four consecutive years
  36. Redis common commands
  37. A pair of slippers triggered the murder, crazy God said java series notes
  38. 1、 MySQL basic installation
  39. Monologue of a programmer: despite my ups and downs in my life, Java framework is the foundation of interview
  40. 【大厂面试】三面三问Spring循环依赖,请一定要把这篇看完(建议收藏)
  41. 一线互联网企业中,springboot入门项目
  42. 一篇文带你入门SSM框架Spring开发,帮你快速拿Offer
  43. 【面试资料】Java全集、微服务、大数据、数据结构与算法、机器学习知识最全总结,283页pdf
  44. 【leetcode刷题】24.数组中重复的数字——Java版
  45. 【leetcode刷题】23.对称二叉树——Java版
  46. 【leetcode刷题】22.二叉树的中序遍历——Java版
  47. 【leetcode刷题】21.三数之和——Java版
  48. 【leetcode刷题】20.最长回文子串——Java版
  49. 【leetcode刷题】19.回文链表——Java版
  50. 【leetcode刷题】18.反转链表——Java版
  51. 【leetcode刷题】17.相交链表——Java&python版
  52. 【leetcode刷题】16.环形链表——Java版
  53. 【leetcode刷题】15.汉明距离——Java版
  54. 【leetcode刷题】14.找到所有数组中消失的数字——Java版
  55. 【leetcode刷题】13.比特位计数——Java版
  56. oracle控制用户权限命令
  57. 三年Java开发,继阿里,鲁班二期Java架构师
  58. Oracle必须要启动的服务
  59. 万字长文!深入剖析HashMap,Java基础笔试题大全带答案
  60. 一问Kafka就心慌?我却凭着这份,图灵学院vip课程百度云