• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.email;
18 
19 import android.content.Context;
20 import android.content.SharedPreferences;
21 import android.text.TextUtils;
22 
23 import com.android.emailcommon.Logging;
24 import com.android.emailcommon.provider.Account;
25 import com.android.mail.utils.LogUtils;
26 
27 import org.json.JSONArray;
28 import org.json.JSONException;
29 
30 import java.util.Collections;
31 import java.util.HashSet;
32 import java.util.Set;
33 import java.util.UUID;
34 
35 public class Preferences {
36 
37     // Preferences file
38     public static final String PREFERENCES_FILE = "AndroidMail.Main";
39 
40     // Preferences field names
41     private static final String ACCOUNT_UUIDS = "accountUuids";
42     private static final String ENABLE_DEBUG_LOGGING = "enableDebugLogging";
43     private static final String ENABLE_EXCHANGE_LOGGING = "enableExchangeLogging";
44     private static final String ENABLE_EXCHANGE_FILE_LOGGING = "enableExchangeFileLogging";
45     private static final String INHIBIT_GRAPHICS_ACCELERATION = "inhibitGraphicsAcceleration";
46     private static final String FORCE_ONE_MINUTE_REFRESH = "forceOneMinuteRefresh";
47     private static final String ENABLE_STRICT_MODE = "enableStrictMode";
48     private static final String DEVICE_UID = "deviceUID";
49     private static final String ONE_TIME_INITIALIZATION_PROGRESS = "oneTimeInitializationProgress";
50     private static final String AUTO_ADVANCE_DIRECTION = "autoAdvance";
51     private static final String TEXT_ZOOM = "textZoom";
52     private static final String BACKGROUND_ATTACHMENTS = "backgroundAttachments";
53     private static final String TRUSTED_SENDERS = "trustedSenders";
54     private static final String LAST_ACCOUNT_USED = "lastAccountUsed";
55     private static final String REQUIRE_MANUAL_SYNC_DIALOG_SHOWN = "requireManualSyncDialogShown";
56     private static final String CONFIRM_DELETE = "confirm_delete";
57     private static final String CONFIRM_SEND = "confirm_send";
58     @Deprecated
59     private static final String SWIPE_DELETE = "swipe_delete";
60     private static final String CONV_LIST_ICON = "conversation_list_icons";
61     @Deprecated
62     private static final String REPLY_ALL = "reply_all";
63 
64     public static final int AUTO_ADVANCE_NEWER = 0;
65     public static final int AUTO_ADVANCE_OLDER = 1;
66     public static final int AUTO_ADVANCE_MESSAGE_LIST = 2;
67     // "move to older" was the behavior on older versions.
68     private static final int AUTO_ADVANCE_DEFAULT = AUTO_ADVANCE_OLDER;
69     private static final boolean CONFIRM_DELETE_DEFAULT = false;
70     private static final boolean CONFIRM_SEND_DEFAULT = false;
71 
72     // The following constants are used as offsets into R.array.general_preference_text_zoom_size.
73     public static final int TEXT_ZOOM_TINY = 0;
74     public static final int TEXT_ZOOM_SMALL = 1;
75     public static final int TEXT_ZOOM_NORMAL = 2;
76     public static final int TEXT_ZOOM_LARGE = 3;
77     public static final int TEXT_ZOOM_HUGE = 4;
78     // "normal" will be the default
79     public static final int TEXT_ZOOM_DEFAULT = TEXT_ZOOM_NORMAL;
80 
81     public static final String CONV_LIST_ICON_SENDER_IMAGE = "senderimage";
82     public static final String CONV_LIST_ICON_NONE = "none";
83     public static final String CONV_LIST_ICON_DEFAULT = CONV_LIST_ICON_SENDER_IMAGE;
84 
85     private static Preferences sPreferences;
86 
87     private final SharedPreferences mSharedPreferences;
88 
Preferences(Context context)89     private Preferences(Context context) {
90         mSharedPreferences = context.getSharedPreferences(PREFERENCES_FILE, Context.MODE_PRIVATE);
91     }
92 
93     /**
94      * TODO need to think about what happens if this gets GCed along with the
95      * Activity that initialized it. Do we lose ability to read Preferences in
96      * further Activities? Maybe this should be stored in the Application
97      * context.
98      */
getPreferences(Context context)99     public static synchronized Preferences getPreferences(Context context) {
100         if (sPreferences == null) {
101             sPreferences = new Preferences(context);
102         }
103         return sPreferences;
104     }
105 
getSharedPreferences(Context context)106     public static SharedPreferences getSharedPreferences(Context context) {
107         return getPreferences(context).mSharedPreferences;
108     }
109 
getLegacyBackupPreference(Context context)110     public static String getLegacyBackupPreference(Context context) {
111         return getPreferences(context).mSharedPreferences.getString(ACCOUNT_UUIDS, null);
112     }
113 
clearLegacyBackupPreference(Context context)114     public static void clearLegacyBackupPreference(Context context) {
115         getPreferences(context).mSharedPreferences.edit().remove(ACCOUNT_UUIDS).apply();
116     }
117 
setEnableDebugLogging(boolean value)118     public void setEnableDebugLogging(boolean value) {
119         mSharedPreferences.edit().putBoolean(ENABLE_DEBUG_LOGGING, value).apply();
120     }
121 
getEnableDebugLogging()122     public boolean getEnableDebugLogging() {
123         return mSharedPreferences.getBoolean(ENABLE_DEBUG_LOGGING, false);
124     }
125 
setEnableExchangeLogging(boolean value)126     public void setEnableExchangeLogging(boolean value) {
127         mSharedPreferences.edit().putBoolean(ENABLE_EXCHANGE_LOGGING, value).apply();
128     }
129 
getEnableExchangeLogging()130     public boolean getEnableExchangeLogging() {
131         return mSharedPreferences.getBoolean(ENABLE_EXCHANGE_LOGGING, false);
132     }
133 
setEnableExchangeFileLogging(boolean value)134     public void setEnableExchangeFileLogging(boolean value) {
135         mSharedPreferences.edit().putBoolean(ENABLE_EXCHANGE_FILE_LOGGING, value).apply();
136     }
137 
getEnableExchangeFileLogging()138     public boolean getEnableExchangeFileLogging() {
139         return mSharedPreferences.getBoolean(ENABLE_EXCHANGE_FILE_LOGGING, false);
140     }
141 
setInhibitGraphicsAcceleration(boolean value)142     public void setInhibitGraphicsAcceleration(boolean value) {
143         mSharedPreferences.edit().putBoolean(INHIBIT_GRAPHICS_ACCELERATION, value).apply();
144     }
145 
getInhibitGraphicsAcceleration()146     public boolean getInhibitGraphicsAcceleration() {
147         return mSharedPreferences.getBoolean(INHIBIT_GRAPHICS_ACCELERATION, false);
148     }
149 
setForceOneMinuteRefresh(boolean value)150     public void setForceOneMinuteRefresh(boolean value) {
151         mSharedPreferences.edit().putBoolean(FORCE_ONE_MINUTE_REFRESH, value).apply();
152     }
153 
getForceOneMinuteRefresh()154     public boolean getForceOneMinuteRefresh() {
155         return mSharedPreferences.getBoolean(FORCE_ONE_MINUTE_REFRESH, false);
156     }
157 
setEnableStrictMode(boolean value)158     public void setEnableStrictMode(boolean value) {
159         mSharedPreferences.edit().putBoolean(ENABLE_STRICT_MODE, value).apply();
160     }
161 
getEnableStrictMode()162     public boolean getEnableStrictMode() {
163         return mSharedPreferences.getBoolean(ENABLE_STRICT_MODE, false);
164     }
165 
166     /**
167      * Generate a new "device UID".  This is local to Email app only, to prevent possibility
168      * of correlation with any other user activities in any other apps.
169      * @return a persistent, unique ID
170      */
getDeviceUID()171     public synchronized String getDeviceUID() {
172          String result = mSharedPreferences.getString(DEVICE_UID, null);
173          if (result == null) {
174              result = UUID.randomUUID().toString();
175              mSharedPreferences.edit().putString(DEVICE_UID, result).apply();
176          }
177          return result;
178     }
179 
getOneTimeInitializationProgress()180     public int getOneTimeInitializationProgress() {
181         return mSharedPreferences.getInt(ONE_TIME_INITIALIZATION_PROGRESS, 0);
182     }
183 
setOneTimeInitializationProgress(int progress)184     public void setOneTimeInitializationProgress(int progress) {
185         mSharedPreferences.edit().putInt(ONE_TIME_INITIALIZATION_PROGRESS, progress).apply();
186     }
187 
getAutoAdvanceDirection()188     public int getAutoAdvanceDirection() {
189         return mSharedPreferences.getInt(AUTO_ADVANCE_DIRECTION, AUTO_ADVANCE_DEFAULT);
190     }
191 
setAutoAdvanceDirection(int direction)192     public void setAutoAdvanceDirection(int direction) {
193         mSharedPreferences.edit().putInt(AUTO_ADVANCE_DIRECTION, direction).apply();
194     }
195 
196     /** @deprecated Only used for migration */
197     @Deprecated
getConversationListIcon()198     public String getConversationListIcon() {
199         return mSharedPreferences.getString(CONV_LIST_ICON, CONV_LIST_ICON_SENDER_IMAGE);
200     }
201 
getConfirmDelete()202     public boolean getConfirmDelete() {
203         return mSharedPreferences.getBoolean(CONFIRM_DELETE, CONFIRM_DELETE_DEFAULT);
204     }
205 
setConfirmDelete(boolean set)206     public void setConfirmDelete(boolean set) {
207         mSharedPreferences.edit().putBoolean(CONFIRM_DELETE, set).apply();
208     }
209 
getConfirmSend()210     public boolean getConfirmSend() {
211         return mSharedPreferences.getBoolean(CONFIRM_SEND, CONFIRM_SEND_DEFAULT);
212     }
213 
setConfirmSend(boolean set)214     public void setConfirmSend(boolean set) {
215         mSharedPreferences.edit().putBoolean(CONFIRM_SEND, set).apply();
216     }
217 
218     /** @deprecated Only used for migration */
219     @Deprecated
hasSwipeDelete()220     public boolean hasSwipeDelete() {
221         return mSharedPreferences.contains(SWIPE_DELETE);
222     }
223 
224     /** @deprecated Only used for migration */
225     @Deprecated
getSwipeDelete()226     public boolean getSwipeDelete() {
227         return mSharedPreferences.getBoolean(SWIPE_DELETE, false);
228     }
229 
230     /** @deprecated Only used for migration */
231     @Deprecated
hasReplyAll()232     public boolean hasReplyAll() {
233         return mSharedPreferences.contains(REPLY_ALL);
234     }
235 
236     /** @deprecated Only used for migration */
237     @Deprecated
getReplyAll()238     public boolean getReplyAll() {
239         return mSharedPreferences.getBoolean(REPLY_ALL, false);
240     }
241 
getTextZoom()242     public int getTextZoom() {
243         return mSharedPreferences.getInt(TEXT_ZOOM, TEXT_ZOOM_DEFAULT);
244     }
245 
setTextZoom(int zoom)246     public void setTextZoom(int zoom) {
247         mSharedPreferences.edit().putInt(TEXT_ZOOM, zoom).apply();
248     }
249 
getBackgroundAttachments()250     public boolean getBackgroundAttachments() {
251         return mSharedPreferences.getBoolean(BACKGROUND_ATTACHMENTS, false);
252     }
253 
setBackgroundAttachments(boolean allowed)254     public void setBackgroundAttachments(boolean allowed) {
255         mSharedPreferences.edit().putBoolean(BACKGROUND_ATTACHMENTS, allowed).apply();
256     }
257 
258     /**
259      * @deprecated This has been moved to {@link com.android.mail.preferences.MailPrefs}, and is only here for migration.
260      */
261     @Deprecated
getWhitelistedSenderAddresses()262     public Set<String> getWhitelistedSenderAddresses() {
263         try {
264             return parseEmailSet(mSharedPreferences.getString(TRUSTED_SENDERS, ""));
265         } catch (JSONException e) {
266             return Collections.emptySet();
267         }
268     }
269 
parseEmailSet(String serialized)270     HashSet<String> parseEmailSet(String serialized) throws JSONException {
271         HashSet<String> result = new HashSet<String>();
272         if (!TextUtils.isEmpty(serialized)) {
273             JSONArray arr = new JSONArray(serialized);
274             for (int i = 0, len = arr.length(); i < len; i++) {
275                 result.add((String) arr.get(i));
276             }
277         }
278         return result;
279     }
280 
packEmailSet(HashSet<String> set)281     String packEmailSet(HashSet<String> set) {
282         return new JSONArray(set).toString();
283     }
284 
285     /**
286      * Returns the last used account ID as set by {@link #setLastUsedAccountId}.
287      * The system makes no attempt to automatically track what is considered a "use" - clients
288      * are expected to call {@link #setLastUsedAccountId} manually.
289      *
290      * Note that the last used account may have been deleted in the background so there is also
291      * no guarantee that the account exists.
292      */
getLastUsedAccountId()293     public long getLastUsedAccountId() {
294         return mSharedPreferences.getLong(LAST_ACCOUNT_USED, Account.NO_ACCOUNT);
295     }
296 
297     /**
298      * Sets the specified ID of the last account used. Treated as an opaque ID and does not
299      * validate the value. Value is saved asynchronously.
300      */
setLastUsedAccountId(long accountId)301     public void setLastUsedAccountId(long accountId) {
302         mSharedPreferences
303                 .edit()
304                 .putLong(LAST_ACCOUNT_USED, accountId)
305                 .apply();
306     }
307 
308     /**
309      * Gets whether the require manual sync dialog has been shown for the specified account.
310      * It should only be shown once per account.
311      */
getHasShownRequireManualSync(Account account)312     public boolean getHasShownRequireManualSync(Account account) {
313         return getBoolean(account.getEmailAddress(), REQUIRE_MANUAL_SYNC_DIALOG_SHOWN, false);
314     }
315 
316     /**
317      * Sets whether the require manual sync dialog has been shown for the specified account.
318      * It should only be shown once per account.
319      */
setHasShownRequireManualSync(Account account, boolean value)320     public void setHasShownRequireManualSync(Account account, boolean value) {
321         setBoolean(account.getEmailAddress(), REQUIRE_MANUAL_SYNC_DIALOG_SHOWN, value);
322     }
323 
324 
325     /**
326      * Get whether to show the manual sync dialog. This dialog is shown when the user is roaming,
327      * connected to a mobile network, the administrator has set the RequireManualSyncWhenRoaming
328      * flag to true, and the dialog has not been shown before for the supplied account.
329      */
shouldShowRequireManualSync(Context context, Account account)330     public boolean shouldShowRequireManualSync(Context context, Account account) {
331         return Account.isAutomaticSyncDisabledByRoaming(context, account.mId)
332                 && !getHasShownRequireManualSync(account);
333     }
334 
clear()335     public void clear() {
336         mSharedPreferences.edit().clear().apply();
337     }
338 
dump()339     public void dump() {
340         if (Logging.LOGD) {
341             for (String key : mSharedPreferences.getAll().keySet()) {
342                 LogUtils.v(Logging.LOG_TAG, key + " = " + mSharedPreferences.getAll().get(key));
343             }
344         }
345     }
346 
347     /**
348      * Utility method for setting a boolean value on a per-account preference.
349      */
setBoolean(String account, String key, Boolean value)350     private void setBoolean(String account, String key, Boolean value) {
351         mSharedPreferences.edit().putBoolean(makeKey(account, key), value).apply();
352     }
353 
354     /**
355      * Utility method for getting a boolean value from a per-account preference.
356      */
getBoolean(String account, String key, boolean def)357     private boolean getBoolean(String account, String key, boolean def) {
358         return mSharedPreferences.getBoolean(makeKey(account, key), def);
359     }
360 
361     /**
362      * Utility method for creating a per account preference key.
363      */
makeKey(String account, String key)364     private static String makeKey(String account, String key) {
365         return account != null ? account + "-" + key : key;
366     }
367 }
368