安卓M-SettingsProvider新功能特性总结

来源:互联网 发布:信号屏蔽软件 编辑:程序博客网 时间:2024/06/07 21:34

1、 System表,合法设定值校验。

外部三方应用可随意设定值,不安全,新版本在Settings.java中增加了Validator。
检查时机:在SettingsProvider中,在做insert动作前:

private void validateSystemSettingValue(String name, String value) {        Settings.System.Validator validator = Settings.System.VALIDATORS.get(name);        if (validator != null && !validator.validate(value)) {            throw new IllegalArgumentException("Invalid value: " + value                    + " for setting: " + name);        }    }

2、 允许用户进行权限限制

在系统设置—应用—配置应用—修改系统设置,提供页面,供用户设定那些应用可以操作SettingsProvider数据库。
例如:之前的版本允许三方应用对屏幕休眠时间设定非法数值.像:起点读书.
启动页面:adb shell am start –a “android.settings.action.MANAGE_WRITE_SETTINGS”
涉及权限:

private static final String PM_WRITE_SETTINGS = Manifest.permission.WRITE_SETTINGS;private static final String PM_CHANGE_NETWORK_STATE = Manifest.permission.CHANGE_NETWORK_STATE;ps:CHANGE_NETWORK_STATE is now merged with WRITE_SETTINGS

3、 根据应用对SettinsProvider写入数据进行限制。

针对PackageName,对进程使用的SettingsProvider数据进行限定.{android}包名对用的进程除外.
针对每个应用,可允许设定的数据总大小依次是:
【System】限制20000,【Global】、【Secure】无限制。

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

4、 在数据库升级中使用UpdateController替代onUpgrade方法:

用户的手机在每次升级,是不能全清数据的,安卓M以前的版本,依赖onUpgrade,在安卓M中,依赖UpdateController.

UpgradeController upgrader = new UpgradeController(userId);upgrader.upgradeIfNeededLocked();

5、 涉及多用户的表:

多用户相关:【Secure】、【Global】.【System】数据表不涉及多用户.

private void notifyForSettingsChange(int key, String name) {            // Update the system property *first*, so if someone is listening for            // a notification and then using the contract class to get their data,            // the system property will be updated and they'll get the new data.            boolean backedUpDataChanged = false;            mHandler.obtainMessage(MyHandler.MSG_NOTIFY_URI_CHANGED,                    userId, 0, uri).sendToTarget();            if (isSecureSettingsKey(key)) {                maybeNotifyProfiles(userId, uri, name, sSecureCloneToManagedSettings);            } else if (isSystemSettingsKey(key)) {                maybeNotifyProfiles(userId, uri, name, sSystemCloneToManagedSettings);            }        }

6、 关于SettingsState。

每个数据表对应一个SettingsState,其中保存了SettingsProvider每张表的数据Tag常量、缓冲区mSettings。
Ps:该缓冲区,所有进程共享。

7、 关于Settings

Settings.java编译在framework.jar中,即运行在调用方进程中。
其中有个缓存区:

HashMap<String, String> mValues = new HashMap<String, String>();

Ps:该缓存区每个进程独自享有,且每个进程的缓存区内容都不同。

8、 关于双缓冲

1、 写操作
通过Settings.java跨进程调用SettingsProvder
获取SettingsState
调用insert方法。
2、 读操作
通过Settings.java 的Settings.System.getInt,getString等接口调用
缓存区是否dirty,dirty则清缓存。
如果缓存可用,则从缓存中读取数据返回。
发起ContentProvider安卓标准query请求。

9、 关于写入

大批量、多次的Settings.System.putInt请求,不会立即写入,会间隔2000毫秒。
写入通过后台进程来完成。

private final class MyHandler extends Handler {        public static final int MSG_PERSIST_SETTINGS = 1;        public MyHandler() {            super(BackgroundThread.getHandler().getLooper());        }        @Override        public void handleMessage(Message message) {            switch (message.what) {                case MSG_PERSIST_SETTINGS: {                    Runnable callback = (Runnable) message.obj;                    doWriteState();                    if (callback != null) {                        callback.run();                    }                }                break;            }        }}

10、 关于写入位置

一般情况下是/data/system/user/0/,其中{0}代表多用户的id.

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);            }        }
1 0
原创粉丝点击