Property 在我们浏览 Android 源码时经常会遇到,特别是在分析 Wifi 模块时尤为突出,在网上查找了一些资料,加上自己的分析,整理出此篇。

1. 简介

Property 译为”属性“,被大量使用在 Android 系统中,用来记录系统设置或进程之间的信息交换,类似于 Windows 系统的环境变量,属性在整个系统中是全局可见的。每个属性都包括名字和值,名字和值都采用字符串存储。

2. 启动 

为了管理属性,Android 系统专门建立了一个属性服务(源码位于 ./system/core/init/property_service.c),这个属性服务运行于 init 守护进程当中。属性服务在初始化时将分配一块共享内存来存储属性,设置属性的进程必须先连接到属性服务并发送消息给他,服务将在共享内存中更新(如果不存在就新建)这个属性,获取属性的进程可以从共享内存中直接读取属性。

我觉得读和写采用不同的方式主要有以下考虑:
#通过属性服务统一写属性可以保证线性操作,避免冲突
#而直接读属性可以提高效率

属性服务启动后会从系统文件中读取默认的属性,并写入共享内存中,以下4个文件为按顺序读取:

 /default.prop
 /system/build.prop
 /system/default.prop
 /data/local.prop

后读入的属性将覆盖前面读取的相同的属性。

3. 在应用程序中操作属性 

应用程序可以直接调用库函数 libcutils 里的接口操作属性,源码在 /device/libs/cutils 内:

 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 来操作属性。在 Android 中 libc 为 bionic,源码路径为:devicce/system/bionic。

4. 在命令行中操作属性 

Android 也提供两个 bin 文件以方便在命令行或者在脚本中操作属性,分别为:

 setprop <key> <value>
 getprop <key>

其中 getprop 可以不带参数,将输出系统中的所有属性。

5. 在Java中操作属性 

属性也可以在使用 Java 编写的应用程序中被操作,Android 提供以下接口:

 System.getProperty()
 System.setProperty()

6. 特殊属性 

以某些字段开始的属性在系统中有特殊的应用。

# ro. :只读属性,一经设定,不可更改。
# persist. : 这设置这个属性时,值将会被写入 /data/property 文件中,暂时没发现有什么用处。
# net. : 设置这个属性时, "net.change" 属性将自动被设置,netresolve 模块使用这个属性来监控是否有任何 net.* 属性被更改,以便做出更新操作。
# ctrl.start :启动服务
# ctrl.stop : 停止服务,启动和停止的服务必须在 /init.rc 和 /init.<board>.rc 中定义,和Linux系统的 service start <service>类似。服务启动和停止的结果将在 "init.svc.<service name>" 属性中。

7. 属性事件 

在设置属性时,默认只会在属性共享内存中修改或者增加属性,并不会执行其它任务脚本或程序,但是属性提供增加事情的方式来达到这个功能。

例如在 /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 时,属性服务将会启动 adbd 服务。