老早之前SettingProvider数据储存的位置在手机目录/data/data/com.android.providers.settings/databases下
不过目前的Android版本虽然也有这个目录,其中却没有对应的文件在,本文是看下当前的数据到底存储在哪里。
代码在在/home/lgy/code/mtk6797/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是另一个文件
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);
// If enough time passed, write without holding off anymore.
final long timeSinceLastNotWrittenMutationMillis = currentTimeMillis
- mLastNotWrittenMutationTimeMillis;
if (timeSinceLastNotWrittenMutationMillis >= MAX_WRITE_SETTINGS_DELAY_MILLIS) {
mHandler.obtainMessage(MyHandler.MSG_PERSIST_SETTINGS).sendToTarget();
return;
}
// Hold off a bit more as settings are frequently changing.
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中的数据文件。