目录

  • 背景
  • 问题
  • 分析
  • 总结

背景

在device.mk文件中新增了一个persist类的property,名字为persist.control,device.mk中将其默认值设定位0。如下所示:

PRODUCT_PROPERTY_OVERRIDES += persist.control=0

进程P根据该property的值来选择执行不同的逻辑,开发者可以通过setprop命令或者property_set接口改变persist.control的值:

 setprop persist.control 1getprop persist.control
1
#include <cutils/properties.h>
char get_prop_crtl[PROPERTY_VALUE_MAX];
property_get("persist.control", get_prop_crtl, "0");

问题

从上述的背景看,是相当简单的需求,修改persist.control的值后,在命令行启动进程P,也确实可以获取到修改后的persist.control的值并执行对应的结果。于是将进程P放到init.rc作为daemon service启动,通过名字为S的service启动进程P,service S的启动条件是on init:

service S /system/bin/Pclass corecriticaldisableduser shellgroup shellseclabel u:r:shell:s0
...
on initstart S

但是重启系统后发现,进程P并没有执行修改后的persist.control的值对应的逻辑,而是执行了persist.control默认值(即device.mk中设定的0)对应的逻辑,但是通过getprop命令查看,persist.control的值确实被修改为1了。

分析

之前也有使用persist类property的经验,但是一直没有了解它的原理,趁这个机会翻了网上的资料和代码,发现persist类property的设置和获取大概是这样:

  1. 在mk文件设定persist类property的默认值;
  2. 编译后persist类property以及其默认值会被汇总到.prop文件,如build.prop和default.prop;
  3. 系统启动后,init读取.prop中的property定义以及默认值,加载至内存;
  4. 对于persist类的property,读取/data/property/persistent_properties中保存的修改后的值,并更新到内存中,这里修改后的值,就是通过setprop命令或者property_set接口更新的值,可以在这个文件中查到,每当修改persist.control的值后,文件中对应的值也会发生相应变化

相关的代码可以查阅system/core/init和system/core/toolbox

从上述流程可以看出,猜测是进程P被启动前,init还没执行第4步,因为进程P被执行的时机是on init,为了验证这一猜想,将进程P的执行时间点,即service S的执行时间点从on init修改为on property:persist.control=1,即等init执行了上述第4步操作后,才去启动进程P:

service S /system/bin/Pclass corecriticaldisableduser shellgroup shellseclabel u:r:shell:s0
...
on property:persist.control=1start S

修改后,进程P确实运行了persist.control=1对应的逻辑,验证了猜想

除此之外,还有另一种修改方法,在system/core/init/property_service.cpp代码中可以看到,当通过/data/property/persistent_properties完成persist类property的值的更新后,会设置ro.persistent_properties.ready为true:

switch (init_message.msg_case()) {case InitMessage::kLoadPersistentProperties: {load_override_properties();// Read persistent properties after all default values have been loaded.auto persistent_properties = LoadPersistentProperties();for (const auto& persistent_property_record : persistent_properties.properties()) {InitPropertySet(persistent_property_record.name(),persistent_property_record.value());}InitPropertySet("ro.persistent_properties.ready", "true");persistent_properties_loaded = true;break;}default:LOG(ERROR) << "Unknown message type from init: " << init_message.msg_case();
}

因此,也可以将启动service S的条件设置为on property:ro.persistent_properties.ready=true,即:

service S /system/bin/Pclass corecriticaldisableduser shellgroup shellseclabel u:r:shell:s0
...
on property:ro.persistent_properties.ready=truestart S

这里可能会有疑惑,为什么ro类的property可以重新设置,其实是因为ro.persistent_properties.ready这个property并没有在代码中被设定默认值,即代码中没有定义ro.persistent_properties.ready这个property,但是却有根据ro.persistent_properties.ready的值去触发操作的逻辑,这在Android系统中是允许的,即用setprop或者property_set接口去设置一个代码中未定义的property的值,注意ro类的property只能设置一次,如果想要重新设置,则需要重启机器,因为这类未在代码定义的property的值,是不会固化保存的(persist类除外,因为这类property是保存在data分区的)。

对于已经在代码中定义好初始值的ro类property,则无法修改对应的值,因为它们的初始值都被保存在system和vendor等只读分区,每次启动都会从对应的prop文件中读取默认值到内存。

从上面可以看出,所谓的ro类的property,严格来说并不是真的只读,而是在每次系统启动后,只有一次设置值的机会,对于已经在代码中定义好的property,都会由系统加载默认值到内存,所以这里的ro,贴切来说,应该是内存中的property只允许赋值一次。

总结

遇到这类系统原生机制导致的问题,还是要回到源码本身和机制的原理进行分析

Android persist类property 知识点相关推荐

  1. Android 属性动画Property Animation(中)

    Android 属性动画Property Animation(上)介绍了属性动画的概念以及相关的类和接口,本篇来看下具体肿么使用. ValueAnimator ValueAnimator指定整形.浮点 ...

  2. Android工程师面试准备知识点

    Android工程师面试准备知识点 听+7哥说,把下面的全弄懂,面试必过,所以我就试着去把所有题目补充了一下,各位能耐的网友们,如果有吐槽或者补充的尽管给我留言,在这里谢过大家了. 1.   andr ...

  3. android动画类

    android动画类有三种实现形式,分别是Property Animation,Frame Animation,Tween Animation.Tween Animation主要是实现图片的移动来实现 ...

  4. Android Bundle类 学习总结

    Android Bundle类 http://blog.csdn.net/randyjiawenjie/article/details/6651437 根据google官方的文档(http://dev ...

  5. android Integer类的toString函数的使用

    今天,简单讲讲android里如何使用Integer类的toString函数.  这个其实很简单,就是将整数转成字符串.不过之前一直使用的是String.value()来进行转换的.后来在为网上查 ...

  6. android AtomicBoolean类的使用

    今天,简洁讲讲如何使用  AtomicBoolean这个类. 类 在java.util.concurrent.atomic包下,有AtomicBoolean , AtomicInteger, At ...

  7. android Rect类的使用

    今天,讲讲Android的Rect类的使用. public final class Rect extends Object implements Parcelable java.lang.Object ...

  8. Android Canvas类介绍和Android Draw Rect 坐标图示

    当我们调整好画笔之后,现在需要绘制到画布上,这就得用Canvas类了.在Android中既然把Canvas当做画布,那么就可以在画布上绘制我们想要的任何东西.除了在画布上绘制之外,还需要设置一些关于画 ...

  9. Android生命周期帮助类,Android Service类与生命周期详细介绍_Android_脚本之家

    Android  Service类与生命周期 Service是Android四大组件与Activity最相似的组件,都代表可执行的程序,区别在于Service一直在后台运行且没有用户界面. 1.Ser ...

最新文章

  1. 《科学》十大年度科学突破反映的新动向
  2. 线下讲座 | 机器翻译大牛Kevin Knight: Translation and Ciphers
  3. 数据结构栈的知识_数据知识栈
  4. Tensorflow笔记(基础):批处理(batch_normalization)
  5. tf.nn.sigmoid_cross_entropy_with_logits 分类
  6. 女生看了别怨我啊!!!!
  7. 2016高管必看的五大互联网营销方法
  8. Chromium学习笔记
  9. http请求中关于SSL server certificate验证的trace细节
  10. 《嵌入式 - STM32开发指南》手把手教你搭建STM32开发环境 [Linux版 - 1]
  11. 为什么一般的眼科医院很难发现眼底疾病?这个是关键!
  12. Linux 下的zip,rar
  13. 步进电机、伺服电机的接线说明书、示意图
  14. 北京第二外国语学院本科毕业论文答辩PPT模板
  15. 微信小程序的开发使用第三方组件库
  16. 24段魔尺,骆驼,小狗,金鱼,蝴蝶结
  17. pqc的中文全称_品质部门 一次看懂IQC / IPQC / PQC / FQC / OQC!
  18. ppt年终总结(计算机专业),计算机系学工办年终工作汇报总结PPT.ppt
  19. php web项目目录结构图,目录结构
  20. require引入js vue_requirejs + vue 项目搭建

热门文章

  1. Linux运维精华面试题
  2. SAP 薪酬计算流程
  3. jupyter 安装插件rise,变为幻灯片PPT格式
  4. 机器学习-神经网络(Neural Network)算法
  5. Element UI 自定义穿梭框的数据项
  6. CSS中定位属性的常见属性值
  7. 基于C语言的简单小游戏-(扫雷)
  8. 数字水印(DWT算法Python实现)
  9. 位图与普通图片的区别
  10. Docker push命令推送镜像到远端仓库