【Android FrameWork】第三十四天:系统设置项(Settings)与系统属性(System Properties)

系统设置项(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的读写请求,核心流程:

  1. 数据库初始化onCreate()方法中创建settings.db并初始化默认值(如默认亮度、铃声路径):

    java 复制代码
    @Override
    public boolean onCreate() {
        mOpenHelper = new DatabaseHelper(getContext());
        mDatabase = mOpenHelper.getWritableDatabase();
        // 初始化默认配置
        loadSystemSettings();
        loadSecureSettings();
        loadGlobalSettings();
        return true;
    }
  2. 写操作权限控制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);
    }
  3. 监听机制 :修改配置后发送ContentObserver通知,上层应用可监听配置变化:

    java 复制代码
    private 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进程中):

  1. 普通属性 :存储在init进程维护的内存哈希表中,重启丢失(如sys.boot_completed);
  2. persist属性 :前缀为persist.,存储在/data/property/persistent_properties文件中,跨重启保留;
  3. 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
  • 核心逻辑:
    1. 启动时加载build.prop/default.prop等文件中的属性到内存;
    2. 监听/dev/socket/property_servicesocket,处理property_get/property_set请求;
    3. 权限控制:通过property_contexts配置属性的读写权限(如普通APP不可调用property_set);
    4. 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.dbsystem表 → 发送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.cppproperty_get() → 与init进程通信 → 返回内存中属性值;
  • set() → JNI调用native_set()SystemProperties.cppproperty_set() → init进程校验权限 → 更新内存哈希表 + (persist.前缀)写入/data/property文件。

总结

Android的Settings和System Properties是配置管理体系的"互补双核心":

  • Settings 是"上层配置中心",基于SQLite实现持久化、可监听的用户级配置,Framework层通过SettingsProvider封装权限和数据库操作,适配多用户和应用交互场景;
  • System Properties 是"底层配置枢纽",基于内存+轻量文件实现高效的系统级配置,Framework层通过JNI封装Native接口,由init进程统一管控,支撑系统启动、原生服务运行的核心配置。
相关推荐
未来之窗软件服务2 小时前
幽冥大陆(六十二) 多数据库交叉链接系统Go语言—东方仙盟筑基期
数据库·人工智能·oracle·golang·数据库集群·仙盟创梦ide·东方仙盟
小CC吃豆子2 小时前
JVM-垃圾回收
jvm
没有bug.的程序员2 小时前
负载均衡的真正含义:从算法到架构的深度解析
java·jvm·算法·微服务·架构·负载均衡
Knight_AL3 小时前
一次真实 GC 实验:Parallel 与 G1 在 `Xms < Xmx` 下的日志对比分析
jvm
、BeYourself3 小时前
GridLayoutManager 网格布局与 RecyclerView 拖拽侧滑实战
android·android-studio
Kapaseker3 小时前
如何写出高性能的Java Stream
android·java
tangweiguo030519873 小时前
Android 插件化开发完全指南(Kotlin DSL/Gradle KTS 配置)
android·kotlin
八眼鱼3 小时前
uniappx 安卓拍照,添加水印后比例正常
android
野生风长3 小时前
从零开始的C语言:文件操作与数据管理(下)(fseek,ftell,rewind,文件的编译和链接)
android·java·c语言·开发语言·visual studio