SettingsProvider数据储存位置

老早之前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是另一个文件

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);

            // 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中的数据文件。

AndroidSettingsProvider是一个系统级应用程序,用于管理设备的设置信息。当Android系统升级时,SettingsProvider也会相应地进行升级。 首先,升级会带来一些新的设置选项。随着Android版本的更新,新的功能和特性将被引入到系统中,这些功能和特性将需要对应的设置选项来进行配置。因此,SettingsProvider需要进行升级,以支持这些新的设置选项。 其次,升级还会修复一些已知的问题和漏洞。在旧版本的SettingsProvider中可能存在一些bug或者安全漏洞,这些问题会被逐步修复和解决。升级后的SettingsProvider将包含修复后的代码,以提高系统的稳定性和安全性。 此外,升级还可能会改变SettingsProvider数据结构或存储方式。为了满足新的需求和功能,SettingsProvider数据存储可能需要进行调整和优化。这可能涉及到数据库表结构的更改或者数据存储的格式改变等。 最后,升级还可能会提供更好的性能和响应速度。随着系统的发展,我们对设备的性能和用户体验的要求也在不断提高。升级后的SettingsProvider可能会经过优化,以提供更快的数据查询和更新速度,从而使用户的设置操作更加流畅和高效。 综上所述,Android系统的升级会带来SettingsProvider的升级,以支持新的设置选项、修复问题和漏洞、改变数据结构和存储方式,并提供更好的性能和响应速度。这些升级将不断提高Android设备的功能和使用体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值