SystemProperties属性变化监听 - 需要设置属性的地方主动触发

news/2025/2/19 23:46:57/

SystemProperties属性变化监听

  • 1、prop属性设置和获取
  • 2、prop属性设置改变
    • 2.1 adb执行文件设置
    • 2.2 C++中设置
    • 2.3 java中设置
    • 2.4 扩充"SystemProperties属性加载"设置
  • 3、prop属性变化监听
    • 3.1、SystemProperties属性加载时属性变化通知
    • 3.2、C++中设置属性变化没有监听
    • 3.3、java中设置属性监听变化 SystemProperties.java
      • 3.3.1 addChangeCallback添加监听
      • 3.3.2 callChangeCallbacks()
      • 3.3.3 简易时序图
      • 3.3.4 代码示例

android-12.0.0_r3


1、prop属性设置和获取

  • adb
    adb shell getprop <key>
    adb shell setprop <key> <value>
  • C++
    /system/core/libcutils/properties.cpp
    int property_get(const char* key, char* value, const char* default_value)
    int property_set(const char* key, const char* value)
  • java
    /frameworks/base/core/java/android/os/SystemProperties.java
    public static String get(@NonNull String key)
    public static void set(@NonNull String key, @Nullable String val)

在这里插入图片描述在这里插入图片描述

2、prop属性设置改变

实质都是__system_property_set() 调用writev进行socket通信设置

2.1 adb执行文件设置

  • 代码位置/system/core/toolbox/getprop.cpp,编译生成执行文件system/bin/getprop

adb shell ls /system/bin | findstr prop
在这里插入图片描述

  • 最终调用SetProperty__system_property_set() 调用writev进行socket通信设置

/system/libbase/properties.cpp
/bionic/libc/include/sys/system_properties.h
/bionic/libc/bionic/system_property_set.cpp

在这里插入图片描述
在这里插入图片描述

2.2 C++中设置

  • 代码位置/system/core/libcutils/properties.cpp
  • 最终调用,同上 2.1 adb执行文件设置

/system/libbase/properties.cpp
/bionic/libc/bionic/system_property_set.cpp

248  int __system_property_set(const char* key, const char* value) {
249    if (key == nullptr) return -1;
250    if (value == nullptr) value = "";
251  
252    if (g_propservice_protocol_version == 0) {
253      detect_protocol_version();
254    }
255  
256    if (g_propservice_protocol_version == kProtocolVersion1) {
257      // Old protocol does not support long names or values
258      if (strlen(key) >= PROP_NAME_MAX) return -1;
259      if (strlen(value) >= PROP_VALUE_MAX) return -1;
260  
261      prop_msg msg;
262      memset(&msg, 0, sizeof msg);
263      msg.cmd = PROP_MSG_SETPROP;
264      strlcpy(msg.name, key, sizeof msg.name);
265      strlcpy(msg.value, value, sizeof msg.value);
266  
267      return send_prop_msg(&msg);
268    } else {
269      // New protocol only allows long values for ro. properties only.
270      if (strlen(value) >= PROP_VALUE_MAX && strncmp(key, "ro.", 3) != 0) return -1;
271      // Use proper protocol
272      PropertyServiceConnection connection;
273      if (!connection.IsValid()) {
274        errno = connection.GetLastError();
275        async_safe_format_log(
276            ANDROID_LOG_WARN, "libc",
277            "Unable to set property \"%s\" to \"%s\": connection failed; errno=%d (%s)", key, value,
278            errno, strerror(errno));
279        return -1;
280      }
281  
282      SocketWriter writer(&connection);
283      if (!writer.WriteUint32(PROP_MSG_SETPROP2).WriteString(key).WriteString(value).Send()) {
284        errno = connection.GetLastError();
285        async_safe_format_log(ANDROID_LOG_WARN, "libc",
286                              "Unable to set property \"%s\" to \"%s\": write failed; errno=%d (%s)",
287                              key, value, errno, strerror(errno));
288        return -1;
289      }
290  
291      int result = -1;
292      if (!connection.RecvInt32(&result)) {
293        errno = connection.GetLastError();
294        async_safe_format_log(ANDROID_LOG_WARN, "libc",
295                              "Unable to set property \"%s\" to \"%s\": recv failed; errno=%d (%s)",
296                              key, value, errno, strerror(errno));
297        return -1;
298      }
299  
300      if (result != PROP_SUCCESS) {
301        async_safe_format_log(ANDROID_LOG_WARN, "libc",
302                              "Unable to set property \"%s\" to \"%s\": error code: 0x%x", key, value,
303                              result);
304        return -1;
305      }
306  
307      return 0;
308    }
309  }

2.3 java中设置

  • 代码位置/frameworks/base/core/java/android/os/SystemProperties.java
  • JNI最终调用,同上 2.1 adb执行文件设置

/frameworks/base/core/jni/android_os_SystemProperties.cpp
/bionic/libc/include/sys/system_properties.h
/bionic/libc/bionic/system_property_set.cpp

在这里插入图片描述

2.4 扩充"SystemProperties属性加载"设置

SystemProperties属性加载

3、prop属性变化监听

通过上面设置查看,只有 SystemProperties属性加载 设置时有属性设置变化通知PropertyChanged(name, value)

3.1、SystemProperties属性加载时属性变化通知

主要用于rc文件监听prop属性变化,ActionManager::GetInstance().QueuePropertyChange(name, value)通知,如/system/core/rootdir/init.rcon property:sys.boot_completed=1监听开机完成处理相关操作

/system/core/init/property_service.cpp
/system/core/init/init.cpp

329  void PropertyChanged(const std::string& name, const std::string& value) {
330      // If the property is sys.powerctl, we bypass the event queue and immediately handle it.
331      // This is to ensure that init will always and immediately shutdown/reboot, regardless of
332      // if there are other pending events to process or if init is waiting on an exec service or
333      // waiting on a property.
334      // In non-thermal-shutdown case, 'shutdown' trigger will be fired to let device specific
335      // commands to be executed.
336      if (name == "sys.powerctl") {
337          trigger_shutdown(value);
338      }
339  
340      if (property_triggers_enabled) {
341          ActionManager::GetInstance().QueuePropertyChange(name, value);
342          WakeMainInitThread();
343      }
344  
345      prop_waiter_state.CheckAndResetWait(name, value);
346  }

3.2、C++中设置属性变化没有监听

需要去实现,并要考虑通知到上层java

3.3、java中设置属性监听变化 SystemProperties.java

236      /**
237       * Add a callback that will be run whenever any system property changes.
238       *
239       * @param callback The {@link Runnable} that should be executed when a system property
240       * changes.
241       * @hide
242       */
243      @UnsupportedAppUsage
244      public static void addChangeCallback(@NonNull Runnable callback) {
245          synchronized (sChangeCallbacks) {
246              if (sChangeCallbacks.size() == 0) {
247                  native_add_change_callback();
248              }
249              sChangeCallbacks.add(callback);
250          }
251      }
252  
253      /**
254       * Remove the target callback.
255       *
256       * @param callback The {@link Runnable} that should be removed.
257       * @hide
258       */
259      @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
260      public static void removeChangeCallback(@NonNull Runnable callback) {
261          synchronized (sChangeCallbacks) {
262              if (sChangeCallbacks.contains(callback)) {
263                  sChangeCallbacks.remove(callback);
264              }
265          }
266      }
267  
268      @SuppressWarnings("unused")  // Called from native code.
269      private static void callChangeCallbacks() {
270          ArrayList<Runnable> callbacks = null;
271          synchronized (sChangeCallbacks) {
272              //Log.i("foo", "Calling " + sChangeCallbacks.size() + " change callbacks!");
273              if (sChangeCallbacks.size() == 0) {
274                  return;
275              }
276              callbacks = new ArrayList<Runnable>(sChangeCallbacks);
277          }
278          final long token = Binder.clearCallingIdentity();
279          try {
280              for (int i = 0; i < callbacks.size(); i++) {
281                  try {
282                      callbacks.get(i).run();
283                  } catch (Throwable t) {
284                      // Ignore and try to go on. Don't use wtf here: that
285                      // will cause the process to exit on some builds and break tests.
286                      Log.e(TAG, "Exception in SystemProperties change callback", t);
287                  }
288              }
289          } finally {
290              Binder.restoreCallingIdentity(token);
291          }
292      }
293  
294      /**
295       * Notifies listeners that a system property has changed
296       * @hide
297       */
298      @UnsupportedAppUsage
299      public static void reportSyspropChanged() {
300          native_report_sysprop_change();
301      }

3.3.1 addChangeCallback添加监听

  • native_add_change_callback() JNI注册到底层
  • sChangeCallbacks.add(callback)添加监听
/*** Add a callback that will be run whenever any system property changes.** @param callback The {@link Runnable} that should be executed when a system property* changes.* @hide*/
@UnsupportedAppUsage
public static void addChangeCallback(@NonNull Runnable callback) {synchronized (sChangeCallbacks) {if (sChangeCallbacks.size() == 0) {native_add_change_callback();}sChangeCallbacks.add(callback);}
}

3.3.2 callChangeCallbacks()

misc.cpp#report_sysprop_change() -> android_os_SystemProperties.cpp#do_report_sysprop_change() -> SystemProperties.java#callChangeCallbacks()
从流程上查看需要主动触发变化上报,但是查看最终__system_property_set()设置属性地方没有触发,反而需要设置属性的地方主动触发

@SuppressWarnings("unused")  // Called from native code.
private static void callChangeCallbacks() {ArrayList<Runnable> callbacks = null;synchronized (sChangeCallbacks) {//Log.i("foo", "Calling " + sChangeCallbacks.size() + " change callbacks!");if (sChangeCallbacks.size() == 0) {return;}callbacks = new ArrayList<Runnable>(sChangeCallbacks);}final long token = Binder.clearCallingIdentity();try {for (int i = 0; i < callbacks.size(); i++) {try {callbacks.get(i).run();} catch (Throwable t) {// Ignore and try to go on. Don't use wtf here: that// will cause the process to exit on some builds and break tests.Log.e(TAG, "Exception in SystemProperties change callback", t);}}} finally {Binder.restoreCallingIdentity(token);}
}

3.3.3 简易时序图

在这里插入图片描述

3.3.4 代码示例

参照时序图

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

SystemProperties.set(ACTUAL_LOGPERSIST_PROPERTY, SELECT_LOGPERSIST_PROPERTY_CLEAR);
SystemPropPoker.getInstance().poke();

/frameworks/base/core/java/android/os/SystemService.java

static {SystemProperties.addChangeCallback(new Runnable() {@Overridepublic void run() {synchronized (sPropertyLock) {sPropertyLock.notifyAll();}}});
}

/frameworks/base/core/java/android/view/WindowManagerGlobal.java
在这里插入图片描述


http://www.ppmy.cn/news/38032.html

相关文章

SpringBoot整合Swagger(三十九)

我喜欢你&#xff0c;可是你却并不知道. 上一章简单介绍了SpringBoot 过滤器和拦截器(三十八) ,如果没有看过,请观看上一章 一. 什么是 Swagger Swagger是一个规范和完整的框架&#xff0c;用于生成、描述、调用和可视化RESTful风格的Web服务&#xff0c;是非常流行的API表达…

AtCoder Beginner Contest 275 F. Erase Subarrays(线性dp)

题目 给一个长度为n(n<3e3)的数组a(1<ai<3e3)&#xff0c; 你可以进行以下操作任意次&#xff1a; 1. 选择一个a的连续子数组&#xff0c;将其删掉 对于x1,2,...,m&#xff0c;分别回答问题&#xff1a; 1. 找到最小的删除次数&#xff0c;使得剩余没被删的元素之…

《C++开发技能树》004 语言类·指针和内存管理·glibc的内存实现ptmalloc

内存泄漏是指程序在运行过程中分配了一块内存空间&#xff0c;但在使用完后没有及时释放&#xff0c;导致这块内存空间无法被再次使用&#xff0c;最终导致系统内存资源的浪费和程序性能的下降。内存泄漏通常是由于程序中存在未释放的动态内存分配、循环引用、资源管理不当等原…

【SQL开发实战技巧】系列(二十八):数仓报表场景☞人员分布问题以及不同组(分区)同时聚集如何实现

系列文章目录 【SQL开发实战技巧】系列&#xff08;一&#xff09;:关于SQL不得不说的那些事 【SQL开发实战技巧】系列&#xff08;二&#xff09;&#xff1a;简单单表查询 【SQL开发实战技巧】系列&#xff08;三&#xff09;&#xff1a;SQL排序的那些事 【SQL开发实战技巧…

【vue3-One-Piece】初入了解vue3的基本结构

前言 Animatrix&#xff1a;黑客帝国 Blade Runner&#xff1a;银翼杀手 Cowboy Bebop&#xff1a;星际牛仔 Dragon Ball&#xff1a;龙珠 Evangelion&#xff1a;新世纪福音战士 Ghostin the Shell&#xff1a;攻壳机动队 Hunter X Hunter&#xff1a;全职猎人 Initial D&…

初识设计模式 - 桥接模式

简介 桥接设计模式&#xff08;Bridge Design Pattern&#xff09;也叫作桥梁模式&#xff0c;其描述是将实现和抽象放在两个不同的类层次中&#xff0c;使两个层次可以独立地变化。 桥接模式采用抽象关联取代了传统的多层继承&#xff0c;将类之间的静态继承关系转化为动态的…

pip安装

在 Windows 上安装 pip 通常有两种方法&#xff1a; &#xff08;一&#xff09;使用 Python 自带的 get-pip.py 脚本进行安装&#xff1a; 首先&#xff0c;下载 get-pip.py 脚本&#xff1a;https://bootstrap.pypa.io/get-pip.py 将下载好的 get-pip.py 脚本保存到本地某个…

fiddler修改请求参数

打开fiddler的Customize Rules..., 在OnBeforeRequest函数中&#xff1a; //修改请求内容, 如果uri包含你的域名信息则修改请求体 if (oSession.uriContains("xxxxxxxxxxxxxxxx") || oSession.uriContains("xxxxxxxxxxxxxxxxxx")) { …