Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9e99080c authored by Ruslan Tkhakokhov's avatar Ruslan Tkhakokhov Committed by Android (Google) Code Review
Browse files

Merge changes from topic "overrideable-by-restore"

* changes:
  Add Settings.(System/Secure).putStringOverrideableByRestore
  Add preserveValueInRestore flag to Setting object
parents 8474b608 018f5534
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -126,6 +126,7 @@ package android {
    field @Deprecated public static final String MODIFY_NETWORK_ACCOUNTING = "android.permission.MODIFY_NETWORK_ACCOUNTING";
    field public static final String MODIFY_PARENTAL_CONTROLS = "android.permission.MODIFY_PARENTAL_CONTROLS";
    field public static final String MODIFY_QUIET_MODE = "android.permission.MODIFY_QUIET_MODE";
    field public static final String MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE = "android.permission.MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE";
    field public static final String MOVE_PACKAGE = "android.permission.MOVE_PACKAGE";
    field public static final String NETWORK_AIRPLANE_MODE = "android.permission.NETWORK_AIRPLANE_MODE";
    field public static final String NETWORK_CARRIER_PROVISIONING = "android.permission.NETWORK_CARRIER_PROVISIONING";
@@ -8169,6 +8170,10 @@ package android.provider {
    field public static final int VOLUME_HUSH_VIBRATE = 1; // 0x1
  }
  public static final class Settings.System extends android.provider.Settings.NameValueTable {
    method @RequiresPermission(android.Manifest.permission.MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE) public static boolean putString(@NonNull android.content.ContentResolver, @NonNull String, @Nullable String, boolean);
  }
  public static interface Telephony.CarrierColumns extends android.provider.BaseColumns {
    field @NonNull public static final android.net.Uri CONTENT_URI;
    field public static final String EXPIRATION_TIME = "expiration_time";
+97 −16
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ import java.util.Set;
 * The Settings provider contains global system-level device preferences.
 */
public final class Settings {
    private static final boolean DEFAULT_OVERRIDEABLE_BY_RESTORE = false;
    // Intent actions for Settings
@@ -2149,6 +2150,11 @@ public final class Settings {
     */
    public static final String CALL_METHOD_FLAGS_KEY = "_flags";
    /**
     * @hide - String argument extra to the fast-path call()-based requests
     */
    public static final String CALL_METHOD_OVERRIDEABLE_BY_RESTORE_KEY = "_overrideable_by_restore";
    /** @hide - Private call() method to write to 'system' table */
    public static final String CALL_METHOD_PUT_SYSTEM = "PUT_system";
@@ -2517,7 +2523,8 @@ public final class Settings {
        }
        public boolean putStringForUser(ContentResolver cr, String name, String value,
                String tag, boolean makeDefault, final int userHandle) {
                String tag, boolean makeDefault, final int userHandle,
                boolean overrideableByRestore) {
            try {
                Bundle arg = new Bundle();
                arg.putString(Settings.NameValueTable.VALUE, value);
@@ -2528,6 +2535,9 @@ public final class Settings {
                if (makeDefault) {
                    arg.putBoolean(CALL_METHOD_MAKE_DEFAULT_KEY, true);
                }
                if (overrideableByRestore) {
                    arg.putBoolean(CALL_METHOD_OVERRIDEABLE_BY_RESTORE_KEY, true);
                }
                IContentProvider cp = mProviderHolder.getProvider(cr);
                cp.call(cr.getPackageName(), cr.getFeatureId(),
                        mProviderHolder.mUri.getAuthority(), mCallSetCommand, name, arg);
@@ -3078,10 +3088,36 @@ public final class Settings {
            return putStringForUser(resolver, name, value, resolver.getUserId());
        }
        /**
         * Store a name/value pair into the database. Values written by this method will be
         * overridden if a restore happens in the future.
         *
         * @param resolver to access the database with
         * @param name to store
         * @param value to associate with the name
         *
         * @return true if the value was set, false on database errors
         *
         * @hide
         */
        @RequiresPermission(Manifest.permission.MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE)
        @SystemApi
        public static boolean putString(@NonNull ContentResolver resolver,
                @NonNull String name, @Nullable String value, boolean overrideableByRestore) {
            return putStringForUser(resolver, name, value, resolver.getUserId(),
                   overrideableByRestore);
        }
        /** @hide */
        @UnsupportedAppUsage
        public static boolean putStringForUser(ContentResolver resolver, String name, String value,
                int userHandle) {
            return putStringForUser(resolver, name, value, userHandle,
                    DEFAULT_OVERRIDEABLE_BY_RESTORE);
        }
        private static boolean putStringForUser(ContentResolver resolver, String name, String value,
                int userHandle, boolean overrideableByRestore) {
            if (MOVED_TO_SECURE.contains(name)) {
                Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System"
                        + " to android.provider.Settings.Secure, value is unchanged.");
@@ -3092,7 +3128,8 @@ public final class Settings {
                        + " to android.provider.Settings.Global, value is unchanged.");
                return false;
            }
            return sNameValueCache.putStringForUser(resolver, name, value, null, false, userHandle);
            return sNameValueCache.putStringForUser(resolver, name, value, null, false, userHandle,
                    overrideableByRestore);
        }
        /**
@@ -3416,7 +3453,7 @@ public final class Settings {
                    // need to store the adjusted configuration as the initial settings.
                    Settings.System.putStringForUser(
                            cr, SYSTEM_LOCALES, outConfig.getLocales().toLanguageTags(),
                            userHandle);
                            userHandle, DEFAULT_OVERRIDEABLE_BY_RESTORE);
                }
            }
        }
@@ -3449,7 +3486,8 @@ public final class Settings {
                int userHandle) {
            return Settings.System.putFloatForUser(cr, FONT_SCALE, config.fontScale, userHandle) &&
                    Settings.System.putStringForUser(
                            cr, SYSTEM_LOCALES, config.getLocales().toLanguageTags(), userHandle);
                            cr, SYSTEM_LOCALES, config.getLocales().toLanguageTags(), userHandle,
                            DEFAULT_OVERRIDEABLE_BY_RESTORE);
        }
        /** @hide */
@@ -5250,6 +5288,24 @@ public final class Settings {
            return sNameValueCache.getStringForUser(resolver, name, userHandle);
        }
        /**
         * Store a name/value pair into the database. Values written by this method will be
         * overridden if a restore happens in the future.
         *
         * @param resolver to access the database with
         * @param name to store
         * @param value to associate with the name
         * @return true if the value was set, false on database errors
         *
         * @hide
         */
        @RequiresPermission(Manifest.permission.MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE)
        public static boolean putString(ContentResolver resolver, String name,
                String value, boolean overrideableByRestore) {
            return putStringForUser(resolver, name, value, /* tag */ null, /* makeDefault */ false,
                    resolver.getUserId(), overrideableByRestore);
        }
        /**
         * Store a name/value pair into the database.
         * @param resolver to access the database with
@@ -5265,22 +5321,23 @@ public final class Settings {
        @UnsupportedAppUsage
        public static boolean putStringForUser(ContentResolver resolver, String name, String value,
                int userHandle) {
            return putStringForUser(resolver, name, value, null, false, userHandle);
            return putStringForUser(resolver, name, value, null, false, userHandle,
                    DEFAULT_OVERRIDEABLE_BY_RESTORE);
        }
        /** @hide */
        @UnsupportedAppUsage
        public static boolean putStringForUser(@NonNull ContentResolver resolver,
                @NonNull String name, @Nullable String value, @Nullable String tag,
                boolean makeDefault, @UserIdInt int userHandle) {
                boolean makeDefault, @UserIdInt int userHandle, boolean overrideableByRestore) {
            if (MOVED_TO_GLOBAL.contains(name)) {
                Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.Secure"
                        + " to android.provider.Settings.Global");
                return Global.putStringForUser(resolver, name, value,
                        tag, makeDefault, userHandle);
                        tag, makeDefault, userHandle, DEFAULT_OVERRIDEABLE_BY_RESTORE);
            }
            return sNameValueCache.putStringForUser(resolver, name, value, tag,
                    makeDefault, userHandle);
                    makeDefault, userHandle, overrideableByRestore);
        }
        /**
@@ -5329,7 +5386,7 @@ public final class Settings {
                @NonNull String name, @Nullable String value, @Nullable String tag,
                boolean makeDefault) {
            return putStringForUser(resolver, name, value, tag, makeDefault,
                    resolver.getUserId());
                    resolver.getUserId(), DEFAULT_OVERRIDEABLE_BY_RESTORE);
        }
        /**
@@ -12940,7 +12997,29 @@ public final class Settings {
         */
        public static boolean putString(ContentResolver resolver,
                String name, String value) {
            return putStringForUser(resolver, name, value, null, false, resolver.getUserId());
            return putStringForUser(resolver, name, value, null, false, resolver.getUserId(),
                    DEFAULT_OVERRIDEABLE_BY_RESTORE);
        }
        /**
         * Store a name/value pair into the database.
         *
         * @param resolver to access the database with
         * @param name to store
         * @param value to associate with the name
         * @param tag to associated with the setting.
         * @param makeDefault whether to make the value the default one.
         * @param overrideableByRestore whether restore can override this value
         * @return true if the value was set, false on database errors
         *
         * @hide
         */
        @RequiresPermission(Manifest.permission.MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE)
        public static boolean putString(@NonNull ContentResolver resolver,
                @NonNull String name, @Nullable String value, @Nullable String tag,
                boolean makeDefault, boolean overrideableByRestore) {
            return putStringForUser(resolver, name, value, tag, makeDefault,
                    resolver.getUserId(), overrideableByRestore);
        }
        /**
@@ -12989,7 +13068,7 @@ public final class Settings {
                @NonNull String name, @Nullable String value, @Nullable String tag,
                boolean makeDefault) {
            return putStringForUser(resolver, name, value, tag, makeDefault,
                    resolver.getUserId());
                    resolver.getUserId(), DEFAULT_OVERRIDEABLE_BY_RESTORE);
        }
        /**
@@ -13051,13 +13130,14 @@ public final class Settings {
        @UnsupportedAppUsage
        public static boolean putStringForUser(ContentResolver resolver,
                String name, String value, int userHandle) {
            return putStringForUser(resolver, name, value, null, false, userHandle);
            return putStringForUser(resolver, name, value, null, false, userHandle,
                    DEFAULT_OVERRIDEABLE_BY_RESTORE);
        }
        /** @hide */
        public static boolean putStringForUser(@NonNull ContentResolver resolver,
                @NonNull String name, @Nullable String value, @Nullable String tag,
                boolean makeDefault, @UserIdInt int userHandle) {
                boolean makeDefault, @UserIdInt int userHandle, boolean overrideableByRestore) {
            if (LOCAL_LOGV) {
                Log.v(TAG, "Global.putString(name=" + name + ", value=" + value
                        + " for " + userHandle);
@@ -13067,10 +13147,10 @@ public final class Settings {
                Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.Global"
                        + " to android.provider.Settings.Secure, value is unchanged.");
                return Secure.putStringForUser(resolver, name, value, tag,
                        makeDefault, userHandle);
                        makeDefault, userHandle, overrideableByRestore);
            }
            return sNameValueCache.putStringForUser(resolver, name, value, tag,
                    makeDefault, userHandle);
                    makeDefault, userHandle, overrideableByRestore);
        }
        /**
@@ -13937,7 +14017,8 @@ public final class Settings {
        static boolean putString(@NonNull ContentResolver resolver, @NonNull String namespace,
                @NonNull String name, @Nullable String value, boolean makeDefault) {
            return sNameValueCache.putStringForUser(resolver, createCompositeName(namespace, name),
                    value, null, makeDefault, resolver.getUserId());
                    value, null, makeDefault, resolver.getUserId(),
                    DEFAULT_OVERRIDEABLE_BY_RESTORE);
        }
        /**
+7 −0
Original line number Diff line number Diff line
@@ -3980,6 +3980,13 @@
    <permission android:name="android.permission.BACKUP"
        android:protectionLevel="signature|privileged" />

    <!-- @SystemApi Allows an application to make modifications to device settings such that these
         modifications will be overridden by settings restore..
    <p>Not for use by third-party applications.
         @hide -->
    <permission android:name="android.permission.MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE"
                android:protectionLevel="signature|setup" />

    <!-- @SystemApi Allows application to manage
         {@link android.security.keystore.recovery.RecoveryController}.
         <p>Not for use by third-party applications.
+148 −93

File changed.

Preview size limit exceeded, changes collapsed.

+64 −14
Original line number Diff line number Diff line
@@ -117,6 +117,8 @@ final class SettingsState {
    private static final String ATTR_NAMESPACE = "namespace";
    private static final String ATTR_BANNED_HASH = "bannedHash";

    private static final String ATTR_PRESERVE_IN_RESTORE = "preserve_in_restore";

    /**
     * Non-binary value will be written in this attributes.
     */
@@ -386,17 +388,27 @@ final class SettingsState {
        }
    }

    // The settings provider must hold its lock when calling here.
    @GuardedBy("mLock")
    public boolean insertSettingOverrideableByRestoreLocked(String name, String value, String tag,
            boolean makeDefault, String packageName) {
        return insertSettingLocked(name, value, tag, makeDefault, false, packageName,
                /* overrideableByRestore */ true);
    }

    // The settings provider must hold its lock when calling here.
    @GuardedBy("mLock")
    public boolean insertSettingLocked(String name, String value, String tag,
            boolean makeDefault, String packageName) {
        return insertSettingLocked(name, value, tag, makeDefault, false, packageName);
        return insertSettingLocked(name, value, tag, makeDefault, false, packageName,
                /* overrideableByRestore */ false);
    }

    // The settings provider must hold its lock when calling here.
    @GuardedBy("mLock")
    public boolean insertSettingLocked(String name, String value, String tag,
            boolean makeDefault, boolean forceNonSystemPackage, String packageName) {
            boolean makeDefault, boolean forceNonSystemPackage, String packageName,
            boolean overrideableByRestore) {
        if (TextUtils.isEmpty(name)) {
            return false;
        }
@@ -407,7 +419,8 @@ final class SettingsState {
        Setting newState;

        if (oldState != null) {
            if (!oldState.update(value, makeDefault, packageName, tag, forceNonSystemPackage)) {
            if (!oldState.update(value, makeDefault, packageName, tag, forceNonSystemPackage,
                    overrideableByRestore)) {
                return false;
            }
            newState = oldState;
@@ -495,7 +508,8 @@ final class SettingsState {
                changedKeys.add(key); // key was added
            } else if (state.value != value) {
                oldValue = state.value;
                state.update(value, false, packageName, null, true);
                state.update(value, false, packageName, null, true,
                        /* overrideableByRestore */ false);
                changedKeys.add(key); // key was updated
            } else {
                // this key/value already exists, no change and no logging necessary
@@ -797,7 +811,8 @@ final class SettingsState {

                    writeSingleSetting(mVersion, serializer, setting.getId(), setting.getName(),
                            setting.getValue(), setting.getDefaultValue(), setting.getPackageName(),
                            setting.getTag(), setting.isDefaultFromSystem());
                            setting.getTag(), setting.isDefaultFromSystem(),
                            setting.isValuePreservedInRestore());

                    if (DEBUG_PERSISTENCE) {
                        Slog.i(LOG_TAG, "[PERSISTED]" + setting.getName() + "="
@@ -886,7 +901,8 @@ final class SettingsState {

    static void writeSingleSetting(int version, XmlSerializer serializer, String id,
            String name, String value, String defaultValue, String packageName,
            String tag, boolean defaultSysSet) throws IOException {
            String tag, boolean defaultSysSet, boolean isValuePreservedInRestore)
            throws IOException {
        if (id == null || isBinary(id) || name == null || isBinary(name)
                || packageName == null || isBinary(packageName)) {
            // This shouldn't happen.
@@ -905,6 +921,9 @@ final class SettingsState {
            setValueAttribute(ATTR_TAG, ATTR_TAG_BASE64,
                    version, serializer, tag);
        }
        if (isValuePreservedInRestore) {
            serializer.attribute(null, ATTR_PRESERVE_IN_RESTORE, Boolean.toString(true));
        }
        serializer.endTag(null, TAG_SETTING);
    }

@@ -1041,6 +1060,10 @@ final class SettingsState {
                String packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
                String defaultValue = getValueAttribute(parser, ATTR_DEFAULT_VALUE,
                        ATTR_DEFAULT_VALUE_BASE64);
                String isPreservedInRestoreString = parser.getAttributeValue(null,
                        ATTR_PRESERVE_IN_RESTORE);
                boolean isPreservedInRestore = isPreservedInRestoreString != null
                        && Boolean.parseBoolean(isPreservedInRestoreString);
                String tag = null;
                boolean fromSystem = false;
                if (defaultValue != null) {
@@ -1049,7 +1072,7 @@ final class SettingsState {
                    tag = getValueAttribute(parser, ATTR_TAG, ATTR_TAG_BASE64);
                }
                mSettings.put(name, new Setting(name, value, defaultValue, packageName, tag,
                        fromSystem, id));
                        fromSystem, id, isPreservedInRestore));

                if (DEBUG_PERSISTENCE) {
                    Slog.i(LOG_TAG, "[RESTORED] " + name + "=" + value);
@@ -1133,6 +1156,8 @@ final class SettingsState {
        private String tag;
        // Whether the default is set by the system
        private boolean defaultFromSystem;
        // Whether the value of this setting will be preserved when restore happens.
        private boolean isValuePreservedInRestore;

        public Setting(Setting other) {
            name = other.name;
@@ -1142,25 +1167,38 @@ final class SettingsState {
            id = other.id;
            defaultFromSystem = other.defaultFromSystem;
            tag = other.tag;
            isValuePreservedInRestore = other.isValuePreservedInRestore;
        }

        public Setting(String name, String value, boolean makeDefault, String packageName,
                String tag) {
            this.name = name;
            update(value, makeDefault, packageName, tag, false);
            // overrideableByRestore = true as the first initialization isn't considered a
            // modification.
            update(value, makeDefault, packageName, tag, false,
                    /* overrideableByRestore */ true);
        }

        public Setting(String name, String value, String defaultValue,
                String packageName, String tag, boolean fromSystem, String id) {
            this(name, value, defaultValue, packageName, tag, fromSystem, id,
                    /* isOverrideableByRestore */ false);
        }

        Setting(String name, String value, String defaultValue,
                String packageName, String tag, boolean fromSystem, String id,
                boolean isValuePreservedInRestore) {
            mNextId = Math.max(mNextId, Long.parseLong(id) + 1);
            if (NULL_VALUE.equals(value)) {
                value = null;
            }
            init(name, value, tag, defaultValue, packageName, fromSystem, id);
            init(name, value, tag, defaultValue, packageName, fromSystem, id,
                    isValuePreservedInRestore);
        }

        private void init(String name, String value, String tag, String defaultValue,
                String packageName, boolean fromSystem, String id) {
                String packageName, boolean fromSystem, String id,
                boolean isValuePreservedInRestore) {
            this.name = name;
            this.value = value;
            this.tag = tag;
@@ -1168,6 +1206,7 @@ final class SettingsState {
            this.packageName = packageName;
            this.id = id;
            this.defaultFromSystem = fromSystem;
            this.isValuePreservedInRestore = isValuePreservedInRestore;
        }

        public String getName() {
@@ -1198,6 +1237,10 @@ final class SettingsState {
            return defaultFromSystem;
        }

        public boolean isValuePreservedInRestore() {
            return isValuePreservedInRestore;
        }

        public String getId() {
            return id;
        }
@@ -1208,7 +1251,9 @@ final class SettingsState {

        /** @return whether the value changed */
        public boolean reset() {
            return update(this.defaultValue, false, packageName, null, true);
            // overrideableByRestore = true as resetting to default value isn't considered a
            // modification.
            return update(this.defaultValue, false, packageName, null, true, true);
        }

        public boolean isTransient() {
@@ -1220,7 +1265,7 @@ final class SettingsState {
        }

        public boolean update(String value, boolean setDefault, String packageName, String tag,
                boolean forceNonSystemPackage) {
                boolean forceNonSystemPackage, boolean overrideableByRestore) {
            if (NULL_VALUE.equals(value)) {
                value = null;
            }
@@ -1253,17 +1298,22 @@ final class SettingsState {
                }
            }

            // isValuePreservedInRestore shouldn't change back to false if it has been set to true.
            boolean isPreserved = this.isValuePreservedInRestore || !overrideableByRestore;

            // Is something gonna change?
            if (Objects.equals(value, this.value)
                    && Objects.equals(defaultValue, this.defaultValue)
                    && Objects.equals(packageName, this.packageName)
                    && Objects.equals(tag, this.tag)
                    && defaultFromSystem == this.defaultFromSystem) {
                    && defaultFromSystem == this.defaultFromSystem
                    && isPreserved == this.isValuePreservedInRestore) {
                return false;
            }

            init(name, value, tag, defaultValue, packageName, defaultFromSystem,
                    String.valueOf(mNextId++));
                    String.valueOf(mNextId++), isPreserved);

            return true;
        }

Loading