Add fields to AccountType for the new "invite" feature
- Add two attributes, inviteContactActivity and inviteContactActionLabel,
to the contacts.xml file, in addition to the existing ones such as
editContactActivity.
e.g.
<ContactsAccountType
xmlns:android="http://schemas.android.com/apk/res/android"
inviteContactActivity="com....editor.InviteContactActivity"
inviteContactActionLabel="@string/invite_action_label">
- Add two methods to AccountType to obtain the new attributes.
(getInviteContactActionLabel() will return a localized string)
- Add AccountTypeManager.getInvitableAccountTypes() which returns
AccountType's which define the invite activity and have one or more account.
Change-Id: I545b47a7e4957765684314870739085ea0355a98
diff --git a/src/com/android/contacts/model/AccountType.java b/src/com/android/contacts/model/AccountType.java
index 563658a..70aa430 100644
--- a/src/com/android/contacts/model/AccountType.java
+++ b/src/com/android/contacts/model/AccountType.java
@@ -18,6 +18,7 @@
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
+import com.google.common.annotations.VisibleForTesting;
import android.accounts.Account;
import android.content.ContentValues;
@@ -45,6 +46,8 @@
* In the future this may be inflated from XML defined by a data source.
*/
public abstract class AccountType {
+ private static final String TAG = "AccountType";
+
/**
* The {@link RawContacts#ACCOUNT_TYPE} these constraints apply to.
*/
@@ -92,14 +95,51 @@
return null;
}
+ /**
+ * Returns an optional custom invite contact activity. The activity class should reside
+ * in the sync adapter package as determined by {@link #resPackageName}.
+ */
+ public String getInviteContactActivityClassName() {
+ return null;
+ }
+
public CharSequence getDisplayLabel(Context context) {
- if (this.titleRes != -1 && this.summaryResPackageName != null) {
+ return getResourceText(context, summaryResPackageName, titleRes, accountType);
+ }
+
+ /**
+ * @return resource ID for the "invite contact" action label, or -1 if not defined.
+ */
+ protected int getInviteContactActionResId(Context conext) {
+ return -1;
+ }
+
+ /**
+ * Returns an optional custom label for the "invite contact" action, which will be shown on
+ * the contact card. (If not defined, returns null.)
+ */
+ public CharSequence getInviteContactActionLabel(Context context) {
+ return getResourceText(context, summaryResPackageName, getInviteContactActionResId(context),
+ null);
+ }
+
+ /**
+ * Return a string resource loaded from the given package (or the current package
+ * if {@code packageName} is null), unless {@code resId} is -1, in which case it returns
+ * {@code defaultValue}.
+ *
+ * (The behavior is undefined if the resource or package doesn't exist.)
+ */
+ @VisibleForTesting
+ static CharSequence getResourceText(Context context, String packageName, int resId,
+ String defaultValue) {
+ if (resId != -1 && packageName != null) {
final PackageManager pm = context.getPackageManager();
- return pm.getText(this.summaryResPackageName, this.titleRes, null);
- } else if (this.titleRes != -1) {
- return context.getText(this.titleRes);
+ return pm.getText(packageName, resId, null);
+ } else if (resId != -1) {
+ return context.getText(resId);
} else {
- return this.accountType;
+ return defaultValue;
}
}
diff --git a/src/com/android/contacts/model/AccountTypeManager.java b/src/com/android/contacts/model/AccountTypeManager.java
index 58195a1..ea2568f 100644
--- a/src/com/android/contacts/model/AccountTypeManager.java
+++ b/src/com/android/contacts/model/AccountTypeManager.java
@@ -18,6 +18,7 @@
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
+import com.google.common.annotations.VisibleForTesting;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import android.accounts.Account;
@@ -39,13 +40,16 @@
import android.os.RemoteException;
import android.os.SystemClock;
import android.provider.ContactsContract;
+import android.text.TextUtils;
import android.util.Log;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Locale;
+import java.util.Map;
import java.util.concurrent.CountDownLatch;
/**
@@ -80,6 +84,12 @@
public abstract AccountType getAccountType(String accountType);
/**
+ * @return Unmodifiable map from account type strings to {@link AccountType}s which support
+ * the "invite" feature and have one or more account.
+ */
+ public abstract Map<String, AccountType> getInvitableAccountTypes();
+
+ /**
* Find the best {@link DataKind} matching the requested
* {@link AccountType#accountType} and {@link DataKind#mimeType}. If no
* direct match found, we try searching {@link FallbackAccountType}.
@@ -101,6 +111,8 @@
private ArrayList<Account> mAccounts = Lists.newArrayList();
private ArrayList<Account> mWritableAccounts = Lists.newArrayList();
private HashMap<String, AccountType> mAccountTypes = Maps.newHashMap();
+ private Map<String, AccountType> mInvitableAccountTypes = Collections.unmodifiableMap(
+ new HashMap<String, AccountType>());
private static final int MESSAGE_LOAD_DATA = 0;
private static final int MESSAGE_PROCESS_BROADCAST_INTENT = 1;
@@ -308,6 +320,7 @@
mAccountTypes = accountTypes;
mAccounts = allAccounts;
mWritableAccounts = writableAccounts;
+ mInvitableAccountTypes = findInvitableAccountTypes(mContext, allAccounts, accountTypes);
}
Log.i(TAG, "Loaded meta-data for " + mAccountTypes.size() + " account types, "
@@ -381,4 +394,34 @@
return type != null ? type : mFallbackAccountType;
}
}
+
+ @Override
+ public Map<String, AccountType> getInvitableAccountTypes() {
+ return mInvitableAccountTypes;
+ }
+
+ /**
+ * 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<String, AccountType> findInvitableAccountTypes(Context context,
+ Collection<Account> accounts, Map<String, AccountType> accountTypes) {
+ HashMap<String, AccountType> result = Maps.newHashMap();
+ for (Account account : accounts) {
+ AccountType type = accountTypes.get(account.type);
+ if (type == null) continue; // just in case
+ if (result.containsKey(type.accountType)) continue;
+
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Type " + type.accountType
+ + " inviteClass=" + type.getInviteContactActivityClassName()
+ + " inviteAction=" + type.getInviteContactActionLabel(context));
+ }
+ if (!TextUtils.isEmpty(type.getInviteContactActivityClassName())) {
+ result.put(type.accountType, type);
+ }
+ }
+ return Collections.unmodifiableMap(result);
+ }
}
diff --git a/src/com/android/contacts/model/ExternalAccountType.java b/src/com/android/contacts/model/ExternalAccountType.java
index 9ce6fd9..4e6add0 100644
--- a/src/com/android/contacts/model/ExternalAccountType.java
+++ b/src/com/android/contacts/model/ExternalAccountType.java
@@ -16,16 +16,21 @@
package com.android.contacts.model;
+import com.google.common.annotations.VisibleForTesting;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
+import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Xml;
@@ -48,9 +53,14 @@
private static final String ATTR_EDIT_CONTACT_ACTIVITY = "editContactActivity";
private static final String ATTR_CREATE_CONTACT_ACTIVITY = "createContactActivity";
+ private static final String ATTR_INVITE_CONTACT_ACTIVITY = "inviteContactActivity";
+ private static final String ATTR_INVITE_CONTACT_ACTION_LABEL = "inviteContactActionLabel";
private String mEditContactActivityClassName;
private String mCreateContactActivityClassName;
+ private String mInviteContactActivity;
+ private String mInviteActionLabelAttribute;
+ private int mInviteActionLabelResId;
public ExternalAccountType(Context context, String resPackageName) {
this.resPackageName = resPackageName;
@@ -71,6 +81,9 @@
}
}
+ mInviteActionLabelResId = resolveExternalResId(context, mInviteActionLabelAttribute,
+ summaryResPackageName, ATTR_INVITE_CONTACT_ACTION_LABEL);
+
// Bring in name and photo from fallback source, which are non-optional
addDataKindStructuredName(context);
addDataKindDisplayName(context);
@@ -93,6 +106,16 @@
return mCreateContactActivityClassName;
}
+ @Override
+ public String getInviteContactActivityClassName() {
+ return mInviteContactActivity;
+ }
+
+ @Override
+ protected int getInviteContactActionResId(Context context) {
+ return mInviteActionLabelResId;
+ }
+
/**
* Inflate this {@link AccountType} from the given parser. This may only
* load details matching the publicly-defined schema.
@@ -121,10 +144,18 @@
int attributeCount = parser.getAttributeCount();
for (int i = 0; i < attributeCount; i++) {
String attr = parser.getAttributeName(i);
+ String value = parser.getAttributeValue(i);
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, attr + "=" + value);
+ }
if (ATTR_EDIT_CONTACT_ACTIVITY.equals(attr)) {
- mEditContactActivityClassName = parser.getAttributeValue(i);
+ mEditContactActivityClassName = value;
} else if (ATTR_CREATE_CONTACT_ACTIVITY.equals(attr)) {
- mCreateContactActivityClassName = parser.getAttributeValue(i);
+ mCreateContactActivityClassName = value;
+ } else if (ATTR_INVITE_CONTACT_ACTIVITY.equals(attr)) {
+ mInviteContactActivity = value;
+ } else if (ATTR_INVITE_CONTACT_ACTION_LABEL.equals(attr)) {
+ mInviteActionLabelAttribute = value;
} else {
Log.e(TAG, "Unsupported attribute " + attr);
}
@@ -172,6 +203,7 @@
}
addKind(kind);
+ a.recycle();
}
} catch (XmlPullParserException e) {
throw new IllegalStateException("Problem reading XML", e);
@@ -189,4 +221,41 @@
public int getSideBarColor(Context context) {
return 0xff6d86b4;
}
+
+ /**
+ * Takes a string in the "@xxx/yyy" format and return the resource ID for the resource in
+ * the resource package.
+ *
+ * If the argument is in the invalid format or isn't a resource name, it returns -1.
+ *
+ * @param context context
+ * @param resourceName Resource name in the "@xxx/yyy" format, e.g. "@string/invite_lavbel"
+ * @param packageName name of the package containing the resource.
+ * @param xmlAttributeName attribute name which the resource came from. Used for logging.
+ */
+ @VisibleForTesting
+ static int resolveExternalResId(Context context, String resourceName,
+ String packageName, String xmlAttributeName) {
+ if (TextUtils.isEmpty(resourceName)) {
+ return -1; // Empty text is okay.
+ }
+ if (resourceName.charAt(0) != '@') {
+ Log.e(TAG, xmlAttributeName + " must be a resource name beginnig with '@'");
+ return -1;
+ }
+ final String name = resourceName.substring(1);
+ final Resources res;
+ try {
+ res = context.getPackageManager().getResourcesForApplication(packageName);
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Unable to load package " + packageName);
+ return -1;
+ }
+ final int resId = res.getIdentifier(name, null, packageName);
+ if (resId == 0) {
+ Log.e(TAG, "Unable to load " + resourceName + " from package " + packageName);
+ return -1;
+ }
+ return resId;
+ }
}
diff --git a/tests/res/values/donottranslate_strings.xml b/tests/res/values/donottranslate_strings.xml
index 9f9f5a4..df74655 100644
--- a/tests/res/values/donottranslate_strings.xml
+++ b/tests/res/values/donottranslate_strings.xml
@@ -17,6 +17,7 @@
<string name="contactsIntents">Contacts Intents</string>
<string name="result">Result returned by activity</string>
+ <string name="test_string">TEST STRING</string>
<string-array name="allIntents">
<!-- List modes -->
diff --git a/tests/src/com/android/contacts/model/AccountTypeManagerTest.java b/tests/src/com/android/contacts/model/AccountTypeManagerTest.java
new file mode 100644
index 0000000..e5cf080
--- /dev/null
+++ b/tests/src/com/android/contacts/model/AccountTypeManagerTest.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.model;
+
+import com.google.android.collect.Lists;
+import com.google.android.collect.Maps;
+
+import android.accounts.Account;
+import android.content.Context;
+import android.test.AndroidTestCase;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Test case for {@link AccountTypeManager}.
+ *
+ * adb shell am instrument -w -e class com.android.contacts.model.AccountTypeManagerTest \
+ com.android.contacts.tests/android.test.InstrumentationTestRunner
+ */
+public class AccountTypeManagerTest extends AndroidTestCase {
+ public void testFindInvitableAccountTypes() {
+ final Context c = getContext();
+
+ // Define account types.
+ final AccountType typeA = new MockAccountType("typeA", null);
+ final AccountType typeB = new MockAccountType("typeB", null);
+ final AccountType typeC = new MockAccountType("typeC", "c");
+ final AccountType typeD = new MockAccountType("typeD", "d");
+
+ // Define users
+ final Account accountA1 = new Account("a1", typeA.accountType);
+ final Account accountC1 = new Account("c1", typeC.accountType);
+ final Account accountC2 = new Account("c2", typeC.accountType);
+ final Account accountD1 = new Account("d1", typeD.accountType);
+
+ // empty - empty
+ Map<String, AccountType> types = AccountTypeManagerImpl.findInvitableAccountTypes(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)
+ /* 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),
+ typeC, typeD
+ );
+ }
+
+ /**
+ * Array of {@link AccountType} -> {@link Map}
+ */
+ private static Map<String, AccountType> buildAccountTypes(AccountType... types) {
+ final HashMap<String, AccountType> result = Maps.newHashMap();
+ for (AccountType type : types) {
+ result.put(type.accountType, type);
+ }
+ return result;
+ }
+
+ /**
+ * Array of {@link Account} -> {@link Collection}
+ */
+ private static Collection<Account> buildAccounts(Account... accounts) {
+ final ArrayList<Account> result = Lists.newArrayList();
+ for (Account account : accounts) {
+ result.add(account);
+ }
+ return result;
+ }
+
+ /**
+ * Executes {@link AccountTypeManagerImpl#findInvitableAccountTypes} and verifies the
+ * result.
+ */
+ private void verifyAccountTypes(Collection<Account> accounts,
+ Map<String, AccountType> types, AccountType... expectedTypes) {
+ Map<String, AccountType> result = AccountTypeManagerImpl.findInvitableAccountTypes(
+ getContext(), accounts, types);
+ for (AccountType type : expectedTypes) {
+ if (!result.containsKey(type.accountType)) {
+ fail("Result doesn't contain type=" + type.accountType);
+ }
+ }
+ }
+
+ private static class MockAccountType extends AccountType {
+ private final String mInviteContactActivityClassName;
+
+ public MockAccountType(String type, String inviteContactActivityClassName) {
+ accountType = type;
+ mInviteContactActivityClassName = inviteContactActivityClassName;
+ }
+
+ @Override
+ public String getInviteContactActivityClassName() {
+ return mInviteContactActivityClassName;
+ }
+
+ @Override
+ public int getHeaderColor(Context context) {
+ return 0;
+ }
+
+ @Override
+ public int getSideBarColor(Context context) {
+ return 0;
+ }
+
+ @Override
+ public boolean isGroupMembershipEditable() {
+ return false;
+ }
+ }
+}
diff --git a/tests/src/com/android/contacts/model/AccountTypeTest.java b/tests/src/com/android/contacts/model/AccountTypeTest.java
new file mode 100644
index 0000000..4898cf3
--- /dev/null
+++ b/tests/src/com/android/contacts/model/AccountTypeTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.model;
+
+import com.android.contacts.tests.R;
+
+import android.content.Context;
+import android.test.AndroidTestCase;
+
+/**
+ * Test case for {@link AccountType}.
+ *
+ * adb shell am instrument -w -e class com.android.contacts.model.AccountTypeTest \
+ com.android.contacts.tests/android.test.InstrumentationTestRunner
+ */
+public class AccountTypeTest extends AndroidTestCase {
+ public void testGetResourceText() {
+ // In this test we use the test package itself as an external package.
+ final String packageName = getTestContext().getPackageName();
+
+ final Context c = getContext();
+ final String DEFAULT = "ABC";
+
+ // Package name null, resId -1, use the default
+ assertEquals(DEFAULT, AccountType.getResourceText(c, null, -1, DEFAULT));
+
+ // Resource ID -1, use the default
+ assertEquals(DEFAULT, AccountType.getResourceText(c, packageName, -1, DEFAULT));
+
+ // Load from an external package. (here, we use this test package itself)
+ final int externalResID = R.string.test_string;
+ assertEquals(getTestContext().getString(externalResID),
+ AccountType.getResourceText(c, packageName, externalResID, DEFAULT));
+
+ // Load from the contacts package itself.
+ final int internalResId = com.android.contacts.R.string.sharedUserLabel;
+ assertEquals(c.getString(internalResId),
+ AccountType.getResourceText(c, null, internalResId, DEFAULT));
+ }
+
+ /**
+ * Verify if {@link AccountType#getInviteContactActionLabel} correctly gets the resource ID
+ * from {@link AccountType#getInviteContactActionResId}
+ */
+ public void testGetInviteContactActionLabel() {
+ final String packageName = getTestContext().getPackageName();
+ final Context c = getContext();
+
+ final int externalResID = R.string.test_string;
+
+ AccountType accountType = new AccountType() {
+ {
+ resPackageName = packageName;
+ summaryResPackageName = packageName;
+ }
+ @Override protected int getInviteContactActionResId(Context conext) {
+ return externalResID;
+ }
+
+ @Override public int getHeaderColor(Context context) {
+ return 0;
+ }
+
+ @Override public int getSideBarColor(Context context) {
+ return 0;
+ }
+
+ @Override public boolean isGroupMembershipEditable() {
+ return false;
+ }
+ };
+
+ assertEquals(getTestContext().getString(externalResID),
+ accountType.getInviteContactActionLabel(c));
+ }
+}
diff --git a/tests/src/com/android/contacts/model/ExternalAccountTypeTest.java b/tests/src/com/android/contacts/model/ExternalAccountTypeTest.java
new file mode 100644
index 0000000..e7ef496
--- /dev/null
+++ b/tests/src/com/android/contacts/model/ExternalAccountTypeTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.model;
+
+import com.android.contacts.tests.R;
+
+import android.content.Context;
+import android.test.AndroidTestCase;
+
+/**
+ * Test case for {@link ExternalAccountType}.
+ *
+ * adb shell am instrument -w -e class com.android.contacts.model.ExternalAccountTypeTest \
+ com.android.contacts.tests/android.test.InstrumentationTestRunner
+ */
+public class ExternalAccountTypeTest extends AndroidTestCase {
+
+ public void testResolveExternalResId() {
+ final Context c = getContext();
+ // In this test we use the test package itself as an external package.
+ final String packageName = getTestContext().getPackageName();
+
+ // Resource name empty.
+ assertEquals(-1, ExternalAccountType.resolveExternalResId(c, null, packageName, ""));
+ assertEquals(-1, ExternalAccountType.resolveExternalResId(c, "", packageName, ""));
+
+ // Name doesn't begin with '@'
+ assertEquals(-1, ExternalAccountType.resolveExternalResId(c, "x", packageName, ""));
+
+ // Invalid resource name
+ assertEquals(-1, ExternalAccountType.resolveExternalResId(c, "@", packageName, ""));
+ assertEquals(-1, ExternalAccountType.resolveExternalResId(c, "@a", packageName, ""));
+ assertEquals(-1, ExternalAccountType.resolveExternalResId(c, "@a/b", packageName, ""));
+
+ // Valid resource name
+ assertEquals(R.string.test_string, ExternalAccountType.resolveExternalResId(c,
+ "@string/test_string", packageName, ""));
+ }
+}
diff --git a/tests/src/com/android/contacts/tests/mocks/MockAccountTypeManager.java b/tests/src/com/android/contacts/tests/mocks/MockAccountTypeManager.java
index 2635a09..acfa7f5 100644
--- a/tests/src/com/android/contacts/tests/mocks/MockAccountTypeManager.java
+++ b/tests/src/com/android/contacts/tests/mocks/MockAccountTypeManager.java
@@ -17,11 +17,14 @@
import com.android.contacts.model.AccountType;
import com.android.contacts.model.AccountTypeManager;
+import com.google.android.collect.Maps;
import android.accounts.Account;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
/**
* A mock {@link AccountTypeManager} class.
@@ -50,4 +53,9 @@
public ArrayList<Account> getAccounts(boolean writableOnly) {
return new ArrayList<Account>(Arrays.asList(mAccounts));
}
+
+ @Override
+ public Map<String, AccountType> getInvitableAccountTypes() {
+ return Maps.newHashMap(); // Always returns empty
+ }
}