首页 > 其他分享 >监听系统属性SystemProperties值变化

监听系统属性SystemProperties值变化

时间:2024-11-01 21:58:15浏览次数:1  
标签:SystemProperties 监听系统 sysprop callback cpp android change 属性

基于 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> 链表中


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

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 //android_os_SystemProperties.cpp 使用的是namespace Android里面的函数 【1】
                    env->CallStaticVoidMethod(sClazz, sCallChangeCallbacks); //native回调Java函数
                        callChangeCallbacks() //SystemProperties.java 看下面首个注册,是这个函数
                            ArrayList<Runnable> callbacks = new ArrayList<Runnable>(sChangeCallbacks);
                            for (int i = 0; i < callbacks.size(); i++) {
                                callbacks.get(i).run(); //直接调用Runnable类的run()方法,相当于在本线程中执行
                            }
                get_report_sysprop_change_func() //misc.cpp
                    do_report_sysprop_change //misc.cpp 通过dlopen(libutils.so)获取的,它本身也属于这个库。
                        Vector<sysprop_change_callback_info> listeners = *gSyspropList; //每个进程首个插入callback时会添加到这里来
                        for (size_t i=0; i<listeners.size(); i++) {
                            listeners[i].callback();
                                do_report_sysprop_change() //android_os_SystemProperties.cpp callback只有一个,固定为它,它的执行内容就是【1】
                        }

TODO: 【1】为啥会重复执行呢?是不同的内容执行的不一样吗?


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

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); //竟然是调用所有服务的
        }
    }

 

三、总结

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

 

 

参考:

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

 

标签:SystemProperties,监听系统,sysprop,callback,cpp,android,change,属性
From: https://www.cnblogs.com/hellokitty2/p/18521371

相关文章

  • C#通过反射实现动态属性访问器
    动态属性访问器使用反射,我们可以创建一个动态的属性访问器(DynamicPropertyAccessor),允许我们在运行时访问和修改对象的属性为什么要动态访问为什么不直接访问,而用动态访问?直接访问适用于:编译时就知道要访问的属性追求最高性能的场景简单的属性访问动态访问适用于:运......
  • PbootCMS后台ueditor编辑器上传图片如何去掉自动添加的title和alt属性
    修改ueditor.all.min.js文件:打开 \core\extend\ueditor\ueditor.all.min.js 文件搜索 "imageUrlPrefix",找到以下代码:javascript g.setAttribute("title",f.title||"");g.setAttribute("alt",f.original||"");修......
  • 根据字符串,获取实体属性上的annotation,如:createTime” 找到对应实体属性中的 TableFi
    根据字符串,获取实体属性上的annotation,如:createTime”找到对应实体属性中的TableField(value="create_time",fill=FieldFill.INSERT)Field[]fields=clazz.getFields();//仅能获取类(及其父类)public属性成员Field[]declaredFields=clazz.getDeclaredFields();......
  • angular - 阅读zone.js代码引出的访问器属性问题
    对websocket的onmessageonerroronopenonclose事件是如何被zone.js代理存在疑问,阅读了zone.js的源码此处对WebSocket.prototype的onmessageonerroronopenonclose进行patch操作 具体的patch操作如下:  对WebSocket.prototype上的访问器属性(区别于数据属性)而言,webSo......
  • angular - 属性修饰器的使用
    参考文章https://zhuanlan.zhihu.com/p/65764702 例子:以前的代码,针对表格的滚动区高度动态设置代码,需要在每个组件里利用ResizeObserver监听表格容器尺寸变化,然后动态修改滚动区高度,这样在代码里存在大量的相似冗余  引入属性修饰器,能够抽象公共代码,如下 业务组件......
  • C# 13(.Net 9) 中的新特性 - 半自动属性
    C#13即.Net9按照计划会在2024年11月发布,目前一些新特性已经定型,今天让我们来预览其中的一个新特性:作者注:该特性虽然随着C#13发布,但是仍然是处于preview状态的特性,请谨慎使用半自动属性Semi-autoproperties大家都知道,C#早在3.0时候就添加了自动属性这个特性,让我......
  • 界面控件DevExpress WPF v24.1新版亮点:属性网格、轻量级主题升级
    DevExpressWPF拥有120+个控件和库,将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpressWPF能创建有着强大互动功能的XAML基础应用程序,这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。DevExpressWPF控件今年一个重大版本——v24.1全......
  • List<Map<String,Object>> 属性获取
    publicstaticvoidmain(String[]args){//1.数据准备List<Map<String,Object>>list=newArrayList<>();Map<String,Object>map=newHashMap<>();map.put("name","songwp");......
  • 学习笔记(六):ArkUi-线性布局 (Row/Column)常用属性
    一、space属性设置排列方向上子元素的间距,使各子元素在排列方向上有等间距效果。 二、alignItems属性设置子元素在交叉轴(排列方向的垂直方向)上的对齐方式。且在各类尺寸屏幕中,表现一致。其中,交叉轴为垂直方向时,取值为VerticalAlign类型,水平方向取值为HorizontalAlign类型。......
  • autofac属性注入
    usingAutofac;namespaceautofac属性注入;internalclassProgram{staticvoidMain(string[]args){//创建一个容器ContainerBuilderbuilder=newContainerBuilder();//注册UserServicebuilder.RegisterType<UserService......