
系统设置项(Settings)与系统属性(System Properties)
Android系统的配置管理体系中,系统设置项(Settings) 和系统属性(System Properties) 是两个核心维度:前者面向上层应用与用户交互的持久化配置,后者面向系统底层与原生层的轻量级运行时配置。
二者在设计目标、存储机制、权限控制和Framework层实现上存在本质差异,本文将从源码角度拆解其核心逻辑与区别。
核心定位与设计目标
| 维度 | 系统设置项(Settings) | 系统属性(System Properties) |
|---|---|---|
| 核心目标 | 承载用户/应用可感知的系统配置(如亮度、铃声) | 承载系统底层/原生层的运行时配置(如设备型号、调试开关) |
| 面向对象 | 上层应用、系统APP、普通用户 | init进程、Native服务、系统进程、Root用户 |
| 设计原则 | 持久化、可监听、权限分级 | 轻量、高效、原子性、部分持久化 |
系统设置项(Settings)
1 整体架构
Settings的核心是SettingsProvider(系统级ContentProvider) + SQLite数据库(settings.db) + 上层API封装(android.provider.Settings),整体架构如下:
上层应用 → Settings.java(API) → ContentResolver → SettingsProvider → settings.db
2 存储介质:SQLite数据库(持久化核心)
Settings的所有配置存储在私有数据库settings.db中,路径为:
/data/data/com.android.providers.settings/databases/settings.db
数据库包含3个核心表(源码定义在SettingsProvider中),对应不同权限等级的配置:
global:全局配置(多用户共享),如网络代理、日期格式(Settings.Global);system:用户可修改的系统配置,如屏幕亮度、铃声模式(Settings.System);secure:安全相关配置(仅系统进程可修改),如WiFi密码、指纹设置(Settings.Secure)。
3 Framework层源码实现
(1)上层API入口:android.provider.Settings
源码路径:frameworks/base/core/java/android/provider/Settings.java
该类是上层访问Settings的唯一入口,通过内部静态类Global/System/Secure封装配置项的Key和读写方法,示例如下:
java
// Settings.System中定义屏幕亮度Key
public static final String SCREEN_BRIGHTNESS = "screen_brightness";
// 写操作示例:设置屏幕亮度
public static boolean putInt(ContentResolver resolver, String name, int value) {
return putString(resolver, name, Integer.toString(value));
}
// 读操作示例:获取屏幕亮度
public static int getInt(ContentResolver resolver, String name, int def) {
String v = getString(resolver, name);
return v != null ? Integer.parseInt(v) : def;
}
核心逻辑:读写方法最终通过ContentResolver调用SettingsProvider的CRUD接口,本质是对SQLite数据库的操作。
(2)核心实现:SettingsProvider
源码路径:frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
SettingsProvider是系统级ContentProvider(AndroidManifest中声明android:authorities="settings"),负责处理所有Settings的读写请求,核心流程:
-
数据库初始化 :
onCreate()方法中创建settings.db并初始化默认值(如默认亮度、铃声路径):java@Override public boolean onCreate() { mOpenHelper = new DatabaseHelper(getContext()); mDatabase = mOpenHelper.getWritableDatabase(); // 初始化默认配置 loadSystemSettings(); loadSecureSettings(); loadGlobalSettings(); return true; } -
写操作权限控制 :
update()方法中校验权限(如修改Secure表需WRITE_SECURE_SETTINGS权限,仅系统应用可申请):java@Override public int update(Uri uri, ContentValues values, String where, String[] whereArgs) { // 权限校验:以Secure表为例 if (isSecureUri(uri) && !hasWriteSecureSettingsPermission()) { throw new SecurityException("Need WRITE_SECURE_SETTINGS permission"); } // 执行数据库更新 return mDatabase.update(getTableName(uri), values, where, whereArgs); } -
监听机制 :修改配置后发送
ContentObserver通知,上层应用可监听配置变化:javaprivate void notifyChange(Uri uri) { getContext().getContentResolver().notifyChange(uri, null); }
4 关键特性
- 强持久化:基于SQLite,配置跨重启保留;
- 权限分级 :普通应用可读写
System表(部分),Secure/Global表需系统权限; - 可监听 :支持
ContentObserver实时监听配置变化; - 多用户适配 :
global表共享,system表按用户隔离。
系统属性(System Properties)
1 整体架构
System Properties的核心是Native层(libcutils) + Java层封装(SystemProperties) + init进程属性服务,整体架构如下:
Java层 → SystemProperties.java(JNI) → libcutils(SystemProperties.cpp) → init进程 → 内存/持久化文件
2 存储介质:内存+文件(按需持久化)
System Properties的存储分三类(源码定义在init进程中):
- 普通属性 :存储在
init进程维护的内存哈希表中,重启丢失(如sys.boot_completed); - persist属性 :前缀为
persist.,存储在/data/property/persistent_properties文件中,跨重启保留; - ro属性 :前缀为
ro.(read-only),编译/刷机时写入/system/build.prop,运行时只读,不可修改。
3 Framework层源码实现
(1)Java层封装:android.os.SystemProperties
源码路径:frameworks/base/core/java/android/os/SystemProperties.java
该类是Java层访问System Properties的入口,所有方法通过JNI调用Native层实现,核心代码:
java
// 读操作:获取属性值
public static String get(String key) {
return native_get(key);
}
// 写操作:设置属性值(需系统权限)
public static int set(String key, String value) {
return native_set(key, value);
}
// JNI方法声明
private static native String native_get(String key);
private static native int native_set(String key, String value);
(2)Native层核心:SystemProperties.cpp
源码路径:frameworks/native/libs/utils/SystemProperties.cpp
Native层通过libcutils库提供property_get/property_set接口,核心逻辑是与init进程的属性服务通信(通过/dev/socket/property_service本地socket):
cpp
// 读属性
int property_get(const char* key, char* value, const char* default_value) {
// 调用底层接口,与init进程通信获取属性值
return __system_property_get(key, value) ?: (strcpy(value, default_value), 0);
}
// 写属性
int property_set(const char* key, const char* value) {
// 权限校验(如ro.属性不可写)
if (strncmp(key, "ro.", 3) == 0) {
return -1;
}
// 与init进程通信设置属性值
return __system_property_set(key, value);
}
(3)核心管控:init进程的属性服务
init进程是Android系统的第一个进程,其property_service模块负责维护所有System Properties:
- 源码路径:
system/core/init/property_service.cpp; - 核心逻辑:
- 启动时加载
build.prop/default.prop等文件中的属性到内存; - 监听
/dev/socket/property_servicesocket,处理property_get/property_set请求; - 权限控制:通过
property_contexts配置属性的读写权限(如普通APP不可调用property_set); - persist属性处理:设置
persist.前缀属性时,同步写入/data/property文件。
- 启动时加载
4 关键特性
- 轻量高效:内存级访问,比SQLite快1-2个数量级;
- 权限严格 :普通APP仅可
get部分属性,set需Root/系统进程; - 部分持久化 :仅
persist.前缀属性跨重启保留; - 只读属性 :
ro.前缀属性编译期确定,运行时不可修改; - 无监听机制:原生不支持配置变化监听(需自行轮询)。
核心差异对比
| 维度 | 系统设置项(Settings) | 系统属性(System Properties) |
|---|---|---|
| 存储介质 | SQLite数据库(settings.db) | 内存哈希表 + persist属性到文件(/data/property) + ro属性到build.prop |
| 持久化 | 全量持久化(跨重启) | 仅persist.前缀持久化,其余重启丢失 |
| 访问权限 | 分级:普通APP可读写System表,Secure/Global需系统权限 | 严格:普通APP仅可get部分属性,set需Root/系统进程 |
| API入口 | android.provider.Settings(ContentResolver) |
android.os.SystemProperties(JNI) |
| 监听机制 | 支持ContentObserver实时监听 | 原生不支持,需自行轮询 |
| 生命周期 | 与应用/系统生命周期解耦,永久存储 | 普通属性与init进程生命周期绑定(重启丢失) |
| 性能 | 中等(SQLite磁盘IO) | 极高(内存访问) |
| 命名规范 | 无强制规范,按表分类(Global/System/Secure) | 前缀规范:ro.(只读)、persist.(持久化)、sys.(运行时)、debug.(调试) |
| 典型使用场景 | 屏幕亮度、铃声模式、网络代理、输入法设置 | 设备型号、系统语言(persist.sys.language)、调试开关(debug.debuggerd.enable) |
典型场景
1 系统设置项:修改屏幕亮度
java
// 上层应用调用(需WRITE_SETTINGS权限)
ContentResolver resolver = getContentResolver();
// 1. 设置亮度值
Settings.System.putInt(resolver, Settings.System.SCREEN_BRIGHTNESS, 150);
// 2. 监听亮度变化
resolver.registerContentObserver(
Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS),
false,
new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
// 亮度变化回调
int brightness = Settings.System.getInt(resolver, Settings.System.SCREEN_BRIGHTNESS, 100);
}
}
);
源码流程 :putInt() → ContentResolver.update() → SettingsProvider.update() → 写入settings.db的system表 → 发送ContentObserver通知。
2 系统属性:获取设备型号+设置持久化语言
java
// 1. 获取只读属性(ro.product.model,普通APP可调用)
String model = SystemProperties.get("ro.product.model");
// 2. 设置持久化属性(persist.sys.language,需系统权限)
SystemProperties.set("persist.sys.language", "zh-CN");
源码流程:
get()→ JNI调用native_get()→SystemProperties.cpp的property_get()→ 与init进程通信 → 返回内存中属性值;set()→ JNI调用native_set()→SystemProperties.cpp的property_set()→ init进程校验权限 → 更新内存哈希表 + (persist.前缀)写入/data/property文件。
总结
Android的Settings和System Properties是配置管理体系的"互补双核心":
- Settings 是"上层配置中心",基于SQLite实现持久化、可监听的用户级配置,Framework层通过
SettingsProvider封装权限和数据库操作,适配多用户和应用交互场景; - System Properties 是"底层配置枢纽",基于内存+轻量文件实现高效的系统级配置,Framework层通过JNI封装Native接口,由
init进程统一管控,支撑系统启动、原生服务运行的核心配置。
