1 /* 2 * Copyright (C) 2010 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.contacts.common.preference; 18 19 import android.content.Context; 20 import android.content.SharedPreferences; 21 import android.content.SharedPreferences.Editor; 22 import android.content.SharedPreferences.OnSharedPreferenceChangeListener; 23 import android.os.Handler; 24 import android.preference.PreferenceManager; 25 import android.provider.Settings; 26 import android.provider.Settings.SettingNotFoundException; 27 import android.text.TextUtils; 28 import com.android.contacts.common.R; 29 import com.android.contacts.common.model.account.AccountWithDataSet; 30 import com.android.dialer.strictmode.StrictModeUtils; 31 32 /** Manages user preferences for contacts. */ 33 public class ContactsPreferences implements OnSharedPreferenceChangeListener { 34 35 /** The value for the DISPLAY_ORDER key to show the given name first. */ 36 public static final int DISPLAY_ORDER_PRIMARY = 1; 37 38 /** The value for the DISPLAY_ORDER key to show the family name first. */ 39 public static final int DISPLAY_ORDER_ALTERNATIVE = 2; 40 41 public static final String DISPLAY_ORDER_KEY = "android.contacts.DISPLAY_ORDER"; 42 43 /** The value for the SORT_ORDER key corresponding to sort by given name first. */ 44 public static final int SORT_ORDER_PRIMARY = 1; 45 46 public static final String SORT_ORDER_KEY = "android.contacts.SORT_ORDER"; 47 48 /** The value for the SORT_ORDER key corresponding to sort by family name first. */ 49 public static final int SORT_ORDER_ALTERNATIVE = 2; 50 51 public static final String PREF_DISPLAY_ONLY_PHONES = "only_phones"; 52 53 public static final boolean PREF_DISPLAY_ONLY_PHONES_DEFAULT = false; 54 55 /** 56 * Value to use when a preference is unassigned and needs to be read from the shared preferences 57 */ 58 private static final int PREFERENCE_UNASSIGNED = -1; 59 60 private final Context mContext; 61 private final SharedPreferences mPreferences; 62 private int mSortOrder = PREFERENCE_UNASSIGNED; 63 private int mDisplayOrder = PREFERENCE_UNASSIGNED; 64 private String mDefaultAccount = null; 65 private ChangeListener mListener = null; 66 private Handler mHandler; 67 private String mDefaultAccountKey; 68 private String mDefaultAccountSavedKey; 69 ContactsPreferences(Context context)70 public ContactsPreferences(Context context) { 71 mContext = context; 72 mHandler = new Handler(); 73 mPreferences = 74 mContext 75 .getApplicationContext() 76 .getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE); 77 mDefaultAccountKey = 78 mContext.getResources().getString(R.string.contact_editor_default_account_key); 79 mDefaultAccountSavedKey = 80 mContext.getResources().getString(R.string.contact_editor_anything_saved_key); 81 maybeMigrateSystemSettings(); 82 } 83 isSortOrderUserChangeable()84 private boolean isSortOrderUserChangeable() { 85 return mContext.getResources().getBoolean(R.bool.config_sort_order_user_changeable); 86 } 87 getDefaultSortOrder()88 private int getDefaultSortOrder() { 89 if (mContext.getResources().getBoolean(R.bool.config_default_sort_order_primary)) { 90 return SORT_ORDER_PRIMARY; 91 } else { 92 return SORT_ORDER_ALTERNATIVE; 93 } 94 } 95 getSortOrder()96 public int getSortOrder() { 97 if (!isSortOrderUserChangeable()) { 98 return getDefaultSortOrder(); 99 } 100 if (mSortOrder == PREFERENCE_UNASSIGNED) { 101 mSortOrder = mPreferences.getInt(SORT_ORDER_KEY, getDefaultSortOrder()); 102 } 103 return mSortOrder; 104 } 105 setSortOrder(int sortOrder)106 public void setSortOrder(int sortOrder) { 107 mSortOrder = sortOrder; 108 final Editor editor = mPreferences.edit(); 109 editor.putInt(SORT_ORDER_KEY, sortOrder); 110 StrictModeUtils.bypass(editor::commit); 111 } 112 isDisplayOrderUserChangeable()113 private boolean isDisplayOrderUserChangeable() { 114 return mContext.getResources().getBoolean(R.bool.config_display_order_user_changeable); 115 } 116 getDefaultDisplayOrder()117 private int getDefaultDisplayOrder() { 118 if (mContext.getResources().getBoolean(R.bool.config_default_display_order_primary)) { 119 return DISPLAY_ORDER_PRIMARY; 120 } else { 121 return DISPLAY_ORDER_ALTERNATIVE; 122 } 123 } 124 getDisplayOrder()125 public int getDisplayOrder() { 126 if (!isDisplayOrderUserChangeable()) { 127 return getDefaultDisplayOrder(); 128 } 129 if (mDisplayOrder == PREFERENCE_UNASSIGNED) { 130 mDisplayOrder = mPreferences.getInt(DISPLAY_ORDER_KEY, getDefaultDisplayOrder()); 131 } 132 return mDisplayOrder; 133 } 134 setDisplayOrder(int displayOrder)135 public void setDisplayOrder(int displayOrder) { 136 mDisplayOrder = displayOrder; 137 final Editor editor = mPreferences.edit(); 138 editor.putInt(DISPLAY_ORDER_KEY, displayOrder); 139 StrictModeUtils.bypass(editor::commit); 140 } 141 isDefaultAccountUserChangeable()142 private boolean isDefaultAccountUserChangeable() { 143 return mContext.getResources().getBoolean(R.bool.config_default_account_user_changeable); 144 } 145 getDefaultAccount()146 private String getDefaultAccount() { 147 if (!isDefaultAccountUserChangeable()) { 148 return mDefaultAccount; 149 } 150 if (TextUtils.isEmpty(mDefaultAccount)) { 151 final String accountString = mPreferences.getString(mDefaultAccountKey, mDefaultAccount); 152 if (!TextUtils.isEmpty(accountString)) { 153 final AccountWithDataSet accountWithDataSet = AccountWithDataSet.unstringify(accountString); 154 mDefaultAccount = accountWithDataSet.name; 155 } 156 } 157 return mDefaultAccount; 158 } 159 setDefaultAccount(AccountWithDataSet accountWithDataSet)160 private void setDefaultAccount(AccountWithDataSet accountWithDataSet) { 161 mDefaultAccount = accountWithDataSet == null ? null : accountWithDataSet.name; 162 final Editor editor = mPreferences.edit(); 163 if (TextUtils.isEmpty(mDefaultAccount)) { 164 editor.remove(mDefaultAccountKey); 165 } else { 166 editor.putString(mDefaultAccountKey, accountWithDataSet.stringify()); 167 } 168 editor.putBoolean(mDefaultAccountSavedKey, true); 169 StrictModeUtils.bypass(editor::commit); 170 } 171 registerChangeListener(ChangeListener listener)172 public void registerChangeListener(ChangeListener listener) { 173 if (mListener != null) { 174 unregisterChangeListener(); 175 } 176 177 mListener = listener; 178 179 // Reset preferences to "unknown" because they may have changed while the 180 // listener was unregistered. 181 mDisplayOrder = PREFERENCE_UNASSIGNED; 182 mSortOrder = PREFERENCE_UNASSIGNED; 183 mDefaultAccount = null; 184 185 mPreferences.registerOnSharedPreferenceChangeListener(this); 186 } 187 unregisterChangeListener()188 public void unregisterChangeListener() { 189 if (mListener != null) { 190 mListener = null; 191 } 192 193 mPreferences.unregisterOnSharedPreferenceChangeListener(this); 194 } 195 196 @Override onSharedPreferenceChanged(SharedPreferences sharedPreferences, final String key)197 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, final String key) { 198 // This notification is not sent on the Ui thread. Use the previously created Handler 199 // to switch to the Ui thread 200 mHandler.post( 201 new Runnable() { 202 @Override 203 public void run() { 204 refreshValue(key); 205 } 206 }); 207 } 208 209 /** 210 * Forces the value for the given key to be looked up from shared preferences and notifies the 211 * registered {@link ChangeListener} 212 * 213 * @param key the {@link SharedPreferences} key to look up 214 */ refreshValue(String key)215 public void refreshValue(String key) { 216 if (DISPLAY_ORDER_KEY.equals(key)) { 217 mDisplayOrder = PREFERENCE_UNASSIGNED; 218 mDisplayOrder = getDisplayOrder(); 219 } else if (SORT_ORDER_KEY.equals(key)) { 220 mSortOrder = PREFERENCE_UNASSIGNED; 221 mSortOrder = getSortOrder(); 222 } else if (mDefaultAccountKey.equals(key)) { 223 mDefaultAccount = null; 224 mDefaultAccount = getDefaultAccount(); 225 } 226 if (mListener != null) { 227 mListener.onChange(); 228 } 229 } 230 231 /** 232 * If there are currently no preferences (which means this is the first time we are run), For sort 233 * order and display order, check to see if there are any preferences stored in system settings 234 * (pre-L) which can be copied into our own SharedPreferences. For default account setting, check 235 * to see if there are any preferences stored in the previous SharedPreferences which can be 236 * copied into current SharedPreferences. 237 */ maybeMigrateSystemSettings()238 private void maybeMigrateSystemSettings() { 239 if (!mPreferences.contains(SORT_ORDER_KEY)) { 240 int sortOrder = getDefaultSortOrder(); 241 try { 242 sortOrder = Settings.System.getInt(mContext.getContentResolver(), SORT_ORDER_KEY); 243 } catch (SettingNotFoundException e) { 244 } 245 setSortOrder(sortOrder); 246 } 247 248 if (!mPreferences.contains(DISPLAY_ORDER_KEY)) { 249 int displayOrder = getDefaultDisplayOrder(); 250 try { 251 displayOrder = Settings.System.getInt(mContext.getContentResolver(), DISPLAY_ORDER_KEY); 252 } catch (SettingNotFoundException e) { 253 } 254 setDisplayOrder(displayOrder); 255 } 256 257 if (!mPreferences.contains(mDefaultAccountKey)) { 258 final SharedPreferences previousPrefs = 259 PreferenceManager.getDefaultSharedPreferences(mContext.getApplicationContext()); 260 final String defaultAccount = previousPrefs.getString(mDefaultAccountKey, null); 261 if (!TextUtils.isEmpty(defaultAccount)) { 262 final AccountWithDataSet accountWithDataSet = 263 AccountWithDataSet.unstringify(defaultAccount); 264 setDefaultAccount(accountWithDataSet); 265 } 266 } 267 } 268 269 public interface ChangeListener { 270 onChange()271 void onChange(); 272 } 273 } 274