SettingProvider工作原理

2023-05-16

1. 基本介绍

SettingsProvider是一个提供设置数据共享的Provider,可以简单理解为数据库, 它包含全局性、系统级别的用户编好设置,例如在手机中的Settings应用,用户可以在Settings里面做很多设备的设置,这些用户偏好的设置很多就保存在SettingsProvider中。例如,飞行模式。

    1. SettingProvider作用及跟其他存储属性机制的区别
      1. SettingProvider作用

SettingProvider最主要的作用是提供跨进程数据访问,给应用之间数据共享提供便利。SettingsProvider是系统设置的内容提供者。SettingsProvider继承ContentProvider,ContentProvider在android中主要扮演着数据共享的角色。

在M(Android5.0)版本之前,SettingsProvider中系统设置是存储在settings.db数据库中;但是在L(Android6.0)之后,SettingsProvider中系统设置改为由xml存储在data分区。

主要源码:SettingsProvider的代码主要包含如下的java文件:

frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java

frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java

frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java

frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java

frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java

frameworks/base/core/java/android/provider/Settings.java

1.1.2 SettingsProvider和Android系统其它Provider的不同之处

  • SettingsProvider只接受int、float、string等基本类型的数据;
  • SettingsProvider由Android系统framework进行了封装,使用更加快捷方便
  • SettingsProvider的数据由键值对组成

1.1.3 SettingsProvider和SystemProperties的不同之处

SettingsProvider有点类似Android的properties系统(Android属性系统):SystemProperties。SystemProperties除具有SettingsProvider以上的三个特性,SettingsProvider和SystemProperties的不同点在于:

  • 数据保存方式不同

SystemProperties的数据保存属性文件中(/system/build.prop等),开机后会被加载到system properties store;SettingsProvider的数据保存在文件/data/system/users/0/settings_***.xml和数据库settings.db中;

  • 作用范围不同

SystemProperties可以实现跨进程、跨层次调用,即底层的c/c++可以调用,java层也可以调用;SettingProvider只能能在java层(APP)使用;

  • 公开程度不同

SettingProvider有部分功能上层第三方APP可以使用,SystemProperties上层第三方APP不可以使用。

1.2 数据分类

1.2.1 三种数据类型

SettingsProvider对数据进行了分类,分别是Global、System、Secure三种类型,它们的区别如下:

  • Global:所有的偏好设置对系统的所有用户公开,第三方APP有读没有写的权限;
  • System:包含各种各样的用户偏好系统设置;
  • Secure:安全性的用户偏好系统设置,第三方APP有读没有写的权限

每种类型具体保存的偏好设置可以在设备如下的目录文件中查看详细的信息:

/data/system/users/0/settings_global.xml

/data/system/users/0/settings_system.xml

/data/system/users/0/settings_secure.xml

1.2.2 三张表的生成过程

在SettingsProvider初始化的过程中生成三张表, frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java文件主要的代码getSettingsFile()方法获取到一个File对象的实例。

对Global、System、Secure分别生成一个File对象实例,它们的File对象分别对应的文件是:

  • 在Android R的代码中,会有生成settings_config.xml文件相关的代码,但是在实际的设备中并没有该文件的存在。
  • /data/system/users/0/settings_global.xml
  • /data/system/users/0/settings_system.xml
  • /data/system/users/0/settings_secure.xml
  • 在8.0以后,每位使用者所安装的每个 APP (package) 都会产生一组独立的 ID (SSAID),并将描述档案放置 “/data/system/users/0/settings_ssaid.xml"。

2. 启动流程

2.1 SettingProvider进程启动流程如下:

SystemServer开始运行时,先启动系统关键Server,例如AvtivityManagerService,最后启动otherService,这是会调用AMS中installSystemProvider方法,安装系统级别的provider,SettingProvider就是其中一个。

Provider启动后,处理SettingsProvider安装之前某些依赖救援程序相关逻辑。最终通过调用ActivityThread#installSystemProviders会调用到SettingProvider的onCreate函数,和打开一个Activity类似,会回调ContentProvider的生命周期方法

2.2 SettingProvider初始化流程

初始化流程主要包括如下三点:

1.在初始化中,如果发现xml文件不存在,那就需要将数据从数据库中迁移到xml,如果xml已经存在了,那就不用做迁移了。数据迁移方法migrateAllLegacySettingsIfNeeded(),该处理只有在设备第一次开机xml文件不存在时候才会做迁移,将数据库总的数据都迁移到xml文件中来。

2.设置广播监听用户id的停止和移除,应用的删除,以便及时更新xml中的数据。startWatchingUserRestrictionChanges()方法。

3.监听部分用户相关设置的变更。

三份数据global/system/secrue是以SettingsState为数据载体,保存在一个列表中mSettingsStates:

private final SparseArray<SettingsState> mSettingsStates = new SparseArray<>();

而SettingsState中的数据又是以内部类Setting为载体,保存在列表mSettings中

private final ArrayMap<String, Setting> mSettings = new ArrayMap<>();

同步数据就是将mSettings中的数据覆写到xml文件中一遍。

3. 操作SettingsProvider

Settings大部分操作的就是SettingsProvider中的数值,也有一些直接操作系统属性的等等。当用户在修改系统设置时,大部分实际上是在修改SettingsProvider中的值。当SettingsProvider数据库中的值被改变时,一些系统服务什么的就会监听到,这时候就会通过jni等当时操作底层,从而达到系统属性或配置改变的效果。如右图所示

由于SetttingsProvider是向整个Android系统提供用户偏好设置的提供程序,在所保存的数据类型和方式上也有一定的规定和约束,为能够保证在整个Android的Java层任意一个地方里面能够方便,快捷的使用SettingsProvider进行数据查询,数据插入,数据更新,所以在framework的provider里面有一个类Settings.java对使用SettingsProvider进行了封装。

SettingsProvider关键数据组织参见上图,在SettingsProvider中持有一个内部类SettingsRegistry的引用m_SettingsRegistry, m_SettingsRegistry通过一个稀疏数组间接持有了系统中所有用户偏好设置数据。稀疏数组m_SettingsStates的value类型是SettingsState类,Key是由偏好类型[Global|System|Secure]和Userid通过计算得出,计算规则在后面给出,SettingsState类的一个实例和上文介绍的某个xml文件关联(内存中的xml文件数据表示)。在SettingsState类中通过ArrayMap持有n个内部类setting的实例,n的值取决于xml文件中item的数量,通过用户偏好设置name可以从mSettings中取出某项具体的用户设置数据。setting类关联到某项具体的用户设置数据。

3.1 查询和插入数据实例

查询数据以查询Device name为例:

从源码packages/apps/Settings中查到设备名称的key为device_name

只需要一行代码即可查询到device_name的值。

mDeviceName = Settings.Global.getString(mContext.getContentResolver(),

                Settings.Global.DEVICE_NAME);

插入数据,以设置Device name为例

也只需要一行代码如下:

private void setSettingsGlobalDeviceName(String deviceName) {

        Settings.Global.putString(mContext.getContentResolver(), Settings.Global.DEVICE_NAME, deviceName);

    }

从以上源码中可以看出查询和插入数据的方法很简单。

深入Settings.java看getString()方法直接调用了getStringForUser()方法:

public static String getStringForUser(ContentResolver resolver, String name, int userHandle) {

……

    return sNameValueCache.getStringForUser(resolver, name, userHandle);

}

在settings.java代码创建了三个静态内部类,System,Secure,Global分别对应SettingsProvider中的System,Secure,Global三种数据类型,Global、Secure、System三个静态内部类会分别持有自己NameValueCache的实例变量,每个NameValueCache持有指向SettingsProvider中的SettingsProvider.java的AIDL远程调用IContentProvider,因此,查询数据需要经过NameValueCache的getStringForUser()方法,插入数据需要经过putStringForUser()方法。同时,NameValueCache还持有一个变量mValues,用于保存查询过的设置项,以便下次再次发起查询时,能够快速返回。

数据的查询过程主要分为如下几点:

1.首先检测用户id是否正确,如果不正确是不能够获取数据的

2.查看mValues中是否已经存在了,存在了就直接将数据返回

3.获取contentprovider

4.如果mCallGetCommand命令不为空,则调用call命令来获取数据,获取到之后将其加入到mValues中,然后返回数据

5.获取命令为空就调用query方法获取数据,将其加入到mValues中,然后返回数据

插入数据的过程:

1.直接调用call方法传入命令和数据

2.修改对应SettingsState中的缓存数据mSettings列表,然后跟新xml文件

3.数据修改成功后contentResolver的notifyChange方法发出数据已被修改通知。

我们在调用android.provider.Settings修改一些设置时,Settings会调用真正的SettingsProvider去访问数据库。

3.2 第三方app使用SettingsProvider

第三方APP可以通过framework的Settings.java查询SettingsProvider中的设置项,3.1节中有具体方法getString()。

第三APP是否可以修改SettingsProvider的设置项?Android系统不允许第三方APP修改SettingsProvider中的设置项。

3.3 权限问题

查询SettingsProvider的设置项不需要声明任何权限。

修改SettingsProvider需要权限:

  1. android.permission.WRITE_SETTINGS,Protection level: signature
  2. Secure数据:android.permission.WRITE_SECURE_SETTINGS,Not for use by third-party applications.
  3. 对于Global和Secure模块,还需要关心上文中的isGlobalOrSecureSettingRestrictedForUser()方法设置到的限制。

4. 常用调试方法

1. 如何修改系统默认的一些设置配置值? 在如下xml文件中修改或添加设置的默认值

frameworks/base/packages/SettingsProvider/res/values/defaults.xml

vendor/mediatek/proprietary/packages/apps/SettingsProvider/res/values/defaults.xml

vendor/mediatek/proprietary/packages/apps/SettingsProvider/res/values/mtk_defaults.xml

注意:在defauls.xml设置的默认值,究竟是会存入settings_global.xml, settings_secure.xml, settings_system.xml 表,是由Settings.java中的class System, Global, Secure 类中管理添加的字段有关,比如MOVED_TO_GLOBAL, MOVED_TO_SECURE

2. 通过ADB修改

settings put system [key] [value] settings get system [key]

settings put global [key] [value] settings get global [key]

settings put secure [key] [value] settings get secure [key]

 3. 代码中如何修改

@Settings.java (frameworks\base\core\java\android\provider)

比如:

Settings.System.putInt(mContext.getContentResolver(), name, value);

int value = Settings.System.getInt(mContext.getContentResolver(), name);

Settings.Global.putInt(...)

Settings.Secure.putInt(...)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SettingProvider工作原理 的相关文章

  • 记InheritedWidget使用思考

    InheritedWidget 是项目中必不可少的组件 xff0c 用户数据共享 老生常谈的Provider框架也是基于InheritedWidget实现的 简介 InheritedWidget组件是功能性组局 xff0c 实现了由上向下共
  • flutter数据共享系列——随记

    Provider InheritedWidget 解决了数据共享问题 迎面也带来数据刷新导致的组件不必要更新问题 Provider基于InheritedWidget实现数据共享 xff0c 数据更新 xff0c 定向通知组件更新等 接下来我
  • Flutter布局——一段代码解释最常见的约束错误

    flutter布局的原理 Constraints go down Sizes go up Parent sets position 父节点向子节点传约束子节点向父节点上传大小最后由父节点决定位置 不是按照直接约束显示 问题代码 xff1a
  • 流媒体压力测试rtmp&hls(含推流和拉流)

    root 64 localhost yum install git unzip patch gcc gcc c 43 43 make root 64 localhost git clone https github com rzrobert
  • Windows开启网络对时方法

    Windows开启网络对时方法 1 启用 NTPServer 为此 xff0c 请按照下列步骤操作 xff1a a 单击 开始 xff0c 单击 运行 xff0c 键入 regedit xff0c 然后单击 确定 进入注册表 b 找到并单击
  • 关于【finder不能完成该操作 因为未能读取或写入"文件名"中的某些数据(错误代码-36)】快速解决办法

    如题 xff1a finder不能完成该操作 因为未能读取或写入 34 文件名 34 中的某些数据 错误代码 36 我们在Mac上操作NTFS格式的硬盘中的文件 xff0c 删除过程中由于某些原因为删除完整 xff0c 直接拔掉硬盘 xff
  • Ubuntu安装指定版本clang-format

    执行以下命令即可 xff1a wget O https apt llvm org llvm snapshot gpg key sudo apt key add sudo vim etc apt sources list 插入从https a
  • Swift中设置tableview的分割线(separator)的样式、颜色、边距

    Swift中设置tableview的分割线 xff08 separator xff09 的样式 颜色 边距 设置分割线样式 三种分割线样式 xff1a case None 无分割线 case SingleLine 单条分割线 case Si
  • React-Native 程序出现闪退原因之一

    React Native 程序出现闪退原因之一 1 RN的iOS端release版本和staging版本出现闪退 原因 xff1a 使用了Number isInteger 该方法在iOS端debug模式下运行不会出现异常 xff0c 一旦生
  • 【Android】【问题分析】G-sensor因数据交互问题导致手机crash

    G sensor因数据交互问题导致手机crash 问题现象 xff1a 测试同事发现 xff0c 手机在使用和待机时 xff0c 低概率发现手机会crash 问题原因 xff1a G sensor在driver和HAL层因交互的参数不匹配
  • 【瓣芽·Banya】React Native 构建的仿豆瓣应用

    今天介绍一个用 React Native 创建的应用 xff0c 集合了豆瓣电影 xff0c 图书等信息展示功能的 app github 地址 瓣芽 Banya 项目使用了react navigation 做路由 redux 做部分状态管理
  • CSS - position

    在 CSS 中 xff0c position 是实现元素定位的一种重要方式 使用定位的元素层叠级别比浮动会更高 xff0c 采用定位来控制元素位置会更加容易 一般我们使用定位 xff0c 是通过使用定位模式和边偏移量来确定元素位置的 定位模
  • React Native 选择器组件 / react-native-slidepicker

    react native slidepicker 一个纯 JavaScript 实现的的 React Native 组件 xff0c 用于如地址 xff0c 时间等分类数据选择的场景 github https github com lexg
  • 函数式组件 ref 的解决方案

    对于 React 中需要强制修改子组件的情况 xff0c React 提供了 Refs 这种解决办法 xff0c 使得我们可以操作底层 DOM 元素或者自定的 class 组件实例 除此之外 xff0c 文档 xff08 v17 0 1 x
  • JavaScript生成指定范围的随机数和随机数序列

    在JavaScript中我们经常使用Math random 方法生成随机数 xff0c 但是该方法生成的随机数只是0 1之间的随机数 先看如下常用方法的特征 xff1a 1 Math random 结果为0 1间的一个随机数 包括0 不包括
  • JavaScript生成指定范围随机数和随机序列

    在JavaScript中我们经常使用Math random 方法生成随机数 xff0c 但是该方法生成的随机数只是0 1之间的随机数 先看如下常用方法的特征 1 Math random 结果为0 1间的一个随机数 包括0 不包括1 2 Ma
  • 【React Native】JavaScript 中 bind 方法

    这个问题其实是一个 JavaScript 中的问题 JavaScript中jQury的bind方法为选定元素添加事件处理程序 xff0c 规定事件发生时运行的函数 语法为 xff1a selector bind event data fun
  • 瑞利信道:从原理到实现

    瑞利信道模型 瑞利信道模型是无线通信信道最重要 最基础的的仿真模型 无线信道中的平坦衰落信道基本上都是在瑞利信道模型的基础上修改而成 xff0c 比如应用同样广泛的莱斯信道就可以通过在瑞利信道的基础上简单的添加直流分量实现 xff0c 而频
  • N个数中的第k个最大值

    确定一组N个数中的第k个最大值 xff0c 这是数据结构和算法分析 java语言描述 中讨论的第一个问题 书中第一章也已给处两种常规思路 xff1a 1 xff0d 先将N个数的数组整体进行递减排序 xff0c 然后返回位置k 数组索引为k
  • 【React Native】app\build\intermediates\res\merged\debug\values-v24\values-v24.xml中错误

    昨天在项目中使用了 react native svg 库 xff0c 配置完成正在正常启动的时候 xff0c 却出现四个错误 xff0c 全部来源于app build intermediates res merged debug value

随机推荐

  • 【React Native】定位获取经纬度,当前城市等地址信息

    2019 8 21 使用内置对象 navigator 来获取经纬度信息 xff0c 参见 定位获取经纬度 xff0c 获取到经纬度等位置信息后需要用到第三方api位置解析 xff08 本文后半段 xff09 2019 7 20更新 xff1
  • 【React Native】定位获取经纬度

    RN 文档上的定位功能需要谷歌框架支持 xff0c 无疑带来了一些麻烦 github 上也有一些开源库 xff0c react native geolocation service等 但是这里还有一个更简便的位置获取 API 使用内置对象n
  • centos7系统下Python2.7升级到Python3.6踩的坑(yum失效,并非简单修改yum文件头)

    centos系统自带的Python2 7用的好好的 xff0c 我非手贱要去升级 xff0c 结果很严重 xff0c 正在运行服务器里面的yum崩了 xff0c 反复尝试了网上提到的几乎完全一致的解决方法 xff1a 将 usr bin y
  • 关于 Android Studio 4.0 创建新的activity和fragment 发现不存在

    1 在 app文件下面的 build gradle里面 注释以下代码
  • RAR文件格式-笔记

    RAR RAR 文件头 52 61 72 21 1A 07 00RAR 文件尾 C4 3D 7B 00 40 07 00 Rar 文件主要由标记块 xff0c 压缩文件头块 xff0c 文件头块 xff0c 结尾块组成 其每一块大致分为以下
  • pptv电话面试

    1 8种基本数据类型 2 String是基本数据类型吗 3 try return 1 catch return 2 finally return3 4 线程池 5 spring实现原理 6 s
  • Linux之systemd服务配置及自动重启

    Linux之systemd服务配置及自动重启 0 背景 在linux上开发时 xff0c 往往需要将自己的程序做成服务 xff0c 并且实现服务开机自动重启 xff0c 以及服务崩溃后自动重启功能 xff0c 本文就对该功能的实现做简单介绍
  • C++中类与对象的关系

    C 43 43 是一门面向对象的编程语言 xff0c 理解C 43 43 xff0c 首先要理解类 xff08 Class xff09 和对象 xff08 Object xff09 这两个概念 C 43 43 中的类 xff08 Class
  • 主定理的证明及应用举例

    主定理 主定理最早出现在 算法导论 中 xff0c 提供了分治方法带来的递归表达式的渐近复杂度分析 规模为n的问题通过分治 xff0c 得到a个规模为n b的问题 xff0c 每次递归带来的额外计算为c n d T n lt 61 aT n
  • Java设计模式 | 观察者模式解析与实战

    概述 观察者模式是一个使用率非常高的模式 xff0c 它最常用的地方是 GUI 系统 订阅 发布系统 这个模式的一个重要作用就是解耦 xff0c 将被观察者和观察者解耦 xff0c 使得它们之间的依赖性更小 xff0c 甚至做到毫无依赖 以
  • blob excel文件导出

    vue 项目中excel文件导出 xff1a exportData 点击方法名称 jjrExport this years then res 61 gt this years为请求参数 console log res const type
  • 知识管理——学习篇

    你的知识需要管理 田志刚 2009年11月 现在 xff0c 根据本书的理念 xff0c 你的使命不仅仅是获取该书的知识 xff08 获取什么 xff1f 他的前瞻性思考判断 xff0c 人家10年前有这种知识管理预见和意识 xff01 作
  • dependencyManagement_前进的火车_新浪博客

    dependencyManagement使用简介 Maven中的dependencyManagement元素提供了一种管理依赖版本号的方式 在dependencyManagement元素中声明所依赖的jar包的版本号等信息 xff0c 那么
  • 【Redis】Redis简介与基本特性

    简介 Redis 全称为 Remote DIctionary Server xff0c 本质上是一个 key value 存储系统 xff0c 属于跨平台的非关系型数据库 Redis 官方对它的定义是 xff1a Redis is an o
  • 【Java 集合类】Collections 类源码分析

    Collections 类源码分析 包路径 xff1a jdk1 8 0 111 rt jar java util Collections java Collections是JDK提供的工具类 xff0c 同样位于java util包中 它
  • 首个Adobe XD教程丨如何用Adobe Experience Design (XD)快速设计图标

    提示 xff1a 阅读本文前建议先从 码农与产品经理看过来 教你用Adobe Xd轻松做原型设计 文章入手 xff0c 会更加学度的掌握此建模神器的精髓http www zoomla cn blog techs 3080 shtml 逐浪小
  • 关于ubuntu下终端打开一闪就退出的一种情况

    终端ctrl 43 alt 43 t后终端一闪即过 首先你换一下访客进入ubuntu查看是否可以打开终端 可以 xff0c 请接着往下看 xff0c 否则抱歉 xff01 首先请你回想一下 xff0c 在这之前你对系统有没有做过什么更改 x
  • 如何转行游戏行业及我眼中的理想游戏开发团队

    前置内容 xff1a 很久没有写文章啦 xff0c 今天就来继续和大家聊一聊关于游戏制作的一些东西 今天主要聊两个方面 xff0c 一个是其他行业转游戏行业的一些注意事项以及需要具备的东西 xff1b 第二是和大家聊一聊我心目中理想的游戏开
  • 浅谈重载new操作符

    new是C 43 43 里非常重要的一个关键词 xff0c 用于申请内存 初始化对象 俗话说 有借有还再借不难 xff0c 通过new向操作系统 借 到的内存用完后必然要 还 回去 xff0c 所以对应地还有一个delete操作符与new共
  • SettingProvider工作原理

    1 基本介绍 SettingsProvider是一个提供设置数据共享的Provider xff0c 可以简单理解为数据库 xff0c 它包含全局性 系统级别的用户编好设置 xff0c 例如在手机中的Settings应用 xff0c 用户可以