Android M之前SettingProvider数据储存的位置在手机目录/data/data/com.Android.providers.settings/databases下
不过目前的Android版本虽然也有这个目录,其中却没有对应的文件在,本文是看下当前的数据到底存储在哪里。
代码在在frameworks/base/packages/SettingsProvider
插入流程分析
从插入代码为线索分析:
frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.Java
- public Uri insert(Uri uri, ContentValues values) {
- ...
- switch (table) {
- ...
- case TABLE_SYSTEM: {
- if (insertSystemSetting(name, value, UserHandle.getCallingUserId())) {
- return Uri.withAppendedPath(Settings.System.CONTENT_URI, name);
- }
- } break;
- ...
- }
只看system表的插入:
- private boolean insertSystemSetting(String name, String value, int requestingUserId) {
- ...
- return mutateSystemSetting(name, value, requestingUserId, MUTATION_OPERATION_INSERT);
- }
- private boolean mutateSystemSetting(String name, String value, int runAsUserId,
- int operation) {
- ...
- case MUTATION_OPERATION_INSERT: {
- validateSystemSettingValue(name, value);
- return mSettingsRegistry
- .insertSettingLocked(SettingsRegistry.SETTINGS_TYPE_SYSTEM,
- owningUserId, name, value, getCallingPackage());
- }
- ...
- }
SettingsRegistry是内部类
- public boolean insertSettingLocked(int type, int userId, String name, String value,
- ...
- final boolean success = settingsState.insertSettingLocked(name, value, packageName);
- ...
- }
SettingsState是另一个文件
frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
- public boolean insertSettingLocked(String name, String value, String packageName) {
- ...
- updateMemoryUsagePerPackageLocked(packageName, oldValue, value);
- scheduleWriteIfNeededLocked();
- ...
- }
- private void scheduleWriteIfNeededLocked() {
- if (!mDirty) {
- mDirty = true;
- writeStateAsyncLocked();
- }
- }
- private void writeStateAsyncLocked() {
- final long currentTimeMillis = SystemClock.uptimeMillis();
-
- if (mWriteScheduled) {
- mHandler.removeMessages(MyHandler.MSG_PERSIST_SETTINGS);
-
-
- final long timeSinceLastNotWrittenMutationMillis = currentTimeMillis
- - mLastNotWrittenMutationTimeMillis;
- if (timeSinceLastNotWrittenMutationMillis >= MAX_WRITE_SETTINGS_DELAY_MILLIS) {
- mHandler.obtainMessage(MyHandler.MSG_PERSIST_SETTINGS).sendToTarget();
- return;
- }
-
-
- final long maxDelayMillis = Math.max(mLastNotWrittenMutationTimeMillis
- + MAX_WRITE_SETTINGS_DELAY_MILLIS - currentTimeMillis, 0);
- final long writeDelayMillis = Math.min(WRITE_SETTINGS_DELAY_MILLIS, maxDelayMillis);
-
- Message message = mHandler.obtainMessage(MyHandler.MSG_PERSIST_SETTINGS);
- mHandler.sendMessageDelayed(message, writeDelayMillis);
- }
- ...
- }
两条分支,不过最终都是发送了个消息,消息处理中会调用doWriteState
- private void doWriteState() {
- ...
- AtomicFile destination = new AtomicFile(mStatePersistFile);
- ...
- FileOutputStream out = null;
- try {
- out = destination.startWrite();
-
- XmlSerializer serializer = Xml.newSerializer();
- serializer.setOutput(out, StandardCharsets.UTF_8.name());
- serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
- serializer.startDocument(null, true);
- serializer.startTag(null, TAG_SETTINGS);
- serializer.attribute(null, ATTR_VERSION, String.valueOf(version));
-
- final int settingCount = settings.size();
- for (int i = 0; i < settingCount; i++) {
- Setting setting = settings.valueAt(i);
-
- writeSingleSetting(mVersion, serializer, setting.getId(), setting.getName(),
- setting.getValue(), setting.getPackageName());
-
- if (DEBUG_PERSISTENCE) {
- Slog.i(LOG_TAG, "[PERSISTED]" + setting.getName() + "=" + setting.getValue());
- }
- }
-
- serializer.endTag(null, TAG_SETTINGS);
- serializer.endDocument();
- destination.finishWrite(out);
- ...
- }
一看到xml就终于知道,是写到了一个xml文件中,并不是写到sqlite中。
文件地址确认
SettingsState中的成员
- private final File mStatePersistFile;
这个成员是xml的写入文件
在SettingsProvider中
- private void ensureSettingsStateLocked(int key) {
- if (mSettingsStates.get(key) == null) {
- final int maxBytesPerPackage = getMaxBytesPerPackageForType(getTypeFromKey(key));
- SettingsState settingsState = new SettingsState(mLock, getSettingsFile(key), key,
- maxBytesPerPackage);
- mSettingsStates.put(key, settingsState);
- }
- }
这个方法负责SettingsState的初始化
- 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);
- }
- }
从getSettingsFile中可以看到SettingsProvider三个表global,system和secure的文件,它们的路径是相同的,通过Environment.getUserSystemDirectory确立
frameworks/base/core/java/android/os/Environment.java
- public static File getUserSystemDirectory(int userId) {
- return new File(new File(getSystemSecureDirectory(), "users"), Integer.toString(userId));
- }
- public static File getSystemSecureDirectory() {
- if (isEncryptedFilesystemEnabled()) {
- return new File(SECURE_DATA_DIRECTORY, "system");
- } else {
- return new File(DATA_DIRECTORY, "system");
- }
- }
- private static final File DATA_DIRECTORY
- = getDirectory("ANDROID_DATA", "/data");
依据ANDROID_DATA环境变量获取路径,获取不到的话就默认为/data。
获取到DATA_DIRECTORY后,后续还要添加"/ " + "system" + "/" + "users" + "/" + userId的值
例如我测试的手机上是/data/system/users/0,该目录的settings_global.xml,settings_secure.xml和settings_system.xml三个xml文件就是SettingsProvider中的数据文件。