Split AccountTypeManager.contains method

It now has an exists method and a isWritable method instead.

Test: manually remove account that is being displayed and manually
remove default account

Bug 33627801

Change-Id: I862779a7ac221fa8b2f0c84b6c73af0fee71c935
diff --git a/src/com/android/contacts/list/ContactListFilterController.java b/src/com/android/contacts/list/ContactListFilterController.java
index 3a4596d..df81832 100644
--- a/src/com/android/contacts/list/ContactListFilterController.java
+++ b/src/com/android/contacts/list/ContactListFilterController.java
@@ -194,6 +194,6 @@
         final AccountTypeManager accountTypeManager = AccountTypeManager.getInstance(mContext);
         final AccountWithDataSet filterAccount = new AccountWithDataSet(
                 mFilter.accountName, mFilter.accountType, mFilter.dataSet);
-        return accountTypeManager.contains(filterAccount, /* contactWritableOnly */ false);
+        return accountTypeManager.exists(filterAccount);
     }
 }
diff --git a/src/com/android/contacts/model/AccountTypeManager.java b/src/com/android/contacts/model/AccountTypeManager.java
index 1d3a5fa..ddbadfd 100644
--- a/src/com/android/contacts/model/AccountTypeManager.java
+++ b/src/com/android/contacts/model/AccountTypeManager.java
@@ -206,7 +206,8 @@
      * Returns true if there are real accounts (not "local" account) in the list of accounts.
      */
     public boolean hasNonLocalAccount() {
-        final List<AccountWithDataSet> allAccounts = getAccounts(/* contactWritableOnly */ false);
+        final List<AccountWithDataSet> allAccounts =
+                AccountInfo.extractAccounts(Futures.getUnchecked(getAccountsAsync()));
         if (allAccounts == null || allAccounts.size() == 0) {
             return false;
         }
@@ -267,16 +268,22 @@
     }
 
     /**
-     * @param contactWritableOnly if true, it only returns ones that support writing contacts.
-     * @return true when this instance contains the given account.
+     * Returns whether the specified account still exists
      */
-    public boolean contains(AccountWithDataSet account, boolean contactWritableOnly) {
-        for (AccountWithDataSet account_2 : getAccounts(contactWritableOnly)) {
-            if (account.equals(account_2)) {
-                return true;
-            }
-        }
-        return false;
+    public boolean exists(AccountWithDataSet account) {
+        final List<AccountWithDataSet> accounts =
+                AccountInfo.extractAccounts(Futures.getUnchecked(getAccountsAsync()));
+        return accounts.contains(account);
+    }
+
+    /**
+     * Returns whether the specified account is writable
+     *
+     * <p>This checks that the account still exists and that
+     * {@link AccountType#areContactsWritable()} is true</p>
+     */
+    public boolean isWritable(AccountWithDataSet account) {
+        return exists(account) && getAccountInfoForAccount(account).getType().areContactsWritable();
     }
 
     public boolean hasGoogleAccount() {
@@ -650,6 +657,13 @@
         return result;
     }
 
+    /**
+     * Returns true if there are real accounts (not "local" account) in the list of accounts.
+     *
+     * <p>This is overriden for performance since the default implementation blocks until all
+     * accounts are loaded
+     * </p>
+     */
     @Override
     public boolean hasNonLocalAccount() {
         final Account[] accounts = mAccountManager.getAccounts();
@@ -685,6 +699,26 @@
     }
 
     /**
+     * Returns whether the account still exists on the device
+     *
+     * <p>This is overridden for performance. The default implementation loads all accounts then
+     * searches through them for specified. This implementation will only load the types for the
+     * specified AccountType (it may still require blocking on IO in some cases but it shouldn't
+     * be as bad as blocking for all accounts).
+     * </p>
+     */
+    @Override
+    public boolean exists(AccountWithDataSet account) {
+        final Account[] accounts = mAccountManager.getAccountsByType(account.type);
+        for (Account existingAccount : accounts) {
+            if (existingAccount.name.equals(account.name)) {
+                return mTypeProvider.getTypeForAccount(account) != null;
+            }
+        }
+        return false;
+    }
+
+    /**
      * Return {@link AccountType} for the given account type and data set.
      */
     @Override
diff --git a/src/com/android/contacts/model/account/AccountWithDataSet.java b/src/com/android/contacts/model/account/AccountWithDataSet.java
index 0f36918..a636440 100644
--- a/src/com/android/contacts/model/account/AccountWithDataSet.java
+++ b/src/com/android/contacts/model/account/AccountWithDataSet.java
@@ -259,7 +259,7 @@
             AccountTypeManager accountTypeManager) {
         if (preferences.isDefaultAccountSet()) {
             final AccountWithDataSet account = preferences.getDefaultAccount();
-            if (accountTypeManager.contains(account, true)) {
+            if (accountTypeManager.isWritable(account)) {
                 return account;
             }
         }