summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/com/android/contacts/editor/ContactEditorUtils.java43
-rw-r--r--src/com/android/contacts/model/AccountTypeManager.java301
-rw-r--r--src/com/android/contacts/model/Contact.java17
-rw-r--r--src/com/android/contacts/model/ContactLoader.java62
-rw-r--r--src/com/android/contacts/model/account/AccountWithDataSet.java2
-rw-r--r--src/com/android/contacts/quickcontact/QuickContactActivity.java4
-rw-r--r--src/com/android/contacts/util/AccountFilterUtil.java4
-rw-r--r--tests/src/com/android/contacts/editor/ContactEditorUtilsTest.java31
-rw-r--r--tests/src/com/android/contacts/model/AccountTypeManagerTest.java138
-rw-r--r--tests/src/com/android/contacts/test/mocks/MockAccountTypeManager.java24
10 files changed, 29 insertions, 597 deletions
diff --git a/src/com/android/contacts/editor/ContactEditorUtils.java b/src/com/android/contacts/editor/ContactEditorUtils.java
index 24d5ce009..4bb075cc6 100644
--- a/src/com/android/contacts/editor/ContactEditorUtils.java
+++ b/src/com/android/contacts/editor/ContactEditorUtils.java
@@ -23,6 +23,7 @@ import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
+import android.os.Bundle;
import android.provider.ContactsContract;
import android.text.TextUtils;
@@ -147,46 +148,20 @@ public class ContactEditorUtils {
}
}
- @VisibleForTesting
- String[] getWritableAccountTypeStrings() {
- final Set<String> types = Sets.newHashSet();
- for (AccountType type : mAccountTypes.getAccountTypes(true)) {
- types.add(type.accountType);
- }
- return types.toArray(new String[types.size()]);
- }
-
/**
- * Create an {@link Intent} to start "add new account" setup wizard. Selectable account
- * types will be limited to ones that supports editing contacts.
+ * Parses a result from {@link AccountManager#newChooseAccountIntent(Account, List, String[],
+ * String, String, String[], Bundle)} and returns the created {@link Account}, or null if
+ * the user has canceled the wizard.
*
- * Use {@link Activity#startActivityForResult} or
- * {@link android.app.Fragment#startActivityForResult} to start the wizard, and
- * {@link Activity#onActivityResult} or {@link android.app.Fragment#onActivityResult} to
- * get the result.
- */
- public Intent createAddWritableAccountIntent() {
- return AccountManager.newChooseAccountIntent(
- null, // selectedAccount
- new ArrayList<Account>(), // allowableAccounts
- getWritableAccountTypeStrings(), // allowableAccountTypes
- false, // alwaysPromptForAccount
- null, // descriptionOverrideText
- null, // addAccountAuthTokenType
- null, // addAccountRequiredFeatures
- null // addAccountOptions
- );
- }
-
- /**
- * Parses a result from {@link #createAddWritableAccountIntent} and returns the created
- * {@link Account}, or null if the user has canceled the wizard. Pass the {@code resultCode}
- * and {@code data} parameters passed to {@link Activity#onActivityResult} or
- * {@link android.app.Fragment#onActivityResult}.
+ * <p>Pass the {@code resultCode} and {@code data} parameters passed to
+ * {@link Activity#onActivityResult} or {@link android.app.Fragment#onActivityResult}.
+ * </p>
*
+ * <p>
* Note although the return type is {@link AccountWithDataSet}, return values from this method
* will never have {@link AccountWithDataSet#dataSet} set, as there's no way to create an
* extension package account from setup wizard.
+ * </p>
*/
public AccountWithDataSet getCreatedAccount(int resultCode, Intent resultData) {
// Javadoc doesn't say anything about resultCode but that the data intent will be non null
diff --git a/src/com/android/contacts/model/AccountTypeManager.java b/src/com/android/contacts/model/AccountTypeManager.java
index b0b3173a9..24957d7b7 100644
--- a/src/com/android/contacts/model/AccountTypeManager.java
+++ b/src/com/android/contacts/model/AccountTypeManager.java
@@ -16,8 +16,6 @@
package com.android.contacts.model;
-import static com.android.contacts.util.DeviceLocalAccountTypeFactory.Util.isLocalAccountType;
-
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AuthenticatorDescription;
@@ -31,10 +29,8 @@ import android.content.SharedPreferences;
import android.content.SyncAdapterType;
import android.content.SyncStatusObserver;
import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
import android.database.ContentObserver;
import android.net.Uri;
-import android.os.AsyncTask;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@@ -47,7 +43,6 @@ import android.util.Log;
import android.util.TimingLogger;
import com.android.contacts.Experiments;
-import com.android.contacts.MoreContactUtils;
import com.android.contacts.R;
import com.android.contacts.list.ContactListFilterController;
import com.android.contacts.model.account.AccountType;
@@ -63,8 +58,6 @@ import com.android.contacts.util.Constants;
import com.android.contacts.util.DeviceLocalAccountTypeFactory;
import com.android.contactsbind.ObjectFactory;
import com.android.contactsbind.experiments.Flags;
-
-import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
@@ -73,18 +66,17 @@ import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.Nullable;
+import static com.android.contacts.util.DeviceLocalAccountTypeFactory.Util.isLocalAccountType;
+
/**
* Singleton holder for all parsed {@link AccountType} available on the
* system, typically filled through {@link PackageManager} queries.
@@ -150,25 +142,9 @@ public abstract class AccountTypeManager {
}
@Override
- public List<AccountWithDataSet> getSortedAccounts(AccountWithDataSet defaultAccount,
- boolean contactWritableOnly) {
- return Collections.emptyList();
- }
-
- @Override
public AccountType getAccountType(AccountTypeWithDataSet accountTypeWithDataSet) {
return null;
}
-
- @Override
- public Map<AccountTypeWithDataSet, AccountType> getUsableInvitableAccountTypes() {
- return null;
- }
-
- @Override
- public List<AccountType> getAccountTypes(boolean contactWritableOnly) {
- return Collections.emptyList();
- }
};
/**
@@ -180,9 +156,6 @@ public abstract class AccountTypeManager {
public abstract List<AccountWithDataSet> getAccounts(Predicate<AccountWithDataSet> filter);
- public abstract List<AccountWithDataSet> getSortedAccounts(AccountWithDataSet defaultAccount,
- boolean contactWritableOnly);
-
/**
* Returns the list of accounts that are group writable.
*/
@@ -235,21 +208,6 @@ public abstract class AccountTypeManager {
}
/**
- * @return Unmodifiable map from {@link AccountTypeWithDataSet}s to {@link AccountType}s
- * which support the "invite" feature and have one or more account.
- *
- * This is a filtered down and more "usable" list compared to
- * {@link #getAllInvitableAccountTypes}, where usable is defined as:
- * (1) making sure that the app that contributed the account type is not disabled
- * (in order to avoid presenting the user with an option that does nothing), and
- * (2) that there is at least one raw contact with that account type in the database
- * (assuming that the user probably doesn't use that account type).
- *
- * Warning: Don't use on the UI thread because this can scan the database.
- */
- public abstract Map<AccountTypeWithDataSet, AccountType> getUsableInvitableAccountTypes();
-
- /**
* Find the best {@link DataKind} matching the requested
* {@link AccountType#accountType}, {@link AccountType#dataSet}, and {@link DataKind#mimeType}.
* If no direct match found, we try searching {@link FallbackAccountType}.
@@ -259,13 +217,6 @@ public abstract class AccountTypeManager {
}
/**
- * Returns all registered {@link AccountType}s, including extension ones.
- *
- * @param contactWritableOnly if true, it only returns ones that support writing contacts.
- */
- public abstract List<AccountType> getAccountTypes(boolean contactWritableOnly);
-
- /**
* @param contactWritableOnly if true, it only returns ones that support writing contacts.
* @return true when this instance contains the given account.
*/
@@ -282,6 +233,15 @@ public abstract class AccountTypeManager {
return getDefaultGoogleAccount() != null;
}
+ /**
+ * Sorts the accounts in-place such that defaultAccount is first in the list and the rest
+ * of the accounts are ordered in manner that is useful for display purposes
+ */
+ public static void sortAccounts(AccountWithDataSet defaultAccount,
+ List<AccountWithDataSet> accounts) {
+ Collections.sort(accounts, new AccountComparator(defaultAccount));
+ }
+
private static boolean hasRequiredPermissions(Context context) {
final boolean canGetAccounts = ContextCompat.checkSelfPermission(context,
android.Manifest.permission.GET_ACCOUNTS) == PackageManager.PERMISSION_GRANTED;
@@ -351,19 +311,6 @@ class AccountComparator implements Comparator<AccountWithDataSet> {
class AccountTypeManagerImpl extends AccountTypeManager
implements OnAccountsUpdateListener, SyncStatusObserver {
- private static final Map<AccountTypeWithDataSet, AccountType>
- EMPTY_UNMODIFIABLE_ACCOUNT_TYPE_MAP =
- Collections.unmodifiableMap(new HashMap<AccountTypeWithDataSet, AccountType>());
-
- /**
- * A sample contact URI used to test whether any activities will respond to an
- * invitable intent with the given URI as the intent data. This doesn't need to be
- * specific to a real contact because an app that intercepts the intent should probably do so
- * for all types of contact URIs.
- */
- private static final Uri SAMPLE_CONTACT_URI = ContactsContract.Contacts.getLookupUri(
- 1, "xxx");
-
private Context mContext;
private AccountManager mAccountManager;
private DeviceLocalAccountTypeFactory mDeviceLocalAccountTypeFactory;
@@ -374,22 +321,6 @@ class AccountTypeManagerImpl extends AccountTypeManager
private List<AccountWithDataSet> mContactWritableAccounts = Lists.newArrayList();
private List<AccountWithDataSet> mGroupWritableAccounts = Lists.newArrayList();
private Map<AccountTypeWithDataSet, AccountType> mAccountTypesWithDataSets = Maps.newHashMap();
- private Map<AccountTypeWithDataSet, AccountType> mInvitableAccountTypes =
- EMPTY_UNMODIFIABLE_ACCOUNT_TYPE_MAP;
-
- private final InvitableAccountTypeCache mInvitableAccountTypeCache;
-
- /**
- * The boolean value is equal to true if the {@link InvitableAccountTypeCache} has been
- * initialized. False otherwise.
- */
- private final AtomicBoolean mInvitablesCacheIsInitialized = new AtomicBoolean(false);
-
- /**
- * The boolean value is equal to true if the {@link FindInvitablesTask} is still executing.
- * False otherwise.
- */
- private final AtomicBoolean mInvitablesTaskIsRunning = new AtomicBoolean(false);
private static final int MESSAGE_LOAD_DATA = 0;
private static final int MESSAGE_PROCESS_BROADCAST_INTENT = 1;
@@ -445,8 +376,6 @@ class AccountTypeManagerImpl extends AccountTypeManager
}
};
- mInvitableAccountTypeCache = new InvitableAccountTypeCache();
-
// Request updates when packages or accounts change
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
@@ -721,8 +650,6 @@ class AccountTypeManagerImpl extends AccountTypeManager
mAccounts = allAccounts;
mContactWritableAccounts = contactWritableAccounts;
mGroupWritableAccounts = groupWritableAccounts;
- mInvitableAccountTypes = findAllInvitableAccountTypes(
- mContext, allAccounts, accountTypesByTypeAndDataSet);
}
timings.dumpToLog();
@@ -789,21 +716,6 @@ class AccountTypeManagerImpl extends AccountTypeManager
}
/**
- * Return list of all known or contact writable {@link AccountWithDataSet}'s sorted by
- * {@code defaultAccount}.
- * {@param defaultAccount} account to sort by
- * {@param contactWritableOnly} whether to restrict to contact writable accounts only
- */
- @Override
- public List<AccountWithDataSet> getSortedAccounts(AccountWithDataSet defaultAccount,
- boolean contactWritableOnly) {
- final AccountComparator comparator = new AccountComparator(defaultAccount);
- final List<AccountWithDataSet> accounts = getAccounts(contactWritableOnly);
- Collections.sort(accounts, comparator);
- return accounts;
- }
-
- /**
* Return the list of all known, group writable {@link AccountWithDataSet}'s.
*/
public List<AccountWithDataSet> getGroupWritableAccounts() {
@@ -865,195 +777,4 @@ class AccountTypeManagerImpl extends AccountTypeManager
return type != null ? type : mFallbackAccountType;
}
}
-
- /**
- * @return Unmodifiable map from {@link AccountTypeWithDataSet}s to {@link AccountType}s
- * which support the "invite" feature and have one or more account. This is an unfiltered
- * list. See {@link #getUsableInvitableAccountTypes()}.
- */
- private Map<AccountTypeWithDataSet, AccountType> getAllInvitableAccountTypes() {
- ensureAccountsLoaded();
- return mInvitableAccountTypes;
- }
-
- @Override
- public Map<AccountTypeWithDataSet, AccountType> getUsableInvitableAccountTypes() {
- ensureAccountsLoaded();
- // Since this method is not thread-safe, it's possible for multiple threads to encounter
- // the situation where (1) the cache has not been initialized yet or
- // (2) an async task to refresh the account type list in the cache has already been
- // started. Hence we use {@link AtomicBoolean}s and return cached values immediately
- // while we compute the actual result in the background. We use this approach instead of
- // using "synchronized" because computing the account type list involves a DB read, and
- // can potentially cause a deadlock situation if this method is called from code which
- // holds the DB lock. The trade-off of potentially having an incorrect list of invitable
- // account types for a short period of time seems more manageable than enforcing the
- // context in which this method is called.
-
- // Computing the list of usable invitable account types is done on the fly as requested.
- // If this method has never been called before, then block until the list has been computed.
- if (!mInvitablesCacheIsInitialized.get()) {
- mInvitableAccountTypeCache.setCachedValue(findUsableInvitableAccountTypes(mContext));
- mInvitablesCacheIsInitialized.set(true);
- } else {
- // Otherwise, there is a value in the cache. If the value has expired and
- // an async task has not already been started by another thread, then kick off a new
- // async task to compute the list.
- if (mInvitableAccountTypeCache.isExpired() &&
- mInvitablesTaskIsRunning.compareAndSet(false, true)) {
- new FindInvitablesTask().execute();
- }
- }
-
- return mInvitableAccountTypeCache.getCachedValue();
- }
-
- /**
- * Return all {@link AccountType}s with at least one account which supports "invite", i.e.
- * its {@link AccountType#getInviteContactActivityClassName()} is not empty.
- */
- @VisibleForTesting
- static Map<AccountTypeWithDataSet, AccountType> findAllInvitableAccountTypes(Context context,
- Collection<AccountWithDataSet> accounts,
- Map<AccountTypeWithDataSet, AccountType> accountTypesByTypeAndDataSet) {
- HashMap<AccountTypeWithDataSet, AccountType> result = Maps.newHashMap();
- for (AccountWithDataSet account : accounts) {
- AccountTypeWithDataSet accountTypeWithDataSet = account.getAccountTypeWithDataSet();
- AccountType type = accountTypesByTypeAndDataSet.get(accountTypeWithDataSet);
- if (type == null) continue; // just in case
- if (result.containsKey(accountTypeWithDataSet)) continue;
-
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Type " + accountTypeWithDataSet
- + " inviteClass=" + type.getInviteContactActivityClassName());
- }
- if (!TextUtils.isEmpty(type.getInviteContactActivityClassName())) {
- result.put(accountTypeWithDataSet, type);
- }
- }
- return Collections.unmodifiableMap(result);
- }
-
- /**
- * Return all usable {@link AccountType}s that support the "invite" feature from the
- * list of all potential invitable account types (retrieved from
- * {@link #getAllInvitableAccountTypes}). A usable invitable account type means:
- * (1) there is at least 1 raw contact in the database with that account type, and
- * (2) the app contributing the account type is not disabled.
- *
- * Warning: Don't use on the UI thread because this can scan the database.
- */
- private Map<AccountTypeWithDataSet, AccountType> findUsableInvitableAccountTypes(
- Context context) {
- Map<AccountTypeWithDataSet, AccountType> allInvitables = getAllInvitableAccountTypes();
- if (allInvitables.isEmpty()) {
- return EMPTY_UNMODIFIABLE_ACCOUNT_TYPE_MAP;
- }
-
- final HashMap<AccountTypeWithDataSet, AccountType> result = Maps.newHashMap();
- result.putAll(allInvitables);
-
- final PackageManager packageManager = context.getPackageManager();
- for (AccountTypeWithDataSet accountTypeWithDataSet : allInvitables.keySet()) {
- AccountType accountType = allInvitables.get(accountTypeWithDataSet);
-
- // Make sure that account types don't come from apps that are disabled.
- Intent invitableIntent = MoreContactUtils.getInvitableIntent(accountType,
- SAMPLE_CONTACT_URI);
- if (invitableIntent == null) {
- result.remove(accountTypeWithDataSet);
- continue;
- }
- ResolveInfo resolveInfo = packageManager.resolveActivity(invitableIntent,
- PackageManager.MATCH_DEFAULT_ONLY);
- if (resolveInfo == null) {
- // If we can't find an activity to start for this intent, then there's no point in
- // showing this option to the user.
- result.remove(accountTypeWithDataSet);
- continue;
- }
-
- // Make sure that there is at least 1 raw contact with this account type. This check
- // is non-trivial and should not be done on the UI thread.
- if (!accountTypeWithDataSet.hasData(context)) {
- result.remove(accountTypeWithDataSet);
- }
- }
-
- return Collections.unmodifiableMap(result);
- }
-
- @Override
- public List<AccountType> getAccountTypes(boolean contactWritableOnly) {
- ensureAccountsLoaded();
- final List<AccountType> accountTypes = Lists.newArrayList();
- synchronized (this) {
- for (AccountType type : mAccountTypesWithDataSets.values()) {
- if (!contactWritableOnly || type.areContactsWritable()) {
- accountTypes.add(type);
- }
- }
- }
- return accountTypes;
- }
-
- /**
- * Background task to find all usable {@link AccountType}s that support the "invite" feature
- * from the list of all potential invitable account types. Once the work is completed,
- * the list of account types is stored in the {@link AccountTypeManager}'s
- * {@link InvitableAccountTypeCache}.
- */
- private class FindInvitablesTask extends AsyncTask<Void, Void,
- Map<AccountTypeWithDataSet, AccountType>> {
-
- @Override
- protected Map<AccountTypeWithDataSet, AccountType> doInBackground(Void... params) {
- return findUsableInvitableAccountTypes(mContext);
- }
-
- @Override
- protected void onPostExecute(Map<AccountTypeWithDataSet, AccountType> accountTypes) {
- mInvitableAccountTypeCache.setCachedValue(accountTypes);
- mInvitablesTaskIsRunning.set(false);
- }
- }
-
- /**
- * This cache holds a list of invitable {@link AccountTypeWithDataSet}s, in the form of a
- * {@link Map<AccountTypeWithDataSet, AccountType>}. Note that the cached value is valid only
- * for {@link #TIME_TO_LIVE} milliseconds.
- */
- private static final class InvitableAccountTypeCache {
-
- /**
- * The cached {@link #mInvitableAccountTypes} list expires after this number of milliseconds
- * has elapsed.
- */
- private static final long TIME_TO_LIVE = 60000;
-
- private Map<AccountTypeWithDataSet, AccountType> mInvitableAccountTypes;
-
- private long mTimeLastSet;
-
- /**
- * Returns true if the data in this cache is stale and needs to be refreshed. Returns false
- * otherwise.
- */
- public boolean isExpired() {
- return SystemClock.elapsedRealtime() - mTimeLastSet > TIME_TO_LIVE;
- }
-
- /**
- * Returns the cached value. Note that the caller is responsible for checking
- * {@link #isExpired()} to ensure that the value is not stale.
- */
- public Map<AccountTypeWithDataSet, AccountType> getCachedValue() {
- return mInvitableAccountTypes;
- }
-
- public void setCachedValue(Map<AccountTypeWithDataSet, AccountType> map) {
- mInvitableAccountTypes = map;
- mTimeLastSet = SystemClock.elapsedRealtime();
- }
- }
}
diff --git a/src/com/android/contacts/model/Contact.java b/src/com/android/contacts/model/Contact.java
index 9d7d9aaa2..82661236d 100644
--- a/src/com/android/contacts/model/Contact.java
+++ b/src/com/android/contacts/model/Contact.java
@@ -74,7 +74,6 @@ public class Contact {
private final Integer mPresence;
private ImmutableList<RawContact> mRawContacts;
private ImmutableMap<Long,DataStatus> mStatuses;
- private ImmutableList<AccountType> mInvitableAccountTypes;
private String mDirectoryDisplayName;
private String mDirectoryType;
@@ -123,7 +122,6 @@ public class Contact {
mPhoneticName = null;
mStarred = false;
mPresence = null;
- mInvitableAccountTypes = null;
mSendToVoicemail = false;
mCustomRingtone = null;
mIsUserProfile = false;
@@ -164,7 +162,6 @@ public class Contact {
mPhoneticName = phoneticName;
mStarred = starred;
mPresence = presence;
- mInvitableAccountTypes = null;
mSendToVoicemail = sendToVoicemail;
mCustomRingtone = customRingtone;
mIsUserProfile = isUserProfile;
@@ -191,7 +188,6 @@ public class Contact {
mPresence = from.mPresence;
mRawContacts = from.mRawContacts;
mStatuses = from.mStatuses;
- mInvitableAccountTypes = from.mInvitableAccountTypes;
mDirectoryDisplayName = from.mDirectoryDisplayName;
mDirectoryType = from.mDirectoryType;
@@ -349,15 +345,6 @@ public class Contact {
return mPresence;
}
- /**
- * This can return non-null invitable account types only if the {@link ContactLoader} was
- * configured to load invitable account types in its constructor.
- * @return
- */
- public ImmutableList<AccountType> getInvitableAccountTypes() {
- return mInvitableAccountTypes;
- }
-
public ImmutableList<RawContact> getRawContacts() {
return mRawContacts;
}
@@ -503,10 +490,6 @@ public class Contact {
mStatuses = statuses;
}
- /* package */ void setInvitableAccountTypes(ImmutableList<AccountType> accountTypes) {
- mInvitableAccountTypes = accountTypes;
- }
-
/* package */ void setGroupMetaData(ImmutableList<GroupMetaData> groups) {
mGroups = groups;
}
diff --git a/src/com/android/contacts/model/ContactLoader.java b/src/com/android/contacts/model/ContactLoader.java
index a864a865d..acb821203 100644
--- a/src/com/android/contacts/model/ContactLoader.java
+++ b/src/com/android/contacts/model/ContactLoader.java
@@ -89,7 +89,6 @@ public class ContactLoader extends AsyncTaskLoader<Contact> {
private final Uri mRequestedUri;
private Uri mLookupUri;
private boolean mLoadGroupMetaData;
- private boolean mLoadInvitableAccountTypes;
private boolean mPostViewNotification;
private boolean mComputeFormattedPhoneNumber;
private Contact mContact;
@@ -97,22 +96,20 @@ public class ContactLoader extends AsyncTaskLoader<Contact> {
private final Set<Long> mNotifiedRawContactIds = Sets.newHashSet();
public ContactLoader(Context context, Uri lookupUri, boolean postViewNotification) {
- this(context, lookupUri, false, false, postViewNotification, false);
+ this(context, lookupUri, false, postViewNotification, false);
}
public ContactLoader(Context context, Uri lookupUri, boolean postViewNotification,
boolean loadGroupMetaData) {
- this(context, lookupUri, loadGroupMetaData, false, postViewNotification, false);
+ this(context, lookupUri, loadGroupMetaData, postViewNotification, false);
}
public ContactLoader(Context context, Uri lookupUri, boolean loadGroupMetaData,
- boolean loadInvitableAccountTypes,
boolean postViewNotification, boolean computeFormattedPhoneNumber) {
super(context);
mLookupUri = lookupUri;
mRequestedUri = lookupUri;
mLoadGroupMetaData = loadGroupMetaData;
- mLoadInvitableAccountTypes = loadInvitableAccountTypes;
mPostViewNotification = postViewNotification;
mComputeFormattedPhoneNumber = computeFormattedPhoneNumber;
}
@@ -344,10 +341,6 @@ public class ContactLoader extends AsyncTaskLoader<Contact> {
}
if (!resultIsCached) loadPhotoBinaryData(result);
- // Note ME profile should never have "Add connection"
- if (mLoadInvitableAccountTypes && result.getInvitableAccountTypes() == null) {
- loadInvitableAccountTypes(result);
- }
}
return result;
} catch (Exception e) {
@@ -591,35 +584,6 @@ public class ContactLoader extends AsyncTaskLoader<Contact> {
}
/**
- * Sets the "invitable" account types to {@link Contact#mInvitableAccountTypes}.
- */
- private void loadInvitableAccountTypes(Contact contactData) {
- final ImmutableList.Builder<AccountType> resultListBuilder =
- new ImmutableList.Builder<AccountType>();
- if (!contactData.isUserProfile()) {
- Map<AccountTypeWithDataSet, AccountType> invitables =
- AccountTypeManager.getInstance(getContext()).getUsableInvitableAccountTypes();
- if (!invitables.isEmpty()) {
- final Map<AccountTypeWithDataSet, AccountType> resultMap =
- Maps.newHashMap(invitables);
-
- // Remove the ones that already have a raw contact in the current contact
- for (RawContact rawContact : contactData.getRawContacts()) {
- final AccountTypeWithDataSet type = AccountTypeWithDataSet.get(
- rawContact.getAccountTypeString(),
- rawContact.getDataSet());
- resultMap.remove(type);
- }
-
- resultListBuilder.addAll(resultMap.values());
- }
- }
-
- // Set to mInvitableAccountTypes
- contactData.setInvitableAccountTypes(resultListBuilder.build());
- }
-
- /**
* Extracts Contact level columns from the cursor.
*/
private Contact loadContactHeaderData(final Cursor cursor, Uri contactUri) {
@@ -954,28 +918,6 @@ public class ContactLoader extends AsyncTaskLoader<Contact> {
}
}
- /**
- * Fully upgrades this ContactLoader to one with all lists fully loaded. When done, the
- * new result will be delivered
- */
- public void upgradeToFullContact() {
- // Everything requested already? Nothing to do, so let's bail out
- if (mLoadGroupMetaData && mLoadInvitableAccountTypes
- && mPostViewNotification && mComputeFormattedPhoneNumber) return;
-
- mLoadGroupMetaData = true;
- mLoadInvitableAccountTypes = true;
- mPostViewNotification = true;
- mComputeFormattedPhoneNumber = true;
-
- // Cache the current result, so that we only load the "missing" parts of the contact.
- cacheResult();
-
- // Our load parameters have changed, so let's pretend the data has changed. Its the same
- // thing, essentially.
- onContentChanged();
- }
-
public Uri getLookupUri() {
return mLookupUri;
}
diff --git a/src/com/android/contacts/model/account/AccountWithDataSet.java b/src/com/android/contacts/model/account/AccountWithDataSet.java
index b0bb84d35..0f36918b6 100644
--- a/src/com/android/contacts/model/account/AccountWithDataSet.java
+++ b/src/com/android/contacts/model/account/AccountWithDataSet.java
@@ -30,7 +30,6 @@ import android.text.TextUtils;
import com.android.contacts.model.AccountTypeManager;
import com.android.contacts.preference.ContactsPreferences;
-
import com.google.common.base.Objects;
import com.google.common.collect.Lists;
@@ -281,3 +280,4 @@ public class AccountWithDataSet implements Parcelable {
return accounts.get(0);
}
}
+
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index 8bf7b68a0..1dfa10c3f 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -2318,8 +2318,8 @@ public class QuickContactActivity extends ContactsActivity {
// Load all contact data. We need loadGroupMetaData=true to determine whether the
// contact is invisible. If it is, we need to display an "Add to Contacts" MenuItem.
return new ContactLoader(getApplicationContext(), mLookupUri,
- true /*loadGroupMetaData*/, false /*loadInvitableAccountTypes*/,
- true /*postViewNotification*/, true /*computeFormattedPhoneNumber*/);
+ true /*loadGroupMetaData*/, true /*postViewNotification*/,
+ true /*computeFormattedPhoneNumber*/);
}
};
diff --git a/src/com/android/contacts/util/AccountFilterUtil.java b/src/com/android/contacts/util/AccountFilterUtil.java
index 0c36f5e80..3a6d49e4e 100644
--- a/src/com/android/contacts/util/AccountFilterUtil.java
+++ b/src/com/android/contacts/util/AccountFilterUtil.java
@@ -133,8 +133,8 @@ public class AccountFilterUtil {
DeviceLocalAccountTypeFactory deviceAccountTypeFactory) {
final ArrayList<ContactListFilter> accountFilters = Lists.newArrayList();
final AccountTypeManager accountTypeManager = AccountTypeManager.getInstance(context);
- final List<AccountWithDataSet> accounts = accountTypeManager.getSortedAccounts(
- /* defaultAccount */ getDefaultAccount(context), /* contactWritableOnly */ true);
+ final List<AccountWithDataSet> accounts = accountTypeManager.getAccounts(true);
+ AccountTypeManager.sortAccounts(getDefaultAccount(context), accounts);
for (AccountWithDataSet account : accounts) {
final AccountType accountType =
diff --git a/tests/src/com/android/contacts/editor/ContactEditorUtilsTest.java b/tests/src/com/android/contacts/editor/ContactEditorUtilsTest.java
index f6c2d1b1c..9756a0c50 100644
--- a/tests/src/com/android/contacts/editor/ContactEditorUtilsTest.java
+++ b/tests/src/com/android/contacts/editor/ContactEditorUtilsTest.java
@@ -79,37 +79,6 @@ public class ContactEditorUtilsTest extends AndroidTestCase {
mAccountTypes.mAccounts = accounts;
}
- public void testGetWritableAccountTypeStrings() {
- String[] types;
-
- // 0 writable types
- setAccountTypes();
-
- types = mTarget.getWritableAccountTypeStrings();
- MoreAsserts.assertEquals(types, new String[0]);
-
- // 1 writable type
- setAccountTypes(TYPE1);
-
- types = mTarget.getWritableAccountTypeStrings();
- MoreAsserts.assertEquals(Sets.newHashSet(TYPE1.accountType), Sets.newHashSet(types));
-
- // 2 writable types
- setAccountTypes(TYPE1, TYPE2EX);
-
- types = mTarget.getWritableAccountTypeStrings();
- MoreAsserts.assertEquals(Sets.newHashSet(TYPE1.accountType, TYPE2EX.accountType),
- Sets.newHashSet(types));
-
- // 3 writable types + 1 readonly type
- setAccountTypes(TYPE1, TYPE2, TYPE2EX, TYPE3);
-
- types = mTarget.getWritableAccountTypeStrings();
- MoreAsserts.assertEquals(
- Sets.newHashSet(TYPE1.accountType, TYPE2.accountType, TYPE2EX.accountType),
- Sets.newHashSet(types));
- }
-
/**
* Test for
* - {@link ContactEditorUtils#saveDefaultAccount}
diff --git a/tests/src/com/android/contacts/model/AccountTypeManagerTest.java b/tests/src/com/android/contacts/model/AccountTypeManagerTest.java
index da2e6c3bd..982517b1b 100644
--- a/tests/src/com/android/contacts/model/AccountTypeManagerTest.java
+++ b/tests/src/com/android/contacts/model/AccountTypeManagerTest.java
@@ -16,11 +16,8 @@
package com.android.contacts.model;
-import static org.mockito.Mockito.when;
-
import android.accounts.Account;
import android.accounts.AccountManager;
-import android.content.Context;
import android.content.SharedPreferences;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
@@ -29,7 +26,6 @@ import com.android.contacts.model.account.AccountType;
import com.android.contacts.model.account.AccountTypeWithDataSet;
import com.android.contacts.model.account.AccountWithDataSet;
import com.android.contacts.model.account.GoogleAccountType;
-
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
@@ -42,6 +38,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import static org.mockito.Mockito.when;
+
/**
* Test case for {@link com.android.contacts.model.AccountTypeManager}.
*
@@ -67,93 +65,6 @@ public class AccountTypeManagerTest extends AndroidTestCase {
MockitoAnnotations.initMocks(this);
}
- public void testFindAllInvitableAccountTypes() {
- final Context c = getContext();
-
- // Define account types.
- final AccountType typeA = new MockAccountType("type1", null, null);
- final AccountType typeB = new MockAccountType("type1", "minus", null);
- final AccountType typeC = new MockAccountType("type2", null, "c");
- final AccountType typeD = new MockAccountType("type2", "minus", "d");
-
- // Define users
- final AccountWithDataSet accountA1 = createAccountWithDataSet("a1", typeA);
- final AccountWithDataSet accountC1 = createAccountWithDataSet("c1", typeC);
- final AccountWithDataSet accountC2 = createAccountWithDataSet("c2", typeC);
- final AccountWithDataSet accountD1 = createAccountWithDataSet("d1", typeD);
-
- // empty - empty
- Map<AccountTypeWithDataSet, AccountType> types =
- AccountTypeManagerImpl.findAllInvitableAccountTypes(c,
- buildAccounts(), buildAccountTypes());
- assertEquals(0, types.size());
- try {
- types.clear();
- fail("Returned Map should be unmodifiable.");
- } catch (UnsupportedOperationException ok) {
- }
-
- // No invite support, no accounts
- verifyAccountTypes(
- buildAccounts(),
- buildAccountTypes(typeA, typeB)
- /* empty */
- );
-
- // No invite support, with accounts
- verifyAccountTypes(
- buildAccounts(accountA1),
- buildAccountTypes(typeA)
- /* empty */
- );
-
- // With invite support, no accounts
- verifyAccountTypes(
- buildAccounts(),
- buildAccountTypes(typeC)
- /* empty */
- );
-
- // With invite support, 1 account
- verifyAccountTypes(
- buildAccounts(accountC1),
- buildAccountTypes(typeC),
- typeC
- );
-
- // With invite support, 2 account
- verifyAccountTypes(
- buildAccounts(accountC1, accountC2),
- buildAccountTypes(typeC),
- typeC
- );
-
- // Combinations...
- verifyAccountTypes(
- buildAccounts(accountA1),
- buildAccountTypes(typeA, typeC)
- /* empty */
- );
-
- verifyAccountTypes(
- buildAccounts(accountC1, accountA1),
- buildAccountTypes(typeA, typeC),
- typeC
- );
-
- verifyAccountTypes(
- buildAccounts(accountC1, accountA1),
- buildAccountTypes(typeD, typeA, typeC),
- typeC
- );
-
- verifyAccountTypes(
- buildAccounts(accountC1, accountA1, accountD1),
- buildAccountTypes(typeD, typeA, typeC, typeB),
- typeC, typeD
- );
- }
-
private static AccountWithDataSet createAccountWithDataSet(String name, AccountType type) {
return new AccountWithDataSet(name, type.accountType, type.dataSet);
}
@@ -180,51 +91,6 @@ public class AccountTypeManagerTest extends AndroidTestCase {
return result;
}
- /**
- * Executes {@link AccountTypeManagerImpl#findInvitableAccountTypes} and verifies the
- * result.
- */
- private void verifyAccountTypes(
- Collection<AccountWithDataSet> accounts,
- Map<AccountTypeWithDataSet, AccountType> types,
- AccountType... expectedInvitableTypes
- ) {
- Map<AccountTypeWithDataSet, AccountType> result =
- AccountTypeManagerImpl.findAllInvitableAccountTypes(getContext(), accounts, types);
- for (AccountType type : expectedInvitableTypes) {
- assertTrue("Result doesn't contain type=" + type.getAccountTypeAndDataSet(),
- result.containsKey(type.getAccountTypeAndDataSet()));
- }
- final int numExcessTypes = result.size() - expectedInvitableTypes.length;
- assertEquals("Result contains " + numExcessTypes + " excess type(s)", 0, numExcessTypes);
- }
-
- private static class MockAccountType extends AccountType {
- private final String mInviteContactActivityClassName;
-
- public MockAccountType(String type, String dataSet, String inviteContactActivityClassName) {
- accountType = type;
- this.dataSet = dataSet;
- mInviteContactActivityClassName = inviteContactActivityClassName;
- }
-
- @Override
- public String getInviteContactActivityClassName() {
- return mInviteContactActivityClassName;
- }
-
- @Override
- public boolean isGroupMembershipEditable() {
- return false;
- }
-
- @Override
- public boolean areContactsWritable() {
- return false;
- }
- }
-
-
public void testGetDefaultAccount_NoAccounts() {
assertNull(getDefaultGoogleAccountName());
}
diff --git a/tests/src/com/android/contacts/test/mocks/MockAccountTypeManager.java b/tests/src/com/android/contacts/test/mocks/MockAccountTypeManager.java
index 00686aa15..a69c87741 100644
--- a/tests/src/com/android/contacts/test/mocks/MockAccountTypeManager.java
+++ b/tests/src/com/android/contacts/test/mocks/MockAccountTypeManager.java
@@ -76,12 +76,6 @@ public class MockAccountTypeManager extends AccountTypeManager {
}
@Override
- public List<AccountWithDataSet> getSortedAccounts(AccountWithDataSet account,
- boolean writableOnly) {
- return Arrays.asList(mAccounts);
- }
-
- @Override
public List<AccountWithDataSet> getGroupWritableAccounts() {
return Arrays.asList(mAccounts);
}
@@ -90,22 +84,4 @@ public class MockAccountTypeManager extends AccountTypeManager {
public Account getDefaultGoogleAccount() {
return null;
}
-
- @Override
- public Map<AccountTypeWithDataSet, AccountType> getUsableInvitableAccountTypes() {
- return Maps.newHashMap(); // Always returns empty
- }
-
- @Override
- public List<AccountType> getAccountTypes(boolean writableOnly) {
- final List<AccountType> ret = Lists.newArrayList();
- synchronized (this) {
- for (AccountType type : mTypes) {
- if (!writableOnly || type.areContactsWritable()) {
- ret.add(type);
- }
- }
- }
- return ret;
- }
}