1/*
2 * Copyright (C) 2008 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.email;
18
19import android.content.Context;
20import android.content.SharedPreferences;
21import android.text.TextUtils;
22
23import com.android.emailcommon.Logging;
24import com.android.emailcommon.provider.Account;
25import com.android.mail.utils.LogUtils;
26
27import org.json.JSONArray;
28import org.json.JSONException;
29
30import java.util.Collections;
31import java.util.HashSet;
32import java.util.Set;
33import java.util.UUID;
34
35public class Preferences {
36
37    // Preferences file
38    public static final String PREFERENCES_FILE = "AndroidMail.Main";
39
40    // Preferences field names
41    @Deprecated
42    private static final String ACCOUNT_UUIDS = "accountUuids";
43    private static final String ENABLE_DEBUG_LOGGING = "enableDebugLogging";
44    private static final String ENABLE_EXCHANGE_LOGGING = "enableExchangeLogging";
45    private static final String ENABLE_EXCHANGE_FILE_LOGGING = "enableExchangeFileLogging";
46    private static final String ENABLE_STRICT_MODE = "enableStrictMode";
47    private static final String DEVICE_UID = "deviceUID";
48    private static final String ONE_TIME_INITIALIZATION_PROGRESS = "oneTimeInitializationProgress";
49    private static final String LAST_ACCOUNT_USED = "lastAccountUsed";
50    // The following are only used for migration
51    @Deprecated
52    private static final String AUTO_ADVANCE_DIRECTION = "autoAdvance";
53    @Deprecated
54    private static final String TRUSTED_SENDERS = "trustedSenders";
55    @Deprecated
56    private static final String CONFIRM_DELETE = "confirm_delete";
57    @Deprecated
58    private static final String CONFIRM_SEND = "confirm_send";
59    @Deprecated
60    private static final String SWIPE_DELETE = "swipe_delete";
61    @Deprecated
62    private static final String CONV_LIST_ICON = "conversation_list_icons";
63    @Deprecated
64    private static final String REPLY_ALL = "reply_all";
65
66    @Deprecated
67    public static final int AUTO_ADVANCE_NEWER = 0;
68    @Deprecated
69    public static final int AUTO_ADVANCE_OLDER = 1;
70    @Deprecated
71    public static final int AUTO_ADVANCE_MESSAGE_LIST = 2;
72    // "move to older" was the behavior on older versions.
73    @Deprecated
74    private static final int AUTO_ADVANCE_DEFAULT = AUTO_ADVANCE_OLDER;
75    @Deprecated
76    private static final boolean CONFIRM_DELETE_DEFAULT = false;
77    @Deprecated
78    private static final boolean CONFIRM_SEND_DEFAULT = false;
79
80    @Deprecated
81    public static final String CONV_LIST_ICON_SENDER_IMAGE = "senderimage";
82    @Deprecated
83    public static final String CONV_LIST_ICON_NONE = "none";
84    @Deprecated
85    public static final String CONV_LIST_ICON_DEFAULT = CONV_LIST_ICON_SENDER_IMAGE;
86
87    private static Preferences sPreferences;
88
89    private final SharedPreferences mSharedPreferences;
90
91    private Preferences(Context context) {
92        mSharedPreferences = context.getSharedPreferences(PREFERENCES_FILE, Context.MODE_PRIVATE);
93    }
94
95    /**
96     * TODO need to think about what happens if this gets GCed along with the
97     * Activity that initialized it. Do we lose ability to read Preferences in
98     * further Activities? Maybe this should be stored in the Application
99     * context.
100     */
101    public static synchronized Preferences getPreferences(Context context) {
102        if (sPreferences == null) {
103            sPreferences = new Preferences(context);
104        }
105        return sPreferences;
106    }
107
108    public static SharedPreferences getSharedPreferences(Context context) {
109        return getPreferences(context).mSharedPreferences;
110    }
111
112    public static String getLegacyBackupPreference(Context context) {
113        return getPreferences(context).mSharedPreferences.getString(ACCOUNT_UUIDS, null);
114    }
115
116    public static void clearLegacyBackupPreference(Context context) {
117        getPreferences(context).mSharedPreferences.edit().remove(ACCOUNT_UUIDS).apply();
118    }
119
120    public void setEnableDebugLogging(boolean value) {
121        mSharedPreferences.edit().putBoolean(ENABLE_DEBUG_LOGGING, value).apply();
122    }
123
124    public boolean getEnableDebugLogging() {
125        return mSharedPreferences.getBoolean(ENABLE_DEBUG_LOGGING, false);
126    }
127
128    public void setEnableExchangeLogging(boolean value) {
129        mSharedPreferences.edit().putBoolean(ENABLE_EXCHANGE_LOGGING, value).apply();
130    }
131
132    public boolean getEnableExchangeLogging() {
133        return mSharedPreferences.getBoolean(ENABLE_EXCHANGE_LOGGING, false);
134    }
135
136    public void setEnableExchangeFileLogging(boolean value) {
137        mSharedPreferences.edit().putBoolean(ENABLE_EXCHANGE_FILE_LOGGING, value).apply();
138    }
139
140    public boolean getEnableExchangeFileLogging() {
141        return mSharedPreferences.getBoolean(ENABLE_EXCHANGE_FILE_LOGGING, false);
142    }
143
144    public void setEnableStrictMode(boolean value) {
145        mSharedPreferences.edit().putBoolean(ENABLE_STRICT_MODE, value).apply();
146    }
147
148    public boolean getEnableStrictMode() {
149        return mSharedPreferences.getBoolean(ENABLE_STRICT_MODE, false);
150    }
151
152    /**
153     * Generate a new "device UID".  This is local to Email app only, to prevent possibility
154     * of correlation with any other user activities in any other apps.
155     * @return a persistent, unique ID
156     */
157    public synchronized String getDeviceUID() {
158         String result = mSharedPreferences.getString(DEVICE_UID, null);
159         if (result == null) {
160             result = UUID.randomUUID().toString();
161             mSharedPreferences.edit().putString(DEVICE_UID, result).apply();
162         }
163         return result;
164    }
165
166    public int getOneTimeInitializationProgress() {
167        return mSharedPreferences.getInt(ONE_TIME_INITIALIZATION_PROGRESS, 0);
168    }
169
170    public void setOneTimeInitializationProgress(int progress) {
171        mSharedPreferences.edit().putInt(ONE_TIME_INITIALIZATION_PROGRESS, progress).apply();
172    }
173
174    /** @deprecated Only used for migration */
175    @Deprecated
176    public int getAutoAdvanceDirection() {
177        return mSharedPreferences.getInt(AUTO_ADVANCE_DIRECTION, AUTO_ADVANCE_DEFAULT);
178    }
179
180    /** @deprecated Only used for migration */
181    @Deprecated
182    public String getConversationListIcon() {
183        return mSharedPreferences.getString(CONV_LIST_ICON, CONV_LIST_ICON_SENDER_IMAGE);
184    }
185
186    /** @deprecated Only used for migration */
187    @Deprecated
188    public boolean getConfirmDelete() {
189        return mSharedPreferences.getBoolean(CONFIRM_DELETE, CONFIRM_DELETE_DEFAULT);
190    }
191
192    /** @deprecated Only used for migration */
193    @Deprecated
194    public boolean getConfirmSend() {
195        return mSharedPreferences.getBoolean(CONFIRM_SEND, CONFIRM_SEND_DEFAULT);
196    }
197
198    /** @deprecated Only used for migration */
199    @Deprecated
200    public boolean hasSwipeDelete() {
201        return mSharedPreferences.contains(SWIPE_DELETE);
202    }
203
204    /** @deprecated Only used for migration */
205    @Deprecated
206    public boolean getSwipeDelete() {
207        return mSharedPreferences.getBoolean(SWIPE_DELETE, false);
208    }
209
210    /** @deprecated Only used for migration */
211    @Deprecated
212    public boolean hasReplyAll() {
213        return mSharedPreferences.contains(REPLY_ALL);
214    }
215
216    /** @deprecated Only used for migration */
217    @Deprecated
218    public boolean getReplyAll() {
219        return mSharedPreferences.getBoolean(REPLY_ALL, false);
220    }
221
222    /**
223     * @deprecated This has been moved to {@link com.android.mail.preferences.MailPrefs}, and is
224     * only here for migration.
225     */
226    @Deprecated
227    public Set<String> getWhitelistedSenderAddresses() {
228        try {
229            return parseEmailSet(mSharedPreferences.getString(TRUSTED_SENDERS, ""));
230        } catch (JSONException e) {
231            return Collections.emptySet();
232        }
233    }
234
235    HashSet<String> parseEmailSet(String serialized) throws JSONException {
236        HashSet<String> result = new HashSet<String>();
237        if (!TextUtils.isEmpty(serialized)) {
238            JSONArray arr = new JSONArray(serialized);
239            for (int i = 0, len = arr.length(); i < len; i++) {
240                result.add((String) arr.get(i));
241            }
242        }
243        return result;
244    }
245
246    /**
247     * Returns the last used account ID as set by {@link #setLastUsedAccountId}.
248     * The system makes no attempt to automatically track what is considered a "use" - clients
249     * are expected to call {@link #setLastUsedAccountId} manually.
250     *
251     * Note that the last used account may have been deleted in the background so there is also
252     * no guarantee that the account exists.
253     */
254    public long getLastUsedAccountId() {
255        return mSharedPreferences.getLong(LAST_ACCOUNT_USED, Account.NO_ACCOUNT);
256    }
257
258    /**
259     * Sets the specified ID of the last account used. Treated as an opaque ID and does not
260     * validate the value. Value is saved asynchronously.
261     */
262    public void setLastUsedAccountId(long accountId) {
263        mSharedPreferences
264                .edit()
265                .putLong(LAST_ACCOUNT_USED, accountId)
266                .apply();
267    }
268
269    public void clear() {
270        mSharedPreferences.edit().clear().apply();
271    }
272
273    public void dump() {
274        if (Logging.LOGD) {
275            for (String key : mSharedPreferences.getAll().keySet()) {
276                LogUtils.v(Logging.LOG_TAG, key + " = " + mSharedPreferences.getAll().get(key));
277            }
278        }
279    }
280}
281