在Android系统中,属性系统(Property System)是一个全局的键值对存储机制,它允许系统服务和应用程序共享配置信息。这套机制在系统初始化、服务管理和运行时配置中扮演着重要角色。理解属性系统的运作原理,对于进行Android系统开发和定制至关重要。
属性系统本质上是一个共享内存区域,由init进程负责维护。所有属性都存储在共享内存中,并通过socket接口进行访问控制。这种设计使得属性访问非常高效,同时也保证了安全性。属性名称采用分层命名空间,常见的命名空间包括:
重要提示:操作Android属性需要特别注意权限问题,特别是在SELinux强制模式下,错误的权限配置会导致操作失败。这也是很多开发者在实际开发中经常遇到的坑。
Android提供了cutils库中的property.h头文件,其中定义了属性操作的核心API:
c复制#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);
在实际使用中,我们通常会封装这些基础API以提高代码的可读性和易用性。如示例代码中的封装:
c++复制void getSystemProperty(const std::string& property) {
char value[PROP_VALUE_MAX]; // PROP_VALUE_MAX通常定义为92
if (property_get(property.c_str(), value, "") > 0) {
ALOGD("Property Value for %s: %s", property.c_str(), value);
} else {
ALOGE("Failed to get property: %s", property.c_str());
}
}
这里有几个关键点需要注意:
除了常规属性外,Android还通过属性系统提供了服务控制机制。通过设置ctl.start和ctl.stop属性,可以启动或停止系统服务:
c++复制// 停止gatekeeper服务
setSystemProperty("ctl.stop", "vendor.gatekeeper-1-0");
// 启动gatekeeper服务
setSystemProperty("ctl.start", "vendor.gatekeeper-1-0");
这种服务控制机制在系统调试和动态服务管理中非常有用。但需要注意:
在AOSP环境中,我们使用Android.bp来定义模块构建规则。对于属性操作工具,典型的配置如下:
python复制cc_binary {
name: "propertyoperation",
srcs: ["main.cpp"],
shared_libs: [
"liblog",
"libcutils",
],
cflags: [
"-Wall",
"-std=c++11",
],
vendor: true,
}
关键配置说明:
vendor: true表示这是一个vendor模块,会安装到/vendor分区shared_libs声明了对Android日志系统和cutils库的依赖-std=c++11启用了C++11标准支持完整的编译部署流程如下:
mmm device/hello/propertyoperation/ -j12adb push out/target/product/xxx/vendor/bin/propertyoperation /vendor/bin/adb shell chmod 755 /vendor/bin/propertyoperation经验分享:在实际开发中,建议先将二进制推送到/data/local/tmp测试,确认功能正常后再部署到/vendor分区。这样可以避免频繁刷机。
在SELinux强制模式下,操作属性经常会遇到权限问题。如示例中出现的错误:
code复制Unable to set property "vendor.my.work.time" to "8": connection failed; errno=13 (Permission denied)
这类错误通常由以下原因导致:
完整的SELinux策略配置需要以下几个文件:
python复制type propertyoperation_dt, domain;
type propertyoperation_dt_exec, exec_type, vendor_file_type, file_type;
init_daemon_domain(propertyoperation_dt)
domain_auto_trans(shell, propertyoperation_dt_exec, propertyoperation_dt)
set_prop(propertyoperation_dt, vendor_my_work_prop);
set_prop(propertyoperation_dt, ctl_default_prop);
set_prop(propertyoperation_dt, ctl_start_prop);
set_prop(propertyoperation_dt, ctl_stop_prop);
code复制/vendor/bin/propertyoperation u:object_r:propertyoperation_dt_exec:s0
code复制type vendor_my_work_prop, property_type, vendor_property_type;
code复制vendor.my.work.time u:object_r:vendor_my_work_prop:s0
策略文件的编译和部署流程:
BOARD_SEPOLICY_DIRS += device/hello/propertydemo2/propertyoperationmake selinux_policy -j12验证策略是否生效:
bash复制# 查看二进制文件的SELinux上下文
ls -Z /vendor/bin/propertyoperation
# 在正确上下文中运行程序
runcon u:r:propertyoperation_dt:s0 vendor/bin/propertyoperation
问题1:属性设置权限不足
错误信息:
code复制Unable to set property "vendor.my.work.time" to "8": connection failed; errno=13
解决方案:
python复制type vendor_my_work_prop, property_type, vendor_property_type;
code复制vendor.my.work.time u:object_r:vendor_my_work_prop:s0
python复制set_prop(propertyoperation_dt, vendor_my_work_prop);
问题2:服务控制权限不足
错误信息:
code复制Unable to set property "ctl.start" to "vendor.gatekeeper-1-0"
解决方案:
python复制set_prop(propertyoperation_dt, ctl_default_prop);
set_prop(propertyoperation_dt, ctl_start_prop);
set_prop(propertyoperation_dt, ctl_stop_prop);
bash复制adb shell dmesg | grep avc
bash复制adb shell audit2allow -a
bash复制adb shell getprop vendor.my.work.time
bash复制adb shell setenforce 0 # 宽松模式
adb shell setenforce 1 # 强制模式
属性操作虽然是线程安全的,但在多线程环境中仍需注意:
对于厂商定制开发,建议:
我在实际项目开发中发现,良好的属性命名规范和权限设计可以显著降低后期维护成本。特别是在系统升级时,清晰的属性分类和权限隔离能够避免很多兼容性问题。