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 com.android.email.mail.Store; 20 21 import android.content.Context; 22 import android.content.SharedPreferences; 23 import android.net.Uri; 24 25 import java.util.Arrays; 26 import java.util.UUID; 27 28 /** 29 * Account stores all of the settings for a single account defined by the user. It is able to save 30 * and delete itself given a Preferences to work with. Each account is defined by a UUID. 31 */ 32 public class Account { 33 public static final int DELETE_POLICY_NEVER = 0; 34 public static final int DELETE_POLICY_7DAYS = 1; 35 public static final int DELETE_POLICY_ON_DELETE = 2; 36 37 public static final int CHECK_INTERVAL_NEVER = -1; 38 public static final int CHECK_INTERVAL_PUSH = -2; 39 40 public static final int SYNC_WINDOW_USER = -1; 41 public static final int SYNC_WINDOW_1_DAY = 1; 42 public static final int SYNC_WINDOW_3_DAYS = 2; 43 public static final int SYNC_WINDOW_1_WEEK = 3; 44 public static final int SYNC_WINDOW_2_WEEKS = 4; 45 public static final int SYNC_WINDOW_1_MONTH = 5; 46 public static final int SYNC_WINDOW_ALL = 6; 47 48 // These flags will never be seen in a "real" (legacy) account 49 public static final int BACKUP_FLAGS_IS_BACKUP = 1; 50 public static final int BACKUP_FLAGS_SYNC_CONTACTS = 2; 51 public static final int BACKUP_FLAGS_IS_DEFAULT = 4; 52 public static final int BACKUP_FLAGS_SYNC_CALENDAR = 8; 53 54 // transient values - do not serialize 55 private transient Preferences mPreferences; 56 57 // serialized values 58 String mUuid; 59 String mStoreUri; 60 String mLocalStoreUri; 61 String mSenderUri; 62 String mDescription; 63 String mName; 64 String mEmail; 65 int mAutomaticCheckIntervalMinutes; 66 long mLastAutomaticCheckTime; 67 boolean mNotifyNewMail; 68 String mDraftsFolderName; 69 String mSentFolderName; 70 String mTrashFolderName; 71 String mOutboxFolderName; 72 int mAccountNumber; 73 boolean mVibrate; // true: Always vibrate. false: Only when mVibrateWhenSilent. 74 boolean mVibrateWhenSilent; // true: Vibrate even if !mVibrate. False: Require mVibrate. 75 String mRingtoneUri; 76 int mSyncWindow; 77 int mBackupFlags; // for account backups only 78 String mProtocolVersion; // for account backups only 79 int mSecurityFlags; // for account backups only 80 String mSignature; // for account backups only 81 82 /** 83 * <pre> 84 * 0 Never 85 * 1 After 7 days 86 * 2 When I delete from inbox 87 * </pre> 88 */ 89 int mDeletePolicy; 90 91 /** 92 * All new fields should have named keys 93 */ 94 private static final String KEY_SYNC_WINDOW = ".syncWindow"; 95 private static final String KEY_BACKUP_FLAGS = ".backupFlags"; 96 private static final String KEY_PROTOCOL_VERSION = ".protocolVersion"; 97 private static final String KEY_SECURITY_FLAGS = ".securityFlags"; 98 private static final String KEY_SIGNATURE = ".signature"; 99 private static final String KEY_VIBRATE_WHEN_SILENT = ".vibrateWhenSilent"; 100 101 public Account(Context context) { 102 // TODO Change local store path to something readable / recognizable 103 mUuid = UUID.randomUUID().toString(); 104 mLocalStoreUri = "local://localhost/" + context.getDatabasePath(mUuid + ".db"); 105 mAutomaticCheckIntervalMinutes = -1; 106 mAccountNumber = -1; 107 mNotifyNewMail = true; 108 mVibrate = false; 109 mVibrateWhenSilent = false; 110 mRingtoneUri = "content://settings/system/notification_sound"; 111 mSyncWindow = SYNC_WINDOW_USER; // IMAP & POP3 112 mBackupFlags = 0; 113 mProtocolVersion = null; 114 mSecurityFlags = 0; 115 mSignature = null; 116 } 117 118 Account(Preferences preferences, String uuid) { 119 this.mUuid = uuid; 120 refresh(preferences); 121 } 122 123 /** 124 * Refresh the account from the stored settings. 125 */ 126 public void refresh(Preferences preferences) { 127 mPreferences = preferences; 128 129 mStoreUri = Utility.base64Decode(preferences.mSharedPreferences.getString(mUuid 130 + ".storeUri", null)); 131 mLocalStoreUri = preferences.mSharedPreferences.getString(mUuid + ".localStoreUri", null); 132 133 String senderText = preferences.mSharedPreferences.getString(mUuid + ".senderUri", null); 134 if (senderText == null) { 135 // Preference ".senderUri" was called ".transportUri" in earlier versions, so we'll 136 // do a simple upgrade here when necessary. 137 senderText = preferences.mSharedPreferences.getString(mUuid + ".transportUri", null); 138 } 139 mSenderUri = Utility.base64Decode(senderText); 140 141 mDescription = preferences.mSharedPreferences.getString(mUuid + ".description", null); 142 mName = preferences.mSharedPreferences.getString(mUuid + ".name", mName); 143 mEmail = preferences.mSharedPreferences.getString(mUuid + ".email", mEmail); 144 mAutomaticCheckIntervalMinutes = preferences.mSharedPreferences.getInt(mUuid 145 + ".automaticCheckIntervalMinutes", -1); 146 mLastAutomaticCheckTime = preferences.mSharedPreferences.getLong(mUuid 147 + ".lastAutomaticCheckTime", 0); 148 mNotifyNewMail = preferences.mSharedPreferences.getBoolean(mUuid + ".notifyNewMail", 149 false); 150 151 // delete policy was incorrectly set on earlier versions, so we'll upgrade it here. 152 // rule: if IMAP account and policy = 0 ("never"), change policy to 2 ("on delete") 153 mDeletePolicy = preferences.mSharedPreferences.getInt(mUuid + ".deletePolicy", 0); 154 if (mDeletePolicy == DELETE_POLICY_NEVER && 155 mStoreUri != null && mStoreUri.toString().startsWith(Store.STORE_SCHEME_IMAP)) { 156 mDeletePolicy = DELETE_POLICY_ON_DELETE; 157 } 158 159 mDraftsFolderName = preferences.mSharedPreferences.getString(mUuid + ".draftsFolderName", 160 "Drafts"); 161 mSentFolderName = preferences.mSharedPreferences.getString(mUuid + ".sentFolderName", 162 "Sent"); 163 mTrashFolderName = preferences.mSharedPreferences.getString(mUuid + ".trashFolderName", 164 "Trash"); 165 mOutboxFolderName = preferences.mSharedPreferences.getString(mUuid + ".outboxFolderName", 166 "Outbox"); 167 mAccountNumber = preferences.mSharedPreferences.getInt(mUuid + ".accountNumber", 0); 168 mVibrate = preferences.mSharedPreferences.getBoolean(mUuid + ".vibrate", false); 169 mVibrateWhenSilent = preferences.mSharedPreferences.getBoolean(mUuid + 170 KEY_VIBRATE_WHEN_SILENT, false); 171 mRingtoneUri = preferences.mSharedPreferences.getString(mUuid + ".ringtone", 172 "content://settings/system/notification_sound"); 173 174 mSyncWindow = preferences.mSharedPreferences.getInt(mUuid + KEY_SYNC_WINDOW, 175 SYNC_WINDOW_USER); 176 177 mBackupFlags = preferences.mSharedPreferences.getInt(mUuid + KEY_BACKUP_FLAGS, 0); 178 mProtocolVersion = preferences.mSharedPreferences.getString(mUuid + KEY_PROTOCOL_VERSION, 179 null); 180 mSecurityFlags = preferences.mSharedPreferences.getInt(mUuid + KEY_SECURITY_FLAGS, 0); 181 mSignature = preferences.mSharedPreferences.getString(mUuid + KEY_SIGNATURE, null); 182 } 183 184 public String getUuid() { 185 return mUuid; 186 } 187 188 public String getStoreUri() { 189 return mStoreUri; 190 } 191 192 public void setStoreUri(String storeUri) { 193 this.mStoreUri = storeUri; 194 } 195 196 public String getSenderUri() { 197 return mSenderUri; 198 } 199 200 public void setSenderUri(String senderUri) { 201 this.mSenderUri = senderUri; 202 } 203 204 public String getDescription() { 205 return mDescription; 206 } 207 208 public void setDescription(String description) { 209 this.mDescription = description; 210 } 211 212 public String getName() { 213 return mName; 214 } 215 216 public void setName(String name) { 217 this.mName = name; 218 } 219 220 public String getEmail() { 221 return mEmail; 222 } 223 224 public void setEmail(String email) { 225 this.mEmail = email; 226 } 227 228 public boolean isVibrate() { 229 return mVibrate; 230 } 231 232 public void setVibrate(boolean vibrate) { 233 mVibrate = vibrate; 234 } 235 236 public boolean isVibrateWhenSilent() { 237 return mVibrateWhenSilent; 238 } 239 240 public void setVibrateWhenSilent(boolean vibrateWhenSilent) { 241 mVibrateWhenSilent = vibrateWhenSilent; 242 } 243 244 public String getRingtone() { 245 return mRingtoneUri; 246 } 247 248 public void setRingtone(String ringtoneUri) { 249 mRingtoneUri = ringtoneUri; 250 } 251 252 public void delete(Preferences preferences) { 253 String[] uuids = preferences.mSharedPreferences.getString("accountUuids", "").split(","); 254 StringBuffer sb = new StringBuffer(); 255 for (int i = 0, length = uuids.length; i < length; i++) { 256 if (!uuids[i].equals(mUuid)) { 257 if (sb.length() > 0) { 258 sb.append(','); 259 } 260 sb.append(uuids[i]); 261 } 262 } 263 String accountUuids = sb.toString(); 264 SharedPreferences.Editor editor = preferences.mSharedPreferences.edit(); 265 editor.putString("accountUuids", accountUuids); 266 267 editor.remove(mUuid + ".storeUri"); 268 editor.remove(mUuid + ".localStoreUri"); 269 editor.remove(mUuid + ".senderUri"); 270 editor.remove(mUuid + ".description"); 271 editor.remove(mUuid + ".name"); 272 editor.remove(mUuid + ".email"); 273 editor.remove(mUuid + ".automaticCheckIntervalMinutes"); 274 editor.remove(mUuid + ".lastAutomaticCheckTime"); 275 editor.remove(mUuid + ".notifyNewMail"); 276 editor.remove(mUuid + ".deletePolicy"); 277 editor.remove(mUuid + ".draftsFolderName"); 278 editor.remove(mUuid + ".sentFolderName"); 279 editor.remove(mUuid + ".trashFolderName"); 280 editor.remove(mUuid + ".outboxFolderName"); 281 editor.remove(mUuid + ".accountNumber"); 282 editor.remove(mUuid + ".vibrate"); 283 editor.remove(mUuid + KEY_VIBRATE_WHEN_SILENT); 284 editor.remove(mUuid + ".ringtone"); 285 editor.remove(mUuid + KEY_SYNC_WINDOW); 286 editor.remove(mUuid + KEY_BACKUP_FLAGS); 287 editor.remove(mUuid + KEY_PROTOCOL_VERSION); 288 editor.remove(mUuid + KEY_SECURITY_FLAGS); 289 editor.remove(mUuid + KEY_SIGNATURE); 290 291 // also delete any deprecated fields 292 editor.remove(mUuid + ".transportUri"); 293 294 editor.commit(); 295 } 296 297 public void save(Preferences preferences) { 298 mPreferences = preferences; 299 300 if (!preferences.mSharedPreferences.getString("accountUuids", "").contains(mUuid)) { 301 /* 302 * When the account is first created we assign it a unique account number. The 303 * account number will be unique to that account for the lifetime of the account. 304 * So, we get all the existing account numbers, sort them ascending, loop through 305 * the list and check if the number is greater than 1 + the previous number. If so 306 * we use the previous number + 1 as the account number. This refills gaps. 307 * mAccountNumber starts as -1 on a newly created account. It must be -1 for this 308 * algorithm to work. 309 * 310 * I bet there is a much smarter way to do this. Anyone like to suggest it? 311 */ 312 Account[] accounts = preferences.getAccounts(); 313 int[] accountNumbers = new int[accounts.length]; 314 for (int i = 0; i < accounts.length; i++) { 315 accountNumbers[i] = accounts[i].getAccountNumber(); 316 } 317 Arrays.sort(accountNumbers); 318 for (int accountNumber : accountNumbers) { 319 if (accountNumber > mAccountNumber + 1) { 320 break; 321 } 322 mAccountNumber = accountNumber; 323 } 324 mAccountNumber++; 325 326 String accountUuids = preferences.mSharedPreferences.getString("accountUuids", ""); 327 accountUuids += (accountUuids.length() != 0 ? "," : "") + mUuid; 328 SharedPreferences.Editor editor = preferences.mSharedPreferences.edit(); 329 editor.putString("accountUuids", accountUuids); 330 editor.commit(); 331 } 332 333 SharedPreferences.Editor editor = preferences.mSharedPreferences.edit(); 334 335 editor.putString(mUuid + ".storeUri", Utility.base64Encode(mStoreUri)); 336 editor.putString(mUuid + ".localStoreUri", mLocalStoreUri); 337 editor.putString(mUuid + ".senderUri", Utility.base64Encode(mSenderUri)); 338 editor.putString(mUuid + ".description", mDescription); 339 editor.putString(mUuid + ".name", mName); 340 editor.putString(mUuid + ".email", mEmail); 341 editor.putInt(mUuid + ".automaticCheckIntervalMinutes", mAutomaticCheckIntervalMinutes); 342 editor.putLong(mUuid + ".lastAutomaticCheckTime", mLastAutomaticCheckTime); 343 editor.putBoolean(mUuid + ".notifyNewMail", mNotifyNewMail); 344 editor.putInt(mUuid + ".deletePolicy", mDeletePolicy); 345 editor.putString(mUuid + ".draftsFolderName", mDraftsFolderName); 346 editor.putString(mUuid + ".sentFolderName", mSentFolderName); 347 editor.putString(mUuid + ".trashFolderName", mTrashFolderName); 348 editor.putString(mUuid + ".outboxFolderName", mOutboxFolderName); 349 editor.putInt(mUuid + ".accountNumber", mAccountNumber); 350 editor.putBoolean(mUuid + ".vibrate", mVibrate); 351 editor.putBoolean(mUuid + KEY_VIBRATE_WHEN_SILENT, mVibrateWhenSilent); 352 editor.putString(mUuid + ".ringtone", mRingtoneUri); 353 editor.putInt(mUuid + KEY_SYNC_WINDOW, mSyncWindow); 354 editor.putInt(mUuid + KEY_BACKUP_FLAGS, mBackupFlags); 355 editor.putString(mUuid + KEY_PROTOCOL_VERSION, mProtocolVersion); 356 editor.putInt(mUuid + KEY_SECURITY_FLAGS, mSecurityFlags); 357 editor.putString(mUuid + KEY_SIGNATURE, mSignature); 358 359 // The following fields are *not* written because they need to be more fine-grained 360 // and not risk rewriting with old data. 361 // editor.putString(mUuid + PREF_TAG_STORE_PERSISTENT, mStorePersistent); 362 363 // also delete any deprecated fields 364 editor.remove(mUuid + ".transportUri"); 365 366 editor.commit(); 367 } 368 369 @Override 370 public String toString() { 371 return mDescription; 372 } 373 374 public Uri getContentUri() { 375 return Uri.parse("content://accounts/" + getUuid()); 376 } 377 378 public String getLocalStoreUri() { 379 return mLocalStoreUri; 380 } 381 382 public void setLocalStoreUri(String localStoreUri) { 383 this.mLocalStoreUri = localStoreUri; 384 } 385 386 /** 387 * Returns -1 for never. 388 */ 389 public int getAutomaticCheckIntervalMinutes() { 390 return mAutomaticCheckIntervalMinutes; 391 } 392 393 /** 394 * @param automaticCheckIntervalMinutes or -1 for never. 395 */ 396 public void setAutomaticCheckIntervalMinutes(int automaticCheckIntervalMinutes) { 397 this.mAutomaticCheckIntervalMinutes = automaticCheckIntervalMinutes; 398 } 399 400 public long getLastAutomaticCheckTime() { 401 return mLastAutomaticCheckTime; 402 } 403 404 public void setLastAutomaticCheckTime(long lastAutomaticCheckTime) { 405 this.mLastAutomaticCheckTime = lastAutomaticCheckTime; 406 } 407 408 public boolean isNotifyNewMail() { 409 return mNotifyNewMail; 410 } 411 412 public void setNotifyNewMail(boolean notifyNewMail) { 413 this.mNotifyNewMail = notifyNewMail; 414 } 415 416 public int getDeletePolicy() { 417 return mDeletePolicy; 418 } 419 420 public void setDeletePolicy(int deletePolicy) { 421 this.mDeletePolicy = deletePolicy; 422 } 423 424 public String getDraftsFolderName() { 425 return mDraftsFolderName; 426 } 427 428 public void setDraftsFolderName(String draftsFolderName) { 429 mDraftsFolderName = draftsFolderName; 430 } 431 432 public String getSentFolderName() { 433 return mSentFolderName; 434 } 435 436 public void setSentFolderName(String sentFolderName) { 437 mSentFolderName = sentFolderName; 438 } 439 440 public String getTrashFolderName() { 441 return mTrashFolderName; 442 } 443 444 public void setTrashFolderName(String trashFolderName) { 445 mTrashFolderName = trashFolderName; 446 } 447 448 public String getOutboxFolderName() { 449 return mOutboxFolderName; 450 } 451 452 public void setOutboxFolderName(String outboxFolderName) { 453 mOutboxFolderName = outboxFolderName; 454 } 455 456 public int getAccountNumber() { 457 return mAccountNumber; 458 } 459 460 public int getSyncWindow() { 461 return mSyncWindow; 462 } 463 464 public void setSyncWindow(int window) { 465 mSyncWindow = window; 466 } 467 468 public int getBackupFlags() { 469 return mBackupFlags; 470 } 471 472 public void setBackupFlags(int flags) { 473 mBackupFlags = flags; 474 } 475 476 @Override 477 public boolean equals(Object o) { 478 if (o instanceof Account) { 479 return ((Account)o).mUuid.equals(mUuid); 480 } 481 return super.equals(o); 482 } 483 } 484