SettingsProvider源码流程解析

本文详细解析了Android系统组件SettingsProvider的源码,包括应用初始化时的数据迁移过程,从数据库迁移到XML文件,并分析了SettingsProvider在用户ID变化时的处理。此外,还介绍了数据的读写流程,通过SettingsRegistry和NameValueCache实现,以及ContentProvider的call方法在数据读取和写入中的作用。文章最后探讨了数据更新时的缓存同步机制。
摘要由CSDN通过智能技术生成
简介:

前阵子遇到个问题,OTA升级之后设置中的默认设置项发生了改变,后来查找发现设置中该设置项是通过读取系统数据库中的数据来决定选项是否开启,所以顺带查看了一下SettingsProvider源码,后来发现问题跟SettingsProvider没关系,但还是抽时间将阅读内容整理记录下来。

模块总览:

该模块主要用于记录一些重要的系统数据,模块代码位于:
\frameworks\base\packages\SettingsProvider
代码不多,就几个java文件,围绕一个SettingsProvider展开,类关系图如下:
在这里插入图片描述
所以manifest文件也十分简洁:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.android.providers.settings"
        coreApp="true"
        android:sharedUserId="android.uid.system">

    <application android:allowClearUserData="false"
                 android:label="@string/app_label"
                 android:process="system"
                 android:backupAgent="SettingsBackupAgent"
                 android:killAfterRestore="false"
                 android:icon="@mipmap/ic_launcher_settings"
                 android:defaultToDeviceProtectedStorage="true"
                 android:directBootAware="true">

        <provider android:name="SettingsProvider"
                  android:authorities="settings"
                  android:multiprocess="false"
                  android:exported="true"
                  android:singleUser="true"
                  android:initOrder="100" />
    </application>
</manifest>

在framework中封装了一个Settings类,提供对SettingsProvider的读写接口。代码路径位于:
frameworks\base\core\java\android\provider\Settings.java

这里主要从以下两点来分析:

  1. 应用的初始化
  2. 数据的读写
1.应用的初始化

SettingsProvider的主要功能大多都在子类SettingsRegistry中实现,以前数据都记录在数据库中,6.0之后就不再使用数据库作为主要存储了,数据主要存储在xml文件中,这些文件路径定义在SettingsRegistry中:

        private static final String SETTINGS_FILE_GLOBAL = "settings_global.xml";
        private static final String SETTINGS_FILE_SYSTEM = "settings_system.xml";
        private static final String SETTINGS_FILE_SECURE = "settings_secure.xml";

文件路径定义为:

        private File getSettingsFile(int key) {
            if (isGlobalSettingsKey(key)) {
                final int userId = getUserIdFromKey(key);
                return new File(Environment.getUserSystemDirectory(userId),
                        SETTINGS_FILE_GLOBAL);
            } else if (isSystemSettingsKey(key)) {
                final int userId = getUserIdFromKey(key);
                return new File(Environment.getUserSystemDirectory(userId),
                        SETTINGS_FILE_SYSTEM);
            } else if (isSecureSettingsKey(key)) {
                final int userId = getUserIdFromKey(key);
                return new File(Environment.getUserSystemDirectory(userId),
                        SETTINGS_FILE_SECURE);
            } else {
                throw new IllegalArgumentException("Invalid settings key:" + key);
            }
        }

所以就是如下三个文件:

data/system/users/0/settings_global.xml
data/system/users/userid/settings_system.xml
data/system/users/userid/settings_secure.xml

首先来分析SettingsProvider的onCreate方法:

    @Override
    public boolean onCreate() {
        synchronized (mLock) {
            mUserManager = UserManager.get(getContext());
            mPackageManager = AppGlobals.getPackageManager();
            mHandlerThread = new HandlerThread(LOG_TAG,
                    Process.THREAD_PRIORITY_BACKGROUND);
            mHandlerThread.start();
            //初始化SettingsRegistry,会在这里做一次数据迁移
            mSettingsRegistry = new SettingsRegistry();
        }
        //注册广播监听
        registerBroadcastReceivers();
        //这里会监听用户限制相关的一些改变,比如分享位置,安装位置来源应用,使能adb等,然后对相关xml文件做修改
        startWatchingUserRestrictionChanges();
        return true;
    }

SettingsRegistry的初始化如下:

        public SettingsRegistry() {
            mHandler = new MyHandler(getContext().getMainLooper());
      
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值