Home | History | Annotate | Download | only in email
      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 
     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      */
     99     public static synchronized Preferences getPreferences(Context context) {
    100         if (sPreferences == null) {
    101             sPreferences = new Preferences(context);
    102         }
    103         return sPreferences;
    104     }
    105 
    106     public static SharedPreferences getSharedPreferences(Context context) {
    107         return getPreferences(context).mSharedPreferences;
    108     }
    109 
    110     public static String getLegacyBackupPreference(Context context) {
    111         return getPreferences(context).mSharedPreferences.getString(ACCOUNT_UUIDS, null);
    112     }
    113 
    114     public static void clearLegacyBackupPreference(Context context) {
    115         getPreferences(context).mSharedPreferences.edit().remove(ACCOUNT_UUIDS).apply();
    116     }
    117 
    118     public void setEnableDebugLogging(boolean value) {
    119         mSharedPreferences.edit().putBoolean(ENABLE_DEBUG_LOGGING, value).apply();
    120     }
    121 
    122     public boolean getEnableDebugLogging() {
    123         return mSharedPreferences.getBoolean(ENABLE_DEBUG_LOGGING, false);
    124     }
    125 
    126     public void setEnableExchangeLogging(boolean value) {
    127         mSharedPreferences.edit().putBoolean(ENABLE_EXCHANGE_LOGGING, value).apply();
    128     }
    129 
    130     public boolean getEnableExchangeLogging() {
    131         return mSharedPreferences.getBoolean(ENABLE_EXCHANGE_LOGGING, false);
    132     }
    133 
    134     public void setEnableExchangeFileLogging(boolean value) {
    135         mSharedPreferences.edit().putBoolean(ENABLE_EXCHANGE_FILE_LOGGING, value).apply();
    136     }
    137 
    138     public boolean getEnableExchangeFileLogging() {
    139         return mSharedPreferences.getBoolean(ENABLE_EXCHANGE_FILE_LOGGING, false);
    140     }
    141 
    142     public void setInhibitGraphicsAcceleration(boolean value) {
    143         mSharedPreferences.edit().putBoolean(INHIBIT_GRAPHICS_ACCELERATION, value).apply();
    144     }
    145 
    146     public boolean getInhibitGraphicsAcceleration() {
    147         return mSharedPreferences.getBoolean(INHIBIT_GRAPHICS_ACCELERATION, false);
    148     }
    149 
    150     public void setForceOneMinuteRefresh(boolean value) {
    151         mSharedPreferences.edit().putBoolean(FORCE_ONE_MINUTE_REFRESH, value).apply();
    152     }
    153 
    154     public boolean getForceOneMinuteRefresh() {
    155         return mSharedPreferences.getBoolean(FORCE_ONE_MINUTE_REFRESH, false);
    156     }
    157 
    158     public void setEnableStrictMode(boolean value) {
    159         mSharedPreferences.edit().putBoolean(ENABLE_STRICT_MODE, value).apply();
    160     }
    161 
    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      */
    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 
    180     public int getOneTimeInitializationProgress() {
    181         return mSharedPreferences.getInt(ONE_TIME_INITIALIZATION_PROGRESS, 0);
    182     }
    183 
    184     public void setOneTimeInitializationProgress(int progress) {
    185         mSharedPreferences.edit().putInt(ONE_TIME_INITIALIZATION_PROGRESS, progress).apply();
    186     }
    187 
    188     public int getAutoAdvanceDirection() {
    189         return mSharedPreferences.getInt(AUTO_ADVANCE_DIRECTION, AUTO_ADVANCE_DEFAULT);
    190     }
    191 
    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
    198     public String getConversationListIcon() {
    199         return mSharedPreferences.getString(CONV_LIST_ICON, CONV_LIST_ICON_SENDER_IMAGE);
    200     }
    201 
    202     public boolean getConfirmDelete() {
    203         return mSharedPreferences.getBoolean(CONFIRM_DELETE, CONFIRM_DELETE_DEFAULT);
    204     }
    205 
    206     public void setConfirmDelete(boolean set) {
    207         mSharedPreferences.edit().putBoolean(CONFIRM_DELETE, set).apply();
    208     }
    209 
    210     public boolean getConfirmSend() {
    211         return mSharedPreferences.getBoolean(CONFIRM_SEND, CONFIRM_SEND_DEFAULT);
    212     }
    213 
    214     public void setConfirmSend(boolean set) {
    215         mSharedPreferences.edit().putBoolean(CONFIRM_SEND, set).apply();
    216     }
    217 
    218     /** @deprecated Only used for migration */
    219     @Deprecated
    220     public boolean hasSwipeDelete() {
    221         return mSharedPreferences.contains(SWIPE_DELETE);
    222     }
    223 
    224     /** @deprecated Only used for migration */
    225     @Deprecated
    226     public boolean getSwipeDelete() {
    227         return mSharedPreferences.getBoolean(SWIPE_DELETE, false);
    228     }
    229 
    230     /** @deprecated Only used for migration */
    231     @Deprecated
    232     public boolean hasReplyAll() {
    233         return mSharedPreferences.contains(REPLY_ALL);
    234     }
    235 
    236     /** @deprecated Only used for migration */
    237     @Deprecated
    238     public boolean getReplyAll() {
    239         return mSharedPreferences.getBoolean(REPLY_ALL, false);
    240     }
    241 
    242     public int getTextZoom() {
    243         return mSharedPreferences.getInt(TEXT_ZOOM, TEXT_ZOOM_DEFAULT);
    244     }
    245 
    246     public void setTextZoom(int zoom) {
    247         mSharedPreferences.edit().putInt(TEXT_ZOOM, zoom).apply();
    248     }
    249 
    250     public boolean getBackgroundAttachments() {
    251         return mSharedPreferences.getBoolean(BACKGROUND_ATTACHMENTS, false);
    252     }
    253 
    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
    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 
    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 
    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      */
    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      */
    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      */
    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      */
    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      */
    330     public boolean shouldShowRequireManualSync(Context context, Account account) {
    331         return Account.isAutomaticSyncDisabledByRoaming(context, account.mId)
    332                 && !getHasShownRequireManualSync(account);
    333     }
    334 
    335     public void clear() {
    336         mSharedPreferences.edit().clear().apply();
    337     }
    338 
    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      */
    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      */
    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      */
    364     private static String makeKey(String account, String key) {
    365         return account != null ? account + "-" + key : key;
    366     }
    367 }
    368