Property属性介绍
Property属性被大量使用在Android系统中,在整个系统中全局可见的,用来记录系统设置或进程之间的信息交换,每个进程可以get/set属性,每个属性都有一个名称和值(key=value),他们都是字符串格式。
属性" ctrl.start “和” ctrl.stop “是用来启动和停止服务。每一项服务必须在init.rc中定义系统启动时,与init守护进程将解析init.rc和启动属性服务。一旦收到设置“ ctrl.start ”属性的请求,属性服务将使用该属性值作为服务名找到该服务,启动该服务,这项服务的启动结果将会放入” init.svc.<服务名> "属性中。
在系统初始化时,Android将分配一个共享内存区来存储的属性。这些是由“init”守护进程完成的,其源代码位于device/system/init
。"init"守护进程将启动一个属性服务,属性服务在“init”守护进程中运行,每一个客户端想要设置属性时,必须连接属性服务,再向其发送信息,属性服务将会在共享内存区中修改和创建属性。任何客户端想获得属性信息,可以从共享内存直接读取,提高了读取性能。
Property属性组成
Android 的系统属性包括两部分:文件保存的持久属性和每次开机导入的cache属性。
前者主要保存在prop文件中,需要注意的是android属性的名称是有一定的格式要求的
system/core/init/property_service.c
#定义的前缀
属性名以ro.开头,该属性被视为只读属性,一旦设置属性值不能改变
属性名以persist.开头,该属性值将写入/data/property
属性名以net.开头,当设置这个属性时,“net.change”属性将会自动设置,以加入到最后修改的属性名
bionic/libc/include/sys/_system_properties.h
//系统的prop属性文件
#define PROP_PATH_RAMDISK_DEFAULT "/default.prop"
#define PROP_PATH_SYSTEM_BUILD "/system/build.prop"
#define PROP_PATH_VENDOR_BUILD "/vendor/build.prop"
#define PROP_PATH_LOCAL_OVERRIDE "/data/local.prop"
#define PROP_PATH_FACTORY "/factory/factory.prop"
后者则通过frameworks/base/core/java/android/os/SystemProperties.java
的接口定义
private static native String native_get(String key);
private static native String native_get(String key, String def);
private static native int native_get_int(String key, int def);
private static native long native_get_long(String key, long def);
private static native boolean native_get_boolean(String key, boolean def);
private static native void native_set(String key, String def);
private static native void native_add_change_callback();
该接口类在初始化运行环境中注册对应的cpp接口android_os_SystemProperties.cpp
,实际操作通过JNI调用的是cpp文件对应的接口frameworks/base/core/jni/AndroidRuntime.cpp
关于build.prop
生成过程的分析,可知属性的来源:
- buildinfo.sh:系统默认属性一般是
build/tool/buildinfo.sh
,编译时写到文件build.prop - system.prop:
- ADDITIONAL_BUILD_PROPERTIES或PRODUCT_PROPERTY_OVERRIDES:
一般我们自定义属性就在对应的项目下device/$(TARGET_DEVICE_DIR)/
system.prop 定义自己的属性即可,建议修改属性在system.prop
或PRODUCT_PROPERTY_OVERRIDES
,这对应于具体特定平台或产品的修改。
Property属性加载
在init.cpp
文件main函数中会调用start_property_service(),而它分别调用load_properties_from_file()读取到.prop文件
,存放系统属性的文件并设置到系统属性。同时会调用load_persistent_properties函数,该函数会在/data/property/中寻找用户的保存设置。
system/core/init/property_service.c
//属性服务启动后会从系统文件中读取默认的属性,并写入共享内存中,以下prop文件为按顺序读取
//后读入的属性将覆盖前面读取的相同的属性
void start_property_service(void)
{
int fd;
load_properties_from_file(PROP_PATH_SYSTEM_BUILD);
load_properties_from_file(PROP_PATH_SYSTEM_DEFAULT);
#ifdef ALLOW_LOCAL_PROP_OVERRIDE
load_properties_from_file(PROP_PATH_LOCAL_OVERRIDE);
#endif /* ALLOW_LOCAL_PROP_OVERRIDE */
/* Read persistent properties after all default values have been loaded. */
load_persistent_properties();
update_legacy_atvc_properties();
}
开机过程中Loading properties
顺序:
01-01 08:05:27.884 0 0 I init : (Loading properties from /default.prop took 0.00s.)
01-01 08:05:29.509 0 0 I init : (Loading properties from /persist/speccfg/vendor_ro.prop took 0.01s.)
01-01 08:05:29.511 0 0 I init : (Loading properties from /system/vendor/vendor.prop took 0.00s.)
01-01 08:05:29.511 0 0 I init : (Loading properties from /system/vendor/Default/system/vendor/vendor.prop took 0.00s.)
01-01 08:05:29.511 0 0 I init : (Loading properties from /persist/speccfg/vendor_persist.prop took 0.00s.)
01-01 08:05:29.512 0 0 I init : (Loading properties from /system/vendor/default.prop took 0.00s.)
01-01 08:05:29.512 0 0 I init : (Loading properties from /system/vendor/power.prop took 0.00s.)
01-01 08:05:29.512 0 0 I init : (Loading properties from /system/build.prop took 0.01s.)
01-01 08:05:29.512 0 0 I init : (Loading properties from /vendor/build.prop took 0.00s.)
01-01 08:05:29.512 0 0 I init : (Loading properties from /factory/factory.prop took 0.00s.)
01-01 00:05:29.490 0 0 I init : (Loading properties from /system/vendor/Default/system/vendor/vendor.prop took 0.00s.)
...
01-01 08:05:30.351 0 0 E init : load persistent properties start
我在load_persist_props()
中加了log,可以发现加载persistent properties
属性会有延迟,之前遇到一个项目的时候发现的在开机动画之后才加载persistent properties
system/core/init/property_service.cpp
void load_persist_props(void) {
load_override_properties();
/* Read persistent properties after all default values have been loaded. */
+ ERROR("load persistent properties start\n");
load_persistent_properties();
}
ADB设置使用Property
getprop
读值
setprop
设值
C:\Users\Admin>adb shell
trinket:/ $ su
trinket:/ # getprop qemu.hw.mainkeys
1
trinket:/ # setprop qemu.hw.mainkeys 0
Property属性使用get/set
- The Java API
import android.os.SystemProperties;
public static String get(String key, String def) {}
public static void set(String key, String val) {}
//示例
//Systemproperties类在android.os下,但这个类是隐藏的,上层程序开发无法直接使用
//需要系统属性设置的程序也必须有system或root权限,或者用Java的反射机制
需要注意的是android属性的名称是有一定的格式要求的,前缀必须用system\core\init\property_service.c中定义的前缀(后面会详细列出),
Systemproperties.set(name, value);//设置
Systemproperties.get(name);//读取
- The Native API
#include <cutils/properties.h>
int property_get(const char *key, char *value, const char *default_value);
int property_set(const char *key, const char *value);
//示例
//property_get有三个参数,第2个参数为数组,表示将get到的值放入此数组中,第3个参数为默认值,如果property_get读不到某属性(未定义此属性),则取默认值
char buf[20]="ssssssssssss";
char tempbuf[PROPERTY_VALUE_MAX];
property_set("phone.imei",buf);
property_get("phone.imei",tempbuf,"0");
属性相关
设置属性,ro.开头的属性将不能被更改属性值,persist.开头的属性会被永久纪录,其他属性值在重新开机后均将被丢弃:
int property_set(const char *name, const char *value)
当用户设置属性时,如果以属性名字以persist.开头,则会同时在/data/property目录下创建以该属性名字命名的文件,并写入属性值
#define PERSISTENT_PROPERTY_DIR “/data/property”
static void write_persistent_property(const char *name, const char *value)
加载永久属性时,会读入在目录/data/property下所有名字以persist.开头的文件内容,作为该名字对应的属性值
static void load_persistent_properties()
Android的启动后,在property_service.c的property_init中完成prop的初始化。系统中存在着几个文件,如build.prop和default.prop等,这些文件在系统构建时候生成的,里面包含很多系统的配置。系统开机时回去加载这些文件中的信息并保存到prop模块(内存)中去,以便其它程序进行读取和使用。
所有的persist类型的属性都是在/data/property/目录下以文件形式存在。
Env环境变量中有一个ANDROID_PROPERTY_WORKSPACE变量,该变量中存储着prop内存区域的大小,可查阅init_property_area()。
通过ps
我们可以查到一些应用的USDER ID为system,radio,AID_USER + app_id ,如果我们碰到设置系统属性不成功,就可以升级应用用户属性来提升用户操作权限。
属性设置的两个地方:一个是配置文件读取的,一个是系统动态获取的
相关参考
https://blog.csdn.net/wdong_love_cl/article/details/52404692
Android 系统属性SystemProperty分析
MTK Android Framework用SystemProperties通过JNI调用访问系统属性
Android SystemProperties简介
Android SystemProperties设置/取得系统属性的用法总结
Android属性之build.prop生成过程