1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.camera.settings;
18
19import android.content.SharedPreferences;
20
21import com.android.camera.debug.Log;
22
23/**
24 * The SettingsUpgrader class can be used to define an upgrade flow that
25 * executes upgrade logic to a target version when a version number has changed.
26 */
27public abstract class SettingsUpgrader {
28    private static final Log.Tag TAG = new Log.Tag("SettingsUpgrader");
29
30    private final String mVersionKey;
31    private final int mTargetVersion;
32
33    // These values were in use by the original preferences management, before
34    // SettingsManager, to represent string-based booleans via typed string
35    // resource arrays. We no longer utilize such value arrays, and reference
36    // these constants only within SettingsUpgraders to convert to new string-
37    // based booleans.
38    protected static final String OLD_SETTINGS_VALUE_NONE = "none";
39    protected static final String OLD_SETTINGS_VALUE_ON = "on";
40    protected static final String OLD_SETTINGS_VALUE_OFF = "off";
41
42    public SettingsUpgrader(String versionKey, int targetVersion) {
43        mVersionKey = versionKey;
44        mTargetVersion = targetVersion;
45    }
46
47    /**
48     * Execute an upgrade callback if an upgrade version has changed. Third
49     * party modules also use this to upgrade settings local to them.
50     */
51    public void upgrade(SettingsManager settingsManager) {
52        int lastVersion = getLastVersion(settingsManager);
53        if (lastVersion != mTargetVersion) {
54            upgrade(settingsManager, lastVersion, mTargetVersion);
55        }
56        settingsManager.set(SettingsManager.SCOPE_GLOBAL, mVersionKey, mTargetVersion);
57    }
58
59    /**
60     * Perform upgrades to bring any settings up to date to the version
61     * specified in currentVersion, where the settings were last upgraded to
62     * lastVersion. Typically an Upgrader will check whether lastVersion is less
63     * than some known version for a particular setting, and apply upgrade logic
64     * if lastVersion is less than that known version.
65     */
66    protected abstract void upgrade(SettingsManager settingsManager, int lastVersion,
67            int targetVersion);
68
69    /**
70     * Retrieve the last persisted version for the particular upgrader.
71     * Typically will be stored in SCOPE_GLOBAL in SettingsManager, but an
72     * Upgrader may need to perform an upgrade analysis on the version
73     * persistence itself and should do so here.
74     *
75     * @throws a {@link ClassCastException} if the value for Version is not a
76     *             String
77     */
78    protected int getLastVersion(SettingsManager settingsManager) {
79        return settingsManager.getInteger(SettingsManager.SCOPE_GLOBAL, mVersionKey);
80    }
81
82    /**
83     * A helper function that is used to remove a setting stored as a boolean,
84     * and return the value that was removed.
85     * <p>
86     * This is used in the upgrade path to change all underlying
87     * SharedPreferences values to Strings. It can be used by third party
88     * modules to upgrade their boolean settings to Strings.
89     */
90    protected boolean removeBoolean(SharedPreferences oldPreferencesLocation, String key) {
91        boolean value = false;
92        try {
93            value = oldPreferencesLocation.getBoolean(key, value);
94        } catch (ClassCastException e) {
95            Log.e(TAG, "error reading old value, removing and returning default", e);
96        }
97        oldPreferencesLocation.edit().remove(key).apply();
98        return value;
99    }
100
101    /**
102     * A helper function that is used to remove a setting stored as an Integer,
103     * and return the value that was removed.
104     * <p>
105     * This is used in the upgrade path to change all underlying
106     * SharedPreferences values to Strings. It can be used by third party
107     * modules to upgrade their Integer settings to Strings.
108     */
109    protected int removeInteger(SharedPreferences oldPreferencesLocation, String key) {
110        int value = 0;
111        try {
112            value = oldPreferencesLocation.getInt(key, value);
113        } catch (ClassCastException e) {
114            Log.e(TAG, "error reading old value, removing and returning default", e);
115        }
116        oldPreferencesLocation.edit().remove(key).apply();
117        return value;
118    }
119
120    /**
121     * A helper function that is used to remove a setting stored as a String,
122     * and return the value that was removed.
123     * <p>
124     * This is used in the upgrade path to change all underlying
125     * SharedPreferences values to Strings. It can be used by third party
126     * modules to upgrade their boolean settings to Strings.
127     */
128    protected String removeString(SharedPreferences oldPreferencesLocation, String key) {
129        String value = null;
130        try {
131            value = oldPreferencesLocation.getString(key, value);
132        } catch (ClassCastException e) {
133            Log.e(TAG, "error reading old value, removing and returning default", e);
134        }
135        oldPreferencesLocation.edit().remove(key).apply();
136        return value;
137    }
138
139}
140