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.rc
中on 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