The corresponding process of servicemanager in Java layer and servicemanager in native layer

Tianwang gaidihu 626 2020-11-08 16:12:41
corresponding process servicemanager java layer


from :https://blog.csdn.net/moonshine2016/article/details/54378358

Reference resources :https://www.jianshu.com/p/9c023701c261

 

A colleague asked me a few days ago Java Layer of Binder and Java Layer of ServiceManager and C++ Layer of ServiceManager How does it correspond to , It's just that I said , If you don't pay attention for a period of time, you will feel strange , Now to sum up , Just write Java Layer of ,C++ The layer does not write ,C++ Binder We need to master the knowledge of ,java and native The basic concepts and corresponding relations of the two are not mentioned .

Java layer Binder The initialization process
Binder The final thing is to deal with its drivers ,Java The layer should be adjusted Linux Things in the kernel layer have to go through native Method , And for android System services ,native and java Corresponding , There's always a registration process , Let's see where the registration is implemented

JNI Binder Registration of
Zygote When it starts :

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 yes AndroidRuntime Subclasses of , It doesn't cover itself start Method , So I'm going to see AndroidRuntime Class start Method

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 Is an array :

static const RegJNIRec gRegJNI[] = {
    ......
    REG_JNI(register_android_os_Binder),
    ......
};
REG_JNI Is a macro definition

#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 It's a RegJNIRec Array of , therefore gRegJNI That's how it's defined :

static const RegJNIRec gRegJNI[] = {
    ......
    { register_android_os_Binder },
    ......
};
register_jni_procs Function as follows :

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;
}
It's a loop call gRegJNI Functions in arrays , At this time register_android_os_Binder(env) It's called .

register_android_os_Binder stay AndroidRuntime.cpp Is declared as extern:

extern int register_android_os_Binder(JNIEnv* env);
1
The place to achieve it is in android_util_Binder.cpp in :

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;
}
From the name , It has to be connected to 3 individual Java Class , Namely Binder, BinderInternal and BinderProxy, One by one, it seems :

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));
}
Associated with the android.os.Binder class , And will use this class of mExecTransact Domain and execTransact Method , Save it to gBinderOffsets In the object , That means native Will save a value to mExecTransact in , Will the callback execTransact Method .

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));
}
Associated with the java Of com.android.internal.os.BinderInternal class , Saved it forceBinderGc Method .

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));
}
This method is longer , The saved Java There are also more things , It is worth noting that , It also preserved BinderProxy Constructor for , In other words, it may take the initiative to new One BinderProxy Examples come out .

See, so far ,native Of Binder To correspond to Java Of 3 Of the classes , Namely android.os.Binder,com.android.internal.os.BinderInternal and android.os.BinderProxy. For ease of reading , Summarize their corresponding relationship in the form of class diagram :

take Java Layer services are registered with ServiceManager The process in
We know ,native Layer of Binder Yes Bn and Bp The said ,Bn Should be Binder Native Abbreviation , It's local implementation Binder It can also be said that C/S Medium S,Bp yes Binder Proxy Abbreviation , amount to C.

With PackageManagerService For example :

    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 Back to a IServiceManager class , And it's a single example , The last thing to call is

    private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }
 
        // Find the service manager
        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
        return sServiceManager;
    }
The above code brings Three questions , One is BinderInternal.getContextObject(), One is ServiceManagerNative.asInterface, The other is addService The role of :

BinderInternal.getContextObject() The essence of
ServiceManagerNative.asInterface The parameter in is BinderInternal.getContextObject(), Look, it's native Method , Corresponding native The code is just in sight android_util_Binder.cpp In file :

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
    // It's a 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;
}
First judge and Java Layer related Native Layer of BpBinder Whether there is , If there is , Delete .
Then create a Java Layer of BinderProxy example .
take Native Layer of BpBinder The pointer is saved to java BinderProxy Example of mObject Field , This way BinderProxy Of mObject Fields can be operated on Native Layer of BpBinder 了 .
Atoms increase gNumProxyRefs and gNumRefsCreated The number of , When gNumRefsCreated The value of exceeds 200, Will call BinderInternal Of forceBinderGc Method .
Sum up :

Created a Native Layer of BpBinder;
take BpBinder Save the pointer to BinderProxy Of mObject, and BpBinder The object of communication is Native Of ServiceManager, This is Java and Native Of ServiceManager It's a foreshadowing for our communications .
Can be BinderProxy succeed in negotiation Java Layer of Bp End .
ServiceManagerNative.asInterface The role of
    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 yes Native Instantiated BinderProxy object ,BinderProxy Code in Binder.java in , and Binder In the same file .queryLocalInterface The return value of is null.
Instantiate a ServiceManagerProxy object , There is one in this example IBinder Type of mRemote Field , This field holds BinderProxy example .
    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;
    }
summary :

ServiceManagerNative.asInterface The return is ServiceManagerProxy Example , This instance implements IServiceManager The interface of .
ServiceManagerProxy Pass through mRemote The fields are saved BinderProxy, That is to say Java Layer of Bp End .
addService The role of
There is an analysis , When calling ServiceManager.addService when , It's actually calling theta ServiceManagerProxy Class addService,ServiceManagerProxy Class is located ServiceManagerNative.java In file .

    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 That is to say BinderProxy, It will be called transactNative,transactNative It's a native Method , Then look at this method .
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;
}
Take it out and store it in BinderProxy Medium BpBinder Object pointer
towards Native Layer of ServiceManager Send a request
summary :

Java Layer calls ServiceManger.addService after , In the end, it's to Native Layer of ServiceManager Asking for additional services .
Native Layer of ServiceManager There is only one , and java Layer of ServiceManager be relative to Native Of ServiceManager It's just C End , such , Whether it's through Native add service Or through java add service, Whole Android You can get this service Of Binder.
Java Service Terminal Bp Where is the
And then there's a question , When calling ServiceManager.addService When it came in Service It should correspond to Native Of BnBinder ah , Now how to reflect the corresponding relationship ? This relationship needs to be reconsidered addService 了 .

addService The second parameter is of type IBinder, It's an interface , Its implementation class is Binder,java The upper layer can call addService When adding services , All the examples are Binder, according to java The rules of , Just instantiate , The corresponding constructor of its parent class must be called :

    public Binder() {
        init();
        ......
    }
init() yes native Method , In fact, now android_util_Binder.cpp in :

static void android_os_Binder_init(JNIEnv* env, jobject obj)
{
    JavaBBinderHolder* jbh = new JavaBBinderHolder();
    ...
    env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);
}
new One native Layer of JavaBBinderHolder, And save it to Binder Of mObject in . Watch out! , although native Layer of gBinderOffsets.mObject It's a static Of , but java Layer of Binder Of mObject Is not static Of course , That is to say, each Binder Instance has one Native Of JavaBBinderHolder Object pointer .

JavaBBinderHolder Class is declared as follows :

class JavaBBinderHolder : public RefBase
{
}
No inheritance BBinder, Still didn't find out what it was Bn The trace of the end , Need to be review Let's go through the previous process , look down ServiceManagerProxy What happens when you add a service :

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

writeStrongBinder What happened?
Parcel The function is as follows :

    public final void writeStrongBinder(IBinder val) {
        nativeWriteStrongBinder(mNativePtr, val);
    }
nativeWriteStrongBinder Implementation in android_os_Parcel.cpp in :

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);
        }
    }
}
Called a ibinderForJavaObject function , This function is located in android_util_Binder.cpp in

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;
}
Incoming obj yes Binder example , So just created JavaBBinderHolder Of get Function will be called :

    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;
    }
The return is JavaBBinder example ,

JavaBBinder Inherited BBinder, So finally add it to Native ServiceManager This is the object in , Summarize their class diagrams :

Java Layer of Binder The object owns Native JavaBBinderHolder Object pointer ,JavaBBinderHolder Yes JavaBBinder The object of , and JavaBBinder And then there is Java layer Binder The object of .

版权声明
本文为[Tianwang gaidihu 626]所创,转载请带上原文链接,感谢

  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课程百度云