监听系统属性SystemProperties值变化

基于 Android-S

一、实现逻辑

相关文件:
frameworks/native/libs/binder/Binder.cpp
/system/core/libutils/misc.cpp
/android/frameworks/base/core/java/android/os/SystemProperties.java
/android/frameworks/base/core/jni/android_os_SystemProperties.cpp
/android/frameworks/base/core/jni/android_util_Binder.cpp

1. callback注册

private static final ArrayList<Runnable> sChangeCallbacks = new ArrayList<Runnable>(); //SystemProperties.java
static Vector<sysprop_change_callback_info>* gSyspropList = nullptr; //misc.c

    addChangeCallback(Runnable callback) //SystemProperties.java public static的
        native_add_change_callback() //只对首个callback的注册执行,注意没有传任何参数 #####
            SystemProperties_add_change_callback(JNIEnv *env, jobject clazz) //android_os_SystemProperties.cpp
                sCallChangeCallbacks = env->GetStaticMethodID(sClazz, "callChangeCallbacks", "()V"); //记录java函数的id
                add_sysprop_change_callback(do_report_sysprop_change, -10000); //形参(cb, priority)
                    sysprop_change_callback_info info;
                    info.callback = cb; //固定是 do_report_sysprop_change()
                    info.priority = priority;
                    bool added = false;
                    for (size_t i=0; i<gSyspropList->size(); i++) { //(只有首个才会)插入到全局vector gSyspropList 中
                        if (priority >= gSyspropList->itemAt(i).priority) {
                            gSyspropList->insertAt(info, i); //priority数值大的插入在前面
                            added = true;
                            break;
                        }
                    }
                    if (!added) {
                        gSyspropList->add(info); //优先级数值最小的插入在末尾
                    }
        sChangeCallbacks.add(callback) //SystemProperties.java 添加到 ArrayList<Runnable> 链表中

注1: 通过 add_sysprop_change_callback(cb, prio) 注册的 cb 的类型是 void (*)(void) 类型,prio 的数值越大,在Vector中越靠前,相当于优先级越高。

注1: 这里列出的只是列出的只是Java通过JNI注册的cb,还有一些native注册的cb这里没列出来。


2. 服务端响应,调用回调

//android/system/libhidl/base/HidlInternal.cpp
//android/system/iorap/src/manager/event_manager.cc

onTransact() //android_util_Binder.cpp if (code == SYSPROPS_TRANSACTION) 成立才调用
    BBinder::onTransact() //Binder.cpp
        case SYSPROPS_TRANSACTION:
            report_sysprop_change() //misc.cpp
                do_report_sysprop_change() //misc.cpp 第一次调用 system/libutils.so 中的####。
                    listeners = *gSyspropList; //通过 add_sysprop_change_callback(cb, prio) 注册。
                    for (size_t i=0; i<listeners.size(); i++) {
                        listeners[i].callback(); //参考下面注册路径
                            //SystemProperties_add_change_callback(do_report_sysprop_change, -10000) android_os_SystemProperties.cpp 进入Java, 主要路径
                            do_report_sysprop_change //android_os_SystemProperties.cpp
                                 env->CallStaticVoidMethod(sClazz, sCallChangeCallbacks);
                                    callChangeCallbacks() //SystemProperties.java 调到Java层
                                        for (int i = 0; i < callbacks.size(); i++)
                                            callbacks.get(i).run(); //回调Java层注册的回调
                            atrace_update_tags() //trace-dev.inc
                            HidlInstrumentor::HidlInstrumentor //HidlInternal.cpp 调用 __gcov_flush()
                            EventManager::Impl::OnSyspropChanged() //event_manager.cc
                    }
                get_report_sysprop_change_func()
                    handle = android_load_sphal_library("libutils.so", RTLD_NOW);
                    func = reinterpret_cast<decltype(func)>(dlsym(handle, "do_report_sysprop_change"));
                (*func)();
                    do_report_sysprop_change() //misc.cpp 如果sphal中也存在,则调用sphal中的

misc.cpp中的 do_report_sysprop_change() 被加载了两次,源码上有这个注释:
libutils.so 文件被重复加载;它同时从默认命名空间和 'sphal' 命名空间加载。请将 sysprop 更改事件重定向到加载在 'sphal' 命名空间中的 libutils.so 实例,以便附加到该实例的监听器也能收到此事件通知。


3. 客户端调用,使用服务

/android/frameworks/base/packages/SettingsLib/src/com/android/settingslib/development/SystemPropPoker.java

SystemPropPoker.poke() //这个是通知所有有名服务
    createPokerTask().execute()
        doInBackground(Void... params)
            String[] services = listServices(); //对系统中的每一个有名服务都调用(你也可以单独调用某一个服务的)########
            for (String service : services) {
                IBinder obj = checkService(service);
                obj.transact(IBinder.SYSPROPS_TRANSACTION, data, null, 0)
            }

触发所有有名服务注册的callback回调。

 

二、其它使用位置

1. ANRdaemon

main(int argc, char* argv[])
    start() //ANRdaemon.cpp
        dfs_poke_binder() //ANRdaemon.cpp
            sp<IServiceManager> sm = defaultServiceManager();
            Vector<String16> services = sm->listServices();
            for (size_t i = 0; i < services.size(); i++) {
                sp<IBinder> obj = sm->checkService(services[i]);
                if (obj != NULL) {
                    Parcel data;
                    obj->transact(IBinder::SYSPROPS_TRANSACTION, data, NULL, 0);
                }
            }

编译成 anrd 这个可执行文件,一般不集成。

 

三、总结

高负载下此调用会导致SS的绝大多数binder线程被卡住。

 

 

参考:

监听SystemProperties变化: https://blog.csdn.net/m0_52481422/article/details/109776370

 

posted on 2024-11-01 22:08  Hello-World3  阅读(630)  评论(0)    收藏  举报

导航