android 属性系统,SystemProperties 的简介---转载

每个属性都有一个名称和值,他们都是字符串格式。属性被大量使用在Android系统中,用来记录系统设置或进程之间的信息交换。属性是在整个系统中全局可见的。每个进程可以get/set属性。
在系统初始化时,Android将分配一个共享内存区来存储的属性。这些是由“init”守护进程完成的,其源代码位于:device/system/init。“init”守护进程将启动一个属性服务。属性服务在“init”守护进程中运行。每一个客户端想要设置属性时,必须连接属性服务,再向其发送信息。属性服务将会在共享内存区中修改和创建属性。任何客户端想获得属性信息,可以从共享内存直接读取。这提高了读取性能。
客户端应用程序可以调用libcutils中的API函数以GET/SET属性信息。libcutils的源代码位于:device/libs/cutils。API函数是:
int property_get(const char *key, char *value, const char *default_value);
int property_set(const char *key, const char *value);
而libcutils又调用libc中的 __system_property_xxx 函数获得共享内存中的属性。libc的源代码位于:device/system/bionic。
属性服务调用libc中的__system_property_init函数来初始化属性系统的共享内存。当启动属性服务时,将从以下文件中加载默认属性:
/ default.prop
/system/build.prop
/system/default.prop
/data/local.prop
属性将会以上述顺序加载。后加载的属性将覆盖原先的值。这些属性加载之后,最后加载的属性会被保持在/data/property中。

 特别属性
如果属性名称以“ro.”开头,那么这个属性被视为只读属性。一旦设置,属性值不能改变。
如果属性名称以“persist.”开头,当设置这个属性时,其值也将写入/data/property。
如果属性名称以“net.”开头,当设置这个属性时,“net.change”属性将会自动设置,以加入到最后修改的属性名。(这是很巧妙的。 netresolve模块的使用这个属性来追踪在net.*属性上的任何变化。)
属性“ ctrl.start ”和“ ctrl.stop ”是用来启动和停止服务。每一项服务必须在/init.rc中定义.系统启动时,与init守护进程将解析init.rc和启动属性服务。一旦收到设置“ ctrl.start ”属性的请求,属性服务将使用该属性值作为服务名找到该服务,启动该服务。这项服务的启动结果将会放入“ init.svc.<服务名>“属性中 。客户端应用程序可以轮询那个属性值,以确定结果。

Android toolbox程序
Android toolbox程序提供了两个工具: setprop和getprop获取和设置属性。其使用方法:
getprop <属性名>
setprop <属性名><<属性值>

Java
在Java应用程序可以使用System.getProperty()和System.setProperty()函数获取和设置属性。

Action
默认情况下,设置属性只会使"init"守护程序写入共享内存,它不会执行任何脚本或二进制程序。但是,您可以将您的想要的实现的操作与init.rc中某个属性的变化相关联.例如,在默认的init.rc中有:

    # adbd on at boot in emulator
    on property:ro.kernel.qemu=1
       start adbd
    on property:persist.service.adb.enable=1
       start adbd
    on property:persist.service.adb.enable=0
       stop adbd

这样,如果你设置persist.service.adb.enable为1 ,"init"守护程序就知道需要采取行动:开启adbd服务。

文章中提到的共享内存就是Android特有的共享方式:ashmen

Ashmem是一个匿名共享内存(Anonymous SHared MEMory)系统,该系统增加了接口因此进程间可以共享具名内存块。举一个例子,系统可以利用Ashmem存储图标,当绘制用户界面的时候多个进程也可以访问。Ashmem优于传统Linux共享内存表现在当共享内存块不再被用的时候,它为Kernel提供一种回收这些共享内存块的手段。如果一个程序尝试访问Kernel释放的一个共享内存块,它将会收到一个错误提示,然后重新分配内存并重载数据。

 


Android 的系统属性包括两部分:文件保存的持久属性和每次开机导入的cache属性。前者主要保存在下面几个文件中:

bionic / libc / include / sys / _system_properties.h
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> 1     #define  PROP_SERVICE_NAME "property_service"
2      #define  PROP_PATH_RAMDISK_DEFAULT  "/default.prop"
3      #define  PROP_PATH_SYSTEM_BUILD     "/system/build.prop"
4      #define  PROP_PATH_SYSTEM_DEFAULT   "/system/default.prop"
5      #define  PROP_PATH_LOCAL_OVERRIDE   "/data/local.prop"

后者则通过frameworks/base/core/java/android/os/SystemProperties.java的接口定义,

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->  1       private   static   native  String native_get(String key);
 2       private   static   native  String native_get(String key, String def);
 3       private   static   native   void  native_set(String key, String def);
 4       public   static   void  set(String key, String val) {
 5           if  (key.length()  >  PROP_NAME_MAX) {
 6               throw   new  IllegalArgumentException( " key.length >  "   +  PROP_NAME_MAX);
 7          }
 8           if  (val  !=   null   &&  val.length()  >  PROP_VALUE_MAX) {
 9               throw   new  IllegalArgumentException( " val.length >  "   +
10                  PROP_VALUE_MAX);
11          }
12          native_set(key, val);
13      }

该接口类在初始化运行环境中注册对应的cpp接口android_os_SystemProperties.cpp,实际操作通过JNI调用的是cpp文件对应的接口:

frameworks/base/core/jni/AndroidRuntime.cpp
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> 1       namespace  android {
2       extern   int  register_android_os_SystemProperties(JNIEnv  * env);
3      }

frameworks/base/core/jni/android_os_SystemProperties.cpp
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->  1       static   void  SystemProperties_set(JNIEnv  * env, jobject clazz, jstring keyJ, jstring valJ)
 2      {
 3           int  err;
 4           const   char *  key;
 5           const   char *  val;
 6          key  =  env -> GetStringUTFChars(keyJ, NULL);
 7           if  (valJ  ==  NULL) {
 8              val  =   "" ;        /*  NULL pointer not allowed here  */
 9          }  else  {
10              val  =  env -> GetStringUTFChars(valJ, NULL);
11          }
12          err  =  property_set(key, val);
13          env -> ReleaseStringUTFChars(keyJ, key);        
14           if  (valJ  !=  NULL) {
15              env -> ReleaseStringUTFChars(valJ, val);
16          }
17      }

设置key的value时,需要作鉴权,根据设置程序所在进程的fd获知uid值,比如system server进程可以设置net打头的key,不可以设置gsm打头的key,相关的定义如下:

system/core/include/private/android_filesystem_config.h
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> 1       #define  AID_ROOT             0  /* traditional unix root user */
2       #define  AID_SYSTEM        1000  /* system server */
3       #define  AID_RADIO         1001  /* telephony subsystem, RIL */
4       #define  AID_DHCP          1014  /* dhcp client */
5       #define  AID_SHELL         2000  /* adb and debug shell user */
6       #define  AID_CACHE         2001  /* cache access */
7       #define  AID_APP          10000 /* first app user */

system/core/init/property_service.c
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->  1       #define  PERSISTENT_PROPERTY_DIR  "/data/property"
 2       struct  {
 3           const   char   * prefix;
 4          unsigned  int  uid;
 5      } property_perms[]  =  {
 6          {  " net.rmnet0. " ,    AID_RADIO },
 7          {  " net.gprs. " ,      AID_RADIO },
 8          {  " ril. " ,           AID_RADIO },
 9          {  " gsm. " ,           AID_RADIO },
10          {  " net.dns " ,        AID_RADIO },
11          {  " net.usb0 " ,       AID_RADIO },
12          {  " net. " ,           AID_SYSTEM },
13          {  " dev. " ,           AID_SYSTEM },
14          {  " runtime. " ,       AID_SYSTEM },
15          {  " hw. " ,            AID_SYSTEM },
16          {  " sys. " ,        AID_SYSTEM },
17          {  " service. " ,    AID_SYSTEM },
18          {  " wlan. " ,        AID_SYSTEM },
19          {  " dhcp. " ,        AID_SYSTEM },
20          {  " dhcp. " ,        AID_DHCP },
21          {  " debug. " ,        AID_SHELL },
22          {  " log. " ,        AID_SHELL },
23          {  " service.adb.root " ,    AID_SHELL },
24          {  " persist.sys. " ,    AID_SYSTEM },
25          {  " persist.service. " ,   AID_SYSTEM },
26          { NULL,  0  }
27      };
28       int  property_set( const   char   * name,  const   char   * value)
29      {
30          property_changed(name, value);
31           return   0 ;
32      }
33       int  start_property_service( void )
34      {
35           int  fd;
36 
37          load_properties_from_file(PROP_PATH_SYSTEM_BUILD);
38          load_properties_from_file(PROP_PATH_SYSTEM_DEFAULT);
39          load_properties_from_file(PROP_PATH_LOCAL_OVERRIDE);
40           /*  Read persistent properties after all default values have been loaded.  */
41          load_persistent_properties();
42 
43          fd  =  create_socket(PROP_SERVICE_NAME, SOCK_STREAM,  0666 0 0 );
44           if (fd  <   0 return   - 1 ;
45          fcntl(fd, F_SETFD, FD_CLOEXEC);
46          fcntl(fd, F_SETFL, O_NONBLOCK);
47 
48          listen(fd,  8 );
49           return  fd;
50      }
51       void  handle_property_set_fd( int  fd)
52      {
53           switch (msg.cmd) {
54           case  PROP_MSG_SETPROP:
55              msg.name[PROP_NAME_MAX - 1 =   0 ;
56              msg.value[PROP_VALUE_MAX - 1 =   0 ;
57 
58               if (memcmp(msg.name, " ctl. " , 4 ==   0 ) {
59                   if  (check_control_perms(msg.value, cr.uid)) {
60                      handle_control_message(( char * ) msg.name  +   4 , ( char * ) msg.value);
61                  }  else  {
62                      ERROR( " sys_prop: Unable to %s service ctl [%s] uid: %d pid:%d\n " ,
63                              msg.name  +   4 , msg.value, cr.uid, cr.pid);
64                  }
65              }  else  {
66                   if  (check_perms(msg.name, cr.uid)) {
67                      property_set(( char * ) msg.name, ( char * ) msg.value);
68                  }  else  {
69                      ERROR( " sys_prop: permission denied uid:%d  name:%s\n " ,
70                            cr.uid, msg.name);
71                  }
72              }
73               break ;
74 
75           default :
76               break ;
77          }
78      }

在开机启动后的init操作中,会执行一个loop循环,当检测到有新的设置时,进入设置流程,鉴权失败会提示相关的异常,如sys_prop: permission denied uid:1000  name:gsm.phone.id

system/core/init/init.c
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->  1       void  property_changed( const   char   * name,  const   char   * value)
 2      {
 3           if  (property_triggers_enabled) {
 4              queue_property_triggers(name, value);
 5              drain_action_queue();
 6          }
 7      }
 8       int  main( int  argc,  char   ** argv)
 9      {
10          parse_config_file( " /init.rc " );
11          qemu_init();
12          device_fd  =  device_init();
13          property_init();
14          fd  =  open(console_name, O_RDWR);
15          property_set_fd  =  start_property_service();
16          ufds[ 0 ].fd  =  device_fd;
17          ufds[ 0 ].events  =  POLLIN;
18          ufds[ 1 ].fd  =  property_set_fd;
19          ufds[ 1 ].events  =  POLLIN;
20          ufds[ 2 ].fd  =  signal_recv_fd;
21          ufds[ 2 ].events  =  POLLIN;
22          fd_count  =   3 ;
23           for (;;) {
24               if  (ufds[ 0 ].revents  ==  POLLIN)
25                  handle_device_fd(device_fd);
26 
27               if  (ufds[ 1 ].revents  ==  POLLIN)
28                  handle_property_set_fd(property_set_fd);
29               if  (ufds[ 3 ].revents  ==  POLLIN)
30                  handle_keychord(keychord_fd);
31          }
32           return   0 ;
33      }
Android system property运作流程源码分析 属性是在整个系统中全局可见的。如果属性是有“net.”字符串开头,当设置这种属性的时候,“net.change”这条属性也会被自动设置,其内容设为最后更新过的属性名,用来记录net.*属性上面的变化。由/bionic/libc/bionic/system_properties.c中的__system_properties_init()来初始化属性系统的共享内存。在/system/core/include/private/android_filesystem_config.h中有各种权限的定义。 阅读详情

相关推荐

Android系统10 RK3399 init进程启动(三十九) property属性系统初始化代码分析

除了了解属性的基本概念,还要知道如何利用属性开发和编程, 更要理解属性背后的涉及原理, 也就源码也要去研究一下, 本章节重点介绍属性系统初始化。

ldswfun的专栏 1679

android共享内存配置,Android属性系统

1. android现在好像只有/ default.prop,/system/build.prop两个文件,别的两个文件找不到2. /data/property下有4个prop文 件:persist.sys.timezone,persist.sys.language,persist.sys.country,persist.sys.localevar, 里面保存着属性名称以“persist.”开头的...

weixin_32484541的博客 483

Android 系统属性SystemProperties)介绍

Android 10添加定制化prop

mart!nhu的博客 1万+

init进程【3】——属性服务

转载自这里】:http://blog.csdn.net/zhgxhuaa Android中的属性主要用来保存一些全局性的信息,这里可以理解为Android中的“注册表”。Android中的属性服务只针对系统开发者使用,并不对应用开发者开发,这通过SystemProperties是hide的可以看出。下面让我们一起来剖析属性服务。 初始化属性空间 在i

fanx9339的博客 525

团队成员的五种需求及其满足方式

加入项目团队中的成员,无疑需要从全局出发,为团队的共同目标而努力。但在项目的建设过程中,每个团队成员可能都存在自己的个性化需求,只要这些需求是合理的、是有利于或不影响团队目标实现的,项目经理就应该尽可能采取必要的措施予以满足。  笔者结合自己的实践经验,总结出团队成员的五种个性化需求:“物质和精神需求”、“学习需求”、“能力锻炼需求”、“交友需求”和“自我展现需求”,并对如何满足这五种需求进行

elimago的专栏 1104

项目团队成员的五种需求及其满足方式

<br />加入项目团队中的成员,无疑需要从全局出发,为团队的共同目标而努力。但在项目的建设过程中,每个团队成员可能都存在自己的个性化需求,只要这些需求是合理的、是有利于或不影响团队目标实现的,项目经理就应该尽可能采取必要的措施予以满足。<br /><br />笔者结合自己的实践经验,总结出团队成员的五种个性化需求:“物质和精神需求”、“学习需求”、“能力锻炼需求”、“交友需求”和“自我展现需求”,并对如何满足这五种需求进行一定深度的探讨。<br /><br />这五种个性化需求,笔者认为可以采用下图来展现

dongdongleng的专栏 789

成功项目团队中应树立的五种意识

人常说:"一个中国人是龙,一群中国人是虫。"由于中西方文化的差异,似乎中国人更擅长单兵作战。所以,项目团队的管理在我国显得特别需要。笔者总结了数年来在IT行业项目管理的经验和教训,认为成功的项目团队应普遍树立起五种思想意识--目标意识、团队意识、服务意识、竞争意识和危机意识。下面一一诠释一下 。一、目标意识1、 目标到人  项目管理是目标管理,项目有明确的目标,所以团队中每个人必需有明确的目标。考

inshine的专栏 1063

使用devops的团队_感谢您的DevOps团队的5种方式

使用devops的团队 我的团队最近收到了一位社区成员的手写感谢信。 音符非常好,出乎意料,使我们感觉很好。 这就是说谢谢的力量。 对于给予者和接受者而言,分享感激创造了一种令人满足和人性化的情感联系。 坦白说,在当今高节奏的工作环境,两极分化的政治和自然灾害的影响下,我们可以在世界上更多地感恩。 更多DevOps资源 什么是DevOps? 最终的DevOps招聘指南 De...

cumo3681的博客 316

马斯洛 游戏需求

4.马斯洛需要层次理论基本内容是什么?对照该理论举例说明玩家在游戏中有哪几级需要。结合关卡中障碍和技巧的设置探讨游戏设计中应该如何满足这些需要。 答:(一)马斯洛需要层次理论基本内容:动机是人类生存和发展的动力,而需要是动机产生的基础。人类大致有五种需要:1.生理需要,指和维持个体生存与发展有关的需要,是最基本、最原始的需要;2.安全需要,指对稳定、安全、保障和秩序等的需要;3.归属与爱的需要,

Code大蛇丸 3177

敏捷团队实现冲刺承诺的5种方式

Scrum团队的一项基本实践是在冲刺开始时致力于优先工作,然后在结束时完全完成它。 强大的敏捷团队可以完成或超越其冲刺承诺,并在冲刺结束时交付工作软件。 他们还测量自己的速度,并在追溯会议上讨论过程改进,以提高质量,生产率和其他指标。 [ 也在InfoWorld上:如何在敏捷软件开发中脱颖而出 ] 但是履行冲刺承诺并不是一件容易的事,而且许多障碍会阻碍团队。 例如: 新组建的团...

cxu0262的博客 681

团队任务进度跟踪:五种工具对比及适用场景

团队任务跟踪工具的选择应基于五个关键维度:可视化程度、责任明确性、实时更新能力、数据分析和灵活适应性。主流工具包括传统看板型(如Trello)、表格型(如Airtable)、综合协作平台(如Notion)、专业项目管理软件(如Jira)以及国内友好型工具(如板栗看板)。选择时需考虑团队规模、流程复杂度、使用习惯和扩展性,建议通过试点测试评估效果。实施时应渐进推广、建立规范并定期优化,最终目标是实现透明高效的团队协作。

Saweet_ie的博客 802

敏捷 冲刺_敏捷团队实现冲刺承诺的5种方式

敏捷 冲刺 Scrum团队的一项基本实践是在冲刺开始时致力于优先工作,然后在结束时完全完成它。 强大的敏捷团队可以完成或超越其冲刺承诺,并在冲刺结束时交付工作软件。 他们还测量自己的速度,并在追溯会议上讨论过程改进,以提高质量,生产率和其他指标。 [ 同样在InfoWorld上:如何在敏捷软件开发中脱颖而出 ] 但是履行冲刺承诺并非微不足道,许多障碍会阻碍团队。 例如: 新组建的...

cxu0262的博客 2099

假如需求拆分像切蛋糕一样简单 | 敏捷实践

需求拆分就跟切蛋糕一样,纵向垂直切分才能更好地实现敏捷。

LigaAI的博客 977
上一篇: 3Gpp 英文简称对应中文
下一篇: android 可用内存的阀值--转载
carywei
博客等级 码龄17年 35粉丝 70原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值