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     @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 
Preferences(Context context)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      */
getPreferences(Context context)101     public static synchronized Preferences getPreferences(Context context) {
102         if (sPreferences == null) {
103             sPreferences = new Preferences(context);
104         }
105         return sPreferences;
106     }
107 
getSharedPreferences(Context context)108     public static SharedPreferences getSharedPreferences(Context context) {
109         return getPreferences(context).mSharedPreferences;
110     }
111 
getLegacyBackupPreference(Context context)112     public static String getLegacyBackupPreference(Context context) {
113         return getPreferences(context).mSharedPreferences.getString(ACCOUNT_UUIDS, null);
114     }
115 
clearLegacyBackupPreference(Context context)116     public static void clearLegacyBackupPreference(Context context) {
117         getPreferences(context).mSharedPreferences.edit().remove(ACCOUNT_UUIDS).apply();
118     }
119 
setEnableDebugLogging(boolean value)120     public void setEnableDebugLogging(boolean value) {
121         mSharedPreferences.edit().putBoolean(ENABLE_DEBUG_LOGGING, value).apply();
122     }
123 
getEnableDebugLogging()124     public boolean getEnableDebugLogging() {
125         return mSharedPreferences.getBoolean(ENABLE_DEBUG_LOGGING, false);
126     }
127 
setEnableExchangeLogging(boolean value)128     public void setEnableExchangeLogging(boolean value) {
129         mSharedPreferences.edit().putBoolean(ENABLE_EXCHANGE_LOGGING, value).apply();
130     }
131 
getEnableExchangeLogging()132     public boolean getEnableExchangeLogging() {
133         return mSharedPreferences.getBoolean(ENABLE_EXCHANGE_LOGGING, false);
134     }
135 
setEnableExchangeFileLogging(boolean value)136     public void setEnableExchangeFileLogging(boolean value) {
137         mSharedPreferences.edit().putBoolean(ENABLE_EXCHANGE_FILE_LOGGING, value).apply();
138     }
139 
getEnableExchangeFileLogging()140     public boolean getEnableExchangeFileLogging() {
141         return mSharedPreferences.getBoolean(ENABLE_EXCHANGE_FILE_LOGGING, false);
142     }
143 
setEnableStrictMode(boolean value)144     public void setEnableStrictMode(boolean value) {
145         mSharedPreferences.edit().putBoolean(ENABLE_STRICT_MODE, value).apply();
146     }
147 
getEnableStrictMode()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      */
getDeviceUID()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 
getOneTimeInitializationProgress()166     public int getOneTimeInitializationProgress() {
167         return mSharedPreferences.getInt(ONE_TIME_INITIALIZATION_PROGRESS, 0);
168     }
169 
setOneTimeInitializationProgress(int progress)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
getAutoAdvanceDirection()176     public int getAutoAdvanceDirection() {
177         return mSharedPreferences.getInt(AUTO_ADVANCE_DIRECTION, AUTO_ADVANCE_DEFAULT);
178     }
179 
180     /** @deprecated Only used for migration */
181     @Deprecated
getConversationListIcon()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
getConfirmDelete()188     public boolean getConfirmDelete() {
189         return mSharedPreferences.getBoolean(CONFIRM_DELETE, CONFIRM_DELETE_DEFAULT);
190     }
191 
192     /** @deprecated Only used for migration */
193     @Deprecated
getConfirmSend()194     public boolean getConfirmSend() {
195         return mSharedPreferences.getBoolean(CONFIRM_SEND, CONFIRM_SEND_DEFAULT);
196     }
197 
198     /** @deprecated Only used for migration */
199     @Deprecated
hasSwipeDelete()200     public boolean hasSwipeDelete() {
201         return mSharedPreferences.contains(SWIPE_DELETE);
202     }
203 
204     /** @deprecated Only used for migration */
205     @Deprecated
getSwipeDelete()206     public boolean getSwipeDelete() {
207         return mSharedPreferences.getBoolean(SWIPE_DELETE, false);
208     }
209 
210     /** @deprecated Only used for migration */
211     @Deprecated
hasReplyAll()212     public boolean hasReplyAll() {
213         return mSharedPreferences.contains(REPLY_ALL);
214     }
215 
216     /** @deprecated Only used for migration */
217     @Deprecated
getReplyAll()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
getWhitelistedSenderAddresses()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 
parseEmailSet(String serialized)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      */
getLastUsedAccountId()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      */
setLastUsedAccountId(long accountId)262     public void setLastUsedAccountId(long accountId) {
263         mSharedPreferences
264                 .edit()
265                 .putLong(LAST_ACCOUNT_USED, accountId)
266                 .apply();
267     }
268 
clear()269     public void clear() {
270         mSharedPreferences.edit().clear().apply();
271     }
272 
dump()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