Moving PhoneNumberInteraction to Dialer.
And moving dependent related resources and test classes.
Bug: 6993891
Change-Id: I4962098d6b1e05d16a6721bbf889f9e3f26194a8
diff --git a/res/layout/phone_disambig_item.xml b/res/layout/phone_disambig_item.xml
deleted file mode 100755
index a31d08d..0000000
--- a/res/layout/phone_disambig_item.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:paddingLeft="30dip"
- android:paddingRight="30dip"
- android:minHeight="?android:attr/listPreferredItemHeight"
- android:gravity="center_vertical">
-
- <TextView
- android:id="@android:id/text1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textStyle="bold"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <TextView
- android:id="@android:id/text2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="-4dip"
- android:textAppearance="?android:attr/textAppearanceSmall" />
-
-</LinearLayout>
diff --git a/res/layout/set_primary_checkbox.xml b/res/layout/set_primary_checkbox.xml
deleted file mode 100644
index 00b0865..0000000
--- a/res/layout/set_primary_checkbox.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingLeft="14dip"
- android:paddingRight="15dip"
- android:orientation="vertical">
-
- <CheckBox
- android:id="@+id/setPrimary"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:focusable="true"
- android:clickable="true"
- android:text="@string/make_primary"/>
-</LinearLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0958dd8..8dc91cc 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -939,18 +939,9 @@
<string name="add_2sec_pause">Add 2-sec pause</string>
<string name="add_wait">Add wait</string>
- <!-- Title for the call disambiguation dialog -->
- <string name="call_disambig_title">Choose number</string>
-
<!-- Menu item label for call settings [CHAR LIMIT=30] -->
<string name="call_settings">Settings</string>
- <!-- Title for the sms disambiguation dialog -->
- <string name="sms_disambig_title">Choose number</string>
-
- <!-- Message next to disamgiguation dialog check box -->
- <string name="make_primary">Remember this choice</string>
-
<!-- Shown as a toast when the user taps on a QuickContact icon, and no application
was found that could perform the selected action. [CHAR LIMIT=NONE] -->
<string name="quickcontact_missing_app">No app was found to handle this action.</string>
diff --git a/src/com/android/contacts/interactions/PhoneNumberInteraction.java b/src/com/android/contacts/interactions/PhoneNumberInteraction.java
deleted file mode 100644
index 2cf0601..0000000
--- a/src/com/android/contacts/interactions/PhoneNumberInteraction.java
+++ /dev/null
@@ -1,474 +0,0 @@
-/*
- * Copyright (C) 2010 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.interactions;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.app.FragmentManager;
-import android.content.Context;
-import android.content.CursorLoader;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnDismissListener;
-import android.content.Intent;
-import android.content.Loader;
-import android.content.Loader.OnLoadCompleteListener;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.CommonDataKinds.SipAddress;
-import android.provider.ContactsContract.Contacts;
-import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.RawContacts;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.CheckBox;
-import android.widget.ListAdapter;
-import android.widget.TextView;
-
-import com.android.contacts.ContactSaveService;
-import com.android.contacts.R;
-import com.android.contacts.common.CallUtil;
-import com.android.contacts.common.Collapser;
-import com.android.contacts.common.Collapser.Collapsible;
-import com.android.contacts.common.MoreContactUtils;
-import com.android.contacts.common.activity.TransactionSafeActivity;
-import com.android.contacts.common.util.ContactDisplayUtils;
-import com.google.common.annotations.VisibleForTesting;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Initiates phone calls or a text message. If there are multiple candidates, this class shows a
- * dialog to pick one. Creating one of these interactions should be done through the static
- * factory methods.
- *
- * Note that this class initiates not only usual *phone* calls but also *SIP* calls.
- *
- * TODO: clean up code and documents since it is quite confusing to use "phone numbers" or
- * "phone calls" here while they can be SIP addresses or SIP calls (See also issue 5039627).
- */
-public class PhoneNumberInteraction implements OnLoadCompleteListener<Cursor> {
- private static final String TAG = PhoneNumberInteraction.class.getSimpleName();
-
- /**
- * A model object for capturing a phone number for a given contact.
- */
- @VisibleForTesting
- /* package */ static class PhoneItem implements Parcelable, Collapsible<PhoneItem> {
- long id;
- String phoneNumber;
- String accountType;
- String dataSet;
- long type;
- String label;
- /** {@link Phone#CONTENT_ITEM_TYPE} or {@link SipAddress#CONTENT_ITEM_TYPE}. */
- String mimeType;
-
- public PhoneItem() {
- }
-
- private PhoneItem(Parcel in) {
- this.id = in.readLong();
- this.phoneNumber = in.readString();
- this.accountType = in.readString();
- this.dataSet = in.readString();
- this.type = in.readLong();
- this.label = in.readString();
- this.mimeType = in.readString();
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeLong(id);
- dest.writeString(phoneNumber);
- dest.writeString(accountType);
- dest.writeString(dataSet);
- dest.writeLong(type);
- dest.writeString(label);
- dest.writeString(mimeType);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public boolean collapseWith(PhoneItem phoneItem) {
- if (!shouldCollapseWith(phoneItem)) {
- return false;
- }
- // Just keep the number and id we already have.
- return true;
- }
-
- @Override
- public boolean shouldCollapseWith(PhoneItem phoneItem) {
- return MoreContactUtils.shouldCollapse(Phone.CONTENT_ITEM_TYPE, phoneNumber,
- Phone.CONTENT_ITEM_TYPE, phoneItem.phoneNumber);
- }
-
- @Override
- public String toString() {
- return phoneNumber;
- }
-
- public static final Parcelable.Creator<PhoneItem> CREATOR
- = new Parcelable.Creator<PhoneItem>() {
- @Override
- public PhoneItem createFromParcel(Parcel in) {
- return new PhoneItem(in);
- }
-
- @Override
- public PhoneItem[] newArray(int size) {
- return new PhoneItem[size];
- }
- };
- }
-
- /**
- * A list adapter that populates the list of contact's phone numbers.
- */
- private static class PhoneItemAdapter extends ArrayAdapter<PhoneItem> {
- private final int mInteractionType;
-
- public PhoneItemAdapter(Context context, List<PhoneItem> list,
- int interactionType) {
- super(context, R.layout.phone_disambig_item, android.R.id.text2, list);
- mInteractionType = interactionType;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- final View view = super.getView(position, convertView, parent);
-
- final PhoneItem item = getItem(position);
- final TextView typeView = (TextView) view.findViewById(android.R.id.text1);
- CharSequence value = ContactDisplayUtils.getLabelForCallOrSms((int) item.type,
- item.label, mInteractionType, getContext());
-
- typeView.setText(value);
- return view;
- }
- }
-
- /**
- * {@link DialogFragment} used for displaying a dialog with a list of phone numbers of which
- * one will be chosen to make a call or initiate an sms message.
- *
- * It is recommended to use
- * {@link PhoneNumberInteraction#startInteractionForPhoneCall(TransactionSafeActivity, Uri)} or
- * {@link PhoneNumberInteraction#startInteractionForTextMessage(TransactionSafeActivity, Uri)}
- * instead of directly using this class, as those methods handle one or multiple data cases
- * appropriately.
- */
- /* Made public to let the system reach this class */
- public static class PhoneDisambiguationDialogFragment extends DialogFragment
- implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
-
- private static final String ARG_PHONE_LIST = "phoneList";
- private static final String ARG_INTERACTION_TYPE = "interactionType";
- private static final String ARG_CALL_ORIGIN = "callOrigin";
-
- private int mInteractionType;
- private ListAdapter mPhonesAdapter;
- private List<PhoneItem> mPhoneList;
- private String mCallOrigin;
-
- public static void show(FragmentManager fragmentManager,
- ArrayList<PhoneItem> phoneList, int interactionType,
- String callOrigin) {
- PhoneDisambiguationDialogFragment fragment = new PhoneDisambiguationDialogFragment();
- Bundle bundle = new Bundle();
- bundle.putParcelableArrayList(ARG_PHONE_LIST, phoneList);
- bundle.putSerializable(ARG_INTERACTION_TYPE, interactionType);
- bundle.putString(ARG_CALL_ORIGIN, callOrigin);
- fragment.setArguments(bundle);
- fragment.show(fragmentManager, TAG);
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- final Activity activity = getActivity();
- mPhoneList = getArguments().getParcelableArrayList(ARG_PHONE_LIST);
- mInteractionType = getArguments().getInt(ARG_INTERACTION_TYPE);
- mCallOrigin = getArguments().getString(ARG_CALL_ORIGIN);
-
- mPhonesAdapter = new PhoneItemAdapter(activity, mPhoneList, mInteractionType);
- final LayoutInflater inflater = activity.getLayoutInflater();
- final View setPrimaryView = inflater.inflate(R.layout.set_primary_checkbox, null);
- return new AlertDialog.Builder(activity)
- .setAdapter(mPhonesAdapter, this)
- .setTitle(mInteractionType == ContactDisplayUtils.INTERACTION_SMS
- ? R.string.sms_disambig_title : R.string.call_disambig_title)
- .setView(setPrimaryView)
- .create();
- }
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- final Activity activity = getActivity();
- if (activity == null) return;
- final AlertDialog alertDialog = (AlertDialog)dialog;
- if (mPhoneList.size() > which && which >= 0) {
- final PhoneItem phoneItem = mPhoneList.get(which);
- final CheckBox checkBox = (CheckBox)alertDialog.findViewById(R.id.setPrimary);
- if (checkBox.isChecked()) {
- // Request to mark the data as primary in the background.
- final Intent serviceIntent = ContactSaveService.createSetSuperPrimaryIntent(
- activity, phoneItem.id);
- activity.startService(serviceIntent);
- }
-
- PhoneNumberInteraction.performAction(activity, phoneItem.phoneNumber,
- mInteractionType, mCallOrigin);
- } else {
- dialog.dismiss();
- }
- }
- }
-
- private static final String[] PHONE_NUMBER_PROJECTION = new String[] {
- Phone._ID,
- Phone.NUMBER,
- Phone.IS_SUPER_PRIMARY,
- RawContacts.ACCOUNT_TYPE,
- RawContacts.DATA_SET,
- Phone.TYPE,
- Phone.LABEL,
- Phone.MIMETYPE
- };
-
- private static final String PHONE_NUMBER_SELECTION =
- Data.MIMETYPE + " IN ('"
- + Phone.CONTENT_ITEM_TYPE + "', "
- + "'" + SipAddress.CONTENT_ITEM_TYPE + "') AND "
- + Data.DATA1 + " NOT NULL";
-
- private final Context mContext;
- private final OnDismissListener mDismissListener;
- private final int mInteractionType;
-
- private final String mCallOrigin;
-
- private CursorLoader mLoader;
-
- /**
- * Constructs a new {@link PhoneNumberInteraction}. The constructor takes in a {@link Context}
- * instead of a {@link TransactionSafeActivity} for testing purposes to verify the functionality
- * of this class. However, all factory methods for creating {@link PhoneNumberInteraction}s
- * require a {@link TransactionSafeActivity} (i.e. see {@link #startInteractionForPhoneCall}).
- */
- @VisibleForTesting
- /* package */ PhoneNumberInteraction(Context context, int interactionType,
- DialogInterface.OnDismissListener dismissListener) {
- this(context, interactionType, dismissListener, null);
- }
-
- private PhoneNumberInteraction(Context context, int interactionType,
- DialogInterface.OnDismissListener dismissListener, String callOrigin) {
- mContext = context;
- mInteractionType = interactionType;
- mDismissListener = dismissListener;
- mCallOrigin = callOrigin;
- }
-
- private void performAction(String phoneNumber) {
- PhoneNumberInteraction.performAction(mContext, phoneNumber, mInteractionType, mCallOrigin);
- }
-
- private static void performAction(
- Context context, String phoneNumber, int interactionType,
- String callOrigin) {
- Intent intent;
- switch (interactionType) {
- case ContactDisplayUtils.INTERACTION_SMS:
- intent = new Intent(
- Intent.ACTION_SENDTO, Uri.fromParts("sms", phoneNumber, null));
- break;
- default:
- intent = CallUtil.getCallIntent(phoneNumber, callOrigin);
- break;
- }
- context.startActivity(intent);
- }
-
- /**
- * Initiates the interaction. This may result in a phone call or sms message started
- * or a disambiguation dialog to determine which phone number should be used.
- */
- @VisibleForTesting
- /* package */ void startInteraction(Uri uri) {
- if (mLoader != null) {
- mLoader.reset();
- }
-
- final Uri queryUri;
- final String inputUriAsString = uri.toString();
- if (inputUriAsString.startsWith(Contacts.CONTENT_URI.toString())) {
- if (!inputUriAsString.endsWith(Contacts.Data.CONTENT_DIRECTORY)) {
- queryUri = Uri.withAppendedPath(uri, Contacts.Data.CONTENT_DIRECTORY);
- } else {
- queryUri = uri;
- }
- } else if (inputUriAsString.startsWith(Data.CONTENT_URI.toString())) {
- queryUri = uri;
- } else {
- throw new UnsupportedOperationException(
- "Input Uri must be contact Uri or data Uri (input: \"" + uri + "\")");
- }
-
- mLoader = new CursorLoader(mContext,
- queryUri,
- PHONE_NUMBER_PROJECTION,
- PHONE_NUMBER_SELECTION,
- null,
- null);
- mLoader.registerListener(0, this);
- mLoader.startLoading();
- }
-
- @Override
- public void onLoadComplete(Loader<Cursor> loader, Cursor cursor) {
- if (cursor == null || !isSafeToCommitTransactions()) {
- onDismiss();
- return;
- }
-
- ArrayList<PhoneItem> phoneList = new ArrayList<PhoneItem>();
- String primaryPhone = null;
- try {
- while (cursor.moveToNext()) {
- if (cursor.getInt(cursor.getColumnIndex(Phone.IS_SUPER_PRIMARY)) != 0) {
- // Found super primary, call it.
- primaryPhone = cursor.getString(cursor.getColumnIndex(Phone.NUMBER));
- break;
- }
-
- PhoneItem item = new PhoneItem();
- item.id = cursor.getLong(cursor.getColumnIndex(Data._ID));
- item.phoneNumber = cursor.getString(cursor.getColumnIndex(Phone.NUMBER));
- item.accountType =
- cursor.getString(cursor.getColumnIndex(RawContacts.ACCOUNT_TYPE));
- item.dataSet = cursor.getString(cursor.getColumnIndex(RawContacts.DATA_SET));
- item.type = cursor.getInt(cursor.getColumnIndex(Phone.TYPE));
- item.label = cursor.getString(cursor.getColumnIndex(Phone.LABEL));
- item.mimeType = cursor.getString(cursor.getColumnIndex(Phone.MIMETYPE));
-
- phoneList.add(item);
- }
- } finally {
- cursor.close();
- }
-
- if (primaryPhone != null) {
- performAction(primaryPhone);
- onDismiss();
- return;
- }
-
- Collapser.collapseList(phoneList);
-
- if (phoneList.size() == 0) {
- onDismiss();
- } else if (phoneList.size() == 1) {
- PhoneItem item = phoneList.get(0);
- onDismiss();
- performAction(item.phoneNumber);
- } else {
- // There are multiple candidates. Let the user choose one.
- showDisambiguationDialog(phoneList);
- }
- }
-
- private boolean isSafeToCommitTransactions() {
- return mContext instanceof TransactionSafeActivity ?
- ((TransactionSafeActivity) mContext).isSafeToCommitTransactions() : true;
- }
-
- private void onDismiss() {
- if (mDismissListener != null) {
- mDismissListener.onDismiss(null);
- }
- }
-
- /**
- * Start call action using given contact Uri. If there are multiple candidates for the phone
- * call, dialog is automatically shown and the user is asked to choose one.
- *
- * @param activity that is calling this interaction. This must be of type
- * {@link TransactionSafeActivity} because we need to check on the activity state after the
- * phone numbers have been queried for.
- * @param uri contact Uri (built from {@link Contacts#CONTENT_URI}) or data Uri
- * (built from {@link Data#CONTENT_URI}). Contact Uri may show the disambiguation dialog while
- * data Uri won't.
- */
- public static void startInteractionForPhoneCall(TransactionSafeActivity activity, Uri uri) {
- (new PhoneNumberInteraction(activity, ContactDisplayUtils.INTERACTION_CALL, null))
- .startInteraction(uri);
- }
-
- /**
- * @param activity that is calling this interaction. This must be of type
- * {@link TransactionSafeActivity} because we need to check on the activity state after the
- * phone numbers have been queried for.
- * @param callOrigin If non null, {@link PhoneConstants#EXTRA_CALL_ORIGIN} will be
- * appended to the Intent initiating phone call. See comments in Phone package (PhoneApp)
- * for more detail.
- */
- public static void startInteractionForPhoneCall(TransactionSafeActivity activity, Uri uri,
- String callOrigin) {
- (new PhoneNumberInteraction(activity, ContactDisplayUtils.INTERACTION_CALL, null, callOrigin))
- .startInteraction(uri);
- }
-
- /**
- * Start text messaging (a.k.a SMS) action using given contact Uri. If there are multiple
- * candidates for the phone call, dialog is automatically shown and the user is asked to choose
- * one.
- *
- * @param activity that is calling this interaction. This must be of type
- * {@link TransactionSafeActivity} because we need to check on the activity state after the
- * phone numbers have been queried for.
- * @param uri contact Uri (built from {@link Contacts#CONTENT_URI}) or data Uri
- * (built from {@link Data#CONTENT_URI}). Contact Uri may show the disambiguation dialog while
- * data Uri won't.
- */
- public static void startInteractionForTextMessage(TransactionSafeActivity activity, Uri uri) {
- (new PhoneNumberInteraction(activity, ContactDisplayUtils.INTERACTION_SMS, null))
- .startInteraction(uri);
- }
-
- @VisibleForTesting
- /* package */ CursorLoader getLoader() {
- return mLoader;
- }
-
- @VisibleForTesting
- /* package */ void showDisambiguationDialog(ArrayList<PhoneItem> phoneList) {
- PhoneDisambiguationDialogFragment.show(((Activity)mContext).getFragmentManager(),
- phoneList, mInteractionType, mCallOrigin);
- }
-}
diff --git a/tests/src/com/android/contacts/ContactDetailTest.java b/tests/src/com/android/contacts/ContactDetailTest.java
index 8d91d9e..ea1e40e 100644
--- a/tests/src/com/android/contacts/ContactDetailTest.java
+++ b/tests/src/com/android/contacts/ContactDetailTest.java
@@ -20,8 +20,8 @@
import android.test.suitebuilder.annotation.SmallTest;
import com.android.contacts.activities.ContactDetailActivity;
-import com.android.contacts.tests.mocks.ContactsMockContext;
-import com.android.contacts.tests.mocks.MockContentProvider;
+import com.android.contacts.common.test.mocks.ContactsMockContext;
+import com.android.contacts.common.test.mocks.MockContentProvider;
@SmallTest
public class ContactDetailTest extends ActivityUnitTestCase<ContactDetailActivity> {
diff --git a/tests/src/com/android/contacts/RawContactModifierTests.java b/tests/src/com/android/contacts/RawContactModifierTests.java
index 9caaffa..497bede 100644
--- a/tests/src/com/android/contacts/RawContactModifierTests.java
+++ b/tests/src/com/android/contacts/RawContactModifierTests.java
@@ -49,9 +49,9 @@
import com.android.contacts.model.account.ExchangeAccountType;
import com.android.contacts.model.account.GoogleAccountType;
import com.android.contacts.model.dataitem.DataKind;
-import com.android.contacts.tests.mocks.ContactsMockContext;
+import com.android.contacts.common.test.mocks.ContactsMockContext;
import com.android.contacts.tests.mocks.MockAccountTypeManager;
-import com.android.contacts.tests.mocks.MockContentProvider;
+import com.android.contacts.common.test.mocks.MockContentProvider;
import com.google.common.collect.Lists;
import java.util.ArrayList;
diff --git a/tests/src/com/android/contacts/activities/PeopleActivityTest.java b/tests/src/com/android/contacts/activities/PeopleActivityTest.java
index db7e5c0..cda7a57 100644
--- a/tests/src/com/android/contacts/activities/PeopleActivityTest.java
+++ b/tests/src/com/android/contacts/activities/PeopleActivityTest.java
@@ -32,9 +32,9 @@
import android.test.suitebuilder.annotation.SmallTest;
import android.widget.TextView;
-import com.android.contacts.common.ContactPhotoManager;
import com.android.contacts.ContactsApplication;
import com.android.contacts.R;
+import com.android.contacts.common.ContactPhotoManager;
import com.android.contacts.detail.ContactDetailFragment;
import com.android.contacts.interactions.TestLoaderManager;
import com.android.contacts.list.ContactBrowseListFragment;
@@ -43,11 +43,12 @@
import com.android.contacts.model.account.AccountWithDataSet;
import com.android.contacts.model.account.BaseAccountType;
import com.android.contacts.test.InjectedServices;
-import com.android.contacts.tests.mocks.ContactsMockContext;
+import com.android.contacts.tests.mocks.ContactsAccountManagerMockContext;
+import com.android.contacts.common.test.mocks.ContactsMockContext;
import com.android.contacts.tests.mocks.MockAccountTypeManager;
import com.android.contacts.tests.mocks.MockContactPhotoManager;
-import com.android.contacts.tests.mocks.MockContentProvider;
-import com.android.contacts.tests.mocks.MockContentProvider.Query;
+import com.android.contacts.common.test.mocks.MockContentProvider;
+import com.android.contacts.common.test.mocks.MockContentProvider.Query;
import com.android.contacts.tests.mocks.MockSharedPreferences;
import com.android.contacts.util.PhoneCapabilityTester;
@@ -86,7 +87,7 @@
@Override
public void setUp() {
- mContext = new ContactsMockContext(getInstrumentation().getTargetContext());
+ mContext = new ContactsAccountManagerMockContext(getInstrumentation().getTargetContext());
mContactsProvider = mContext.getContactsProvider();
mSettingsProvider = mContext.getSettingsProvider();
InjectedServices services = new InjectedServices();
@@ -106,7 +107,7 @@
services.setSystemService(AccountTypeManager.ACCOUNT_TYPE_SERVICE,
new MockAccountTypeManager(
- new AccountType[] { accountType }, new AccountWithDataSet[] { account }));
+ new AccountType[]{accountType}, new AccountWithDataSet[]{account}));
ContactsApplication.injectServices(services);
}
diff --git a/tests/src/com/android/contacts/interactions/ContactDeletionInteractionTest.java b/tests/src/com/android/contacts/interactions/ContactDeletionInteractionTest.java
index 3b856ea..c834688 100644
--- a/tests/src/com/android/contacts/interactions/ContactDeletionInteractionTest.java
+++ b/tests/src/com/android/contacts/interactions/ContactDeletionInteractionTest.java
@@ -31,10 +31,11 @@
import com.android.contacts.model.account.BaseAccountType;
import com.android.contacts.common.test.FragmentTestActivity;
import com.android.contacts.test.InjectedServices;
-import com.android.contacts.tests.mocks.ContactsMockContext;
+import com.android.contacts.tests.mocks.ContactsAccountManagerMockContext;
+import com.android.contacts.common.test.mocks.ContactsMockContext;
import com.android.contacts.tests.mocks.MockAccountTypeManager;
-import com.android.contacts.tests.mocks.MockContentProvider;
-import com.android.contacts.tests.mocks.MockContentProvider.Query;
+import com.android.contacts.common.test.mocks.MockContentProvider;
+import com.android.contacts.common.test.mocks.MockContentProvider.Query;
import com.android.contacts.common.test.IntegrationTestUtils;
/**
@@ -79,7 +80,7 @@
mUtils = new IntegrationTestUtils(getInstrumentation());
mUtils.acquireScreenWakeLock(getInstrumentation().getTargetContext());
- mContext = new ContactsMockContext(getInstrumentation().getTargetContext());
+ mContext = new ContactsAccountManagerMockContext(getInstrumentation().getTargetContext());
InjectedServices services = new InjectedServices();
services.setContentResolver(mContext.getContentResolver());
@@ -101,7 +102,7 @@
services.setSystemService(AccountTypeManager.ACCOUNT_TYPE_SERVICE,
new MockAccountTypeManager(
- new AccountType[] { writableAccountType, readOnlyAccountType }, null));
+ new AccountType[]{writableAccountType, readOnlyAccountType}, null));
ContactsApplication.injectServices(services);
mContactsProvider = mContext.getContactsProvider();
}
diff --git a/tests/src/com/android/contacts/interactions/PhoneNumberInteractionTest.java b/tests/src/com/android/contacts/interactions/PhoneNumberInteractionTest.java
deleted file mode 100644
index 4e347b7..0000000
--- a/tests/src/com/android/contacts/interactions/PhoneNumberInteractionTest.java
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Copyright (C) 2010 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.interactions;
-
-import android.content.ContentUris;
-import android.content.Context;
-import android.content.DialogInterface.OnDismissListener;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.CommonDataKinds.SipAddress;
-import android.provider.ContactsContract.Contacts;
-import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.RawContacts;
-import android.test.InstrumentationTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import com.android.contacts.common.util.ContactDisplayUtils;
-import com.android.contacts.interactions.PhoneNumberInteraction.PhoneItem;
-import com.android.contacts.tests.mocks.ContactsMockContext;
-import com.android.contacts.tests.mocks.MockContentProvider;
-import com.android.contacts.tests.mocks.MockContentProvider.Query;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Tests for {@link PhoneNumberInteraction}.
- *
- * Running all tests:
- *
- * runtest contacts
- * or
- * adb shell am instrument \
- * -w com.android.contacts.tests/android.test.InstrumentationTestRunner
- */
-@SmallTest
-public class PhoneNumberInteractionTest extends InstrumentationTestCase {
-
- static {
- // AsyncTask class needs to be initialized on the main thread.
- AsyncTask.init();
- }
-
- private final static class TestPhoneNumberInteraction extends PhoneNumberInteraction {
- private ArrayList<PhoneItem> mPhoneList;
-
- public TestPhoneNumberInteraction(Context context, int interactionType,
- OnDismissListener dismissListener) {
- super(context, interactionType, dismissListener);
- }
-
- @Override
- void showDisambiguationDialog(ArrayList<PhoneItem> phoneList) {
- this.mPhoneList = phoneList;
- }
- }
-
- private ContactsMockContext mContext;
- private MockContentProvider mContactsProvider;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mContext = new ContactsMockContext(getInstrumentation().getTargetContext());
- mContactsProvider = mContext.getContactsProvider();
- }
-
- @Override
- protected void tearDown() throws Exception {
- mContactsProvider.verify();
- super.tearDown();
- }
-
- public void testSendSmsWhenOnlyOneNumberAvailable() {
- Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, 13);
- expectQuery(contactUri)
- .returnRow(1, "123", 0, null, null, Phone.TYPE_HOME, null,
- Phone.CONTENT_ITEM_TYPE);
-
- TestPhoneNumberInteraction interaction = new TestPhoneNumberInteraction(
- mContext, ContactDisplayUtils.INTERACTION_SMS, null);
-
- interaction.startInteraction(contactUri);
- interaction.getLoader().waitForLoader();
-
- Intent intent = mContext.getIntentForStartActivity();
- assertNotNull(intent);
-
- assertEquals(Intent.ACTION_SENDTO, intent.getAction());
- assertEquals("sms:123", intent.getDataString());
- }
-
- public void testSendSmsWhenDataIdIsProvided() {
- Uri dataUri = ContentUris.withAppendedId(Data.CONTENT_URI, 1);
- expectQuery(dataUri, true /* isDataUri */ )
- .returnRow(1, "987", 0, null, null, Phone.TYPE_HOME, null,
- Phone.CONTENT_ITEM_TYPE);
-
- TestPhoneNumberInteraction interaction = new TestPhoneNumberInteraction(
- mContext, ContactDisplayUtils.INTERACTION_SMS, null);
-
- interaction.startInteraction(dataUri);
- interaction.getLoader().waitForLoader();
-
- Intent intent = mContext.getIntentForStartActivity();
- assertNotNull(intent);
-
- assertEquals(Intent.ACTION_SENDTO, intent.getAction());
- assertEquals("sms:987", intent.getDataString());
- }
-
- public void testSendSmsWhenThereIsPrimaryNumber() {
- Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, 13);
- expectQuery(contactUri)
- .returnRow(
- 1, "123", 0, null, null, Phone.TYPE_HOME, null, Phone.CONTENT_ITEM_TYPE)
- .returnRow(
- 2, "456", 1, null, null, Phone.TYPE_HOME, null, Phone.CONTENT_ITEM_TYPE);
-
- TestPhoneNumberInteraction interaction = new TestPhoneNumberInteraction(
- mContext, ContactDisplayUtils.INTERACTION_SMS, null);
-
- interaction.startInteraction(contactUri);
- interaction.getLoader().waitForLoader();
-
- Intent intent = mContext.getIntentForStartActivity();
- assertNotNull(intent);
-
- assertEquals(Intent.ACTION_SENDTO, intent.getAction());
- assertEquals("sms:456", intent.getDataString());
- }
-
- public void testShouldCollapseWith() {
- PhoneNumberInteraction.PhoneItem phoneItem1 = new PhoneNumberInteraction.PhoneItem();
- PhoneNumberInteraction.PhoneItem phoneItem2 = new PhoneNumberInteraction.PhoneItem();
-
- phoneItem1.phoneNumber = "123";
- phoneItem2.phoneNumber = "123";
-
- assertTrue(phoneItem1.shouldCollapseWith(phoneItem2));
-
- phoneItem1.phoneNumber = "123";
- phoneItem2.phoneNumber = "456";
-
- assertFalse(phoneItem1.shouldCollapseWith(phoneItem2));
-
- phoneItem1.phoneNumber = "123#,123";
- phoneItem2.phoneNumber = "123#,456";
-
- assertFalse(phoneItem1.shouldCollapseWith(phoneItem2));
- }
-
- public void testCallNumberWhenThereAreDuplicates() {
- Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, 13);
- expectQuery(contactUri)
- .returnRow(1, "123", 0, null, null, Phone.TYPE_HOME, null,
- Phone.CONTENT_ITEM_TYPE)
- .returnRow(2, "123", 0, null, null, Phone.TYPE_WORK, null,
- Phone.CONTENT_ITEM_TYPE);
-
- TestPhoneNumberInteraction interaction = new TestPhoneNumberInteraction(
- mContext, ContactDisplayUtils.INTERACTION_CALL, null);
-
- interaction.startInteraction(contactUri);
- interaction.getLoader().waitForLoader();
-
- Intent intent = mContext.getIntentForStartActivity();
- assertNotNull(intent);
-
- assertEquals(Intent.ACTION_CALL_PRIVILEGED, intent.getAction());
- assertEquals("tel:123", intent.getDataString());
- }
-
- public void testCallWithSip() {
- Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, 13);
- expectQuery(contactUri)
- .returnRow(1, "example@example.com", 0, null, null, Phone.TYPE_HOME, null,
- SipAddress.CONTENT_ITEM_TYPE);
- TestPhoneNumberInteraction interaction = new TestPhoneNumberInteraction(
- mContext, ContactDisplayUtils.INTERACTION_CALL, null);
-
- interaction.startInteraction(contactUri);
- interaction.getLoader().waitForLoader();
-
- Intent intent = mContext.getIntentForStartActivity();
- assertNotNull(intent);
-
- assertEquals(Intent.ACTION_CALL_PRIVILEGED, intent.getAction());
- assertEquals("sip:example%40example.com", intent.getDataString());
- }
-
- public void testShowDisambigDialogForCalling() {
- Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, 13);
- expectQuery(contactUri)
- .returnRow(1, "123", 0, "account", null, Phone.TYPE_HOME, "label",
- Phone.CONTENT_ITEM_TYPE)
- .returnRow(2, "456", 0, null, null, Phone.TYPE_WORK, null,
- Phone.CONTENT_ITEM_TYPE);
-
- TestPhoneNumberInteraction interaction = new TestPhoneNumberInteraction(
- mContext, ContactDisplayUtils.INTERACTION_CALL, null);
-
- interaction.startInteraction(contactUri);
- interaction.getLoader().waitForLoader();
-
- List<PhoneItem> items = interaction.mPhoneList;
- assertNotNull(items);
- assertEquals(2, items.size());
-
- PhoneItem item = items.get(0);
- assertEquals(1, item.id);
- assertEquals("123", item.phoneNumber);
- assertEquals("account", item.accountType);
- assertEquals(Phone.TYPE_HOME, item.type);
- assertEquals("label", item.label);
- }
-
- private Query expectQuery(Uri contactUri) {
- return expectQuery(contactUri, false);
- }
-
- private Query expectQuery(Uri uri, boolean isDataUri) {
- final Uri dataUri;
- if (isDataUri) {
- dataUri = uri;
- } else {
- dataUri = Uri.withAppendedPath(uri, Contacts.Data.CONTENT_DIRECTORY);
- }
- return mContactsProvider
- .expectQuery(dataUri)
- .withProjection(
- Phone._ID,
- Phone.NUMBER,
- Phone.IS_SUPER_PRIMARY,
- RawContacts.ACCOUNT_TYPE,
- RawContacts.DATA_SET,
- Phone.TYPE,
- Phone.LABEL,
- Phone.MIMETYPE)
- .withSelection("mimetype IN ('vnd.android.cursor.item/phone_v2',"
- + " 'vnd.android.cursor.item/sip_address') AND data1 NOT NULL");
- }
-}
diff --git a/tests/src/com/android/contacts/model/ContactLoaderTest.java b/tests/src/com/android/contacts/model/ContactLoaderTest.java
index 54d220f..f1fb7ae 100644
--- a/tests/src/com/android/contacts/model/ContactLoaderTest.java
+++ b/tests/src/com/android/contacts/model/ContactLoaderTest.java
@@ -28,27 +28,26 @@
import android.test.LoaderTestCase;
import android.test.suitebuilder.annotation.LargeTest;
-import com.android.contacts.model.Contact;
import com.android.contacts.model.account.AccountType;
import com.android.contacts.model.account.AccountWithDataSet;
import com.android.contacts.model.account.BaseAccountType;
import com.android.contacts.test.InjectedServices;
-import com.android.contacts.tests.mocks.ContactsMockContext;
+import com.android.contacts.tests.mocks.ContactsAccountManagerMockContext;
import com.android.contacts.tests.mocks.MockAccountTypeManager;
-import com.android.contacts.tests.mocks.MockContentProvider;
+import com.android.contacts.common.test.mocks.MockContentProvider;
/**
* Runs ContactLoader tests for the the contact-detail and editor view.
*/
@LargeTest
public class ContactLoaderTest extends LoaderTestCase {
- private ContactsMockContext mMockContext;
+ private ContactsAccountManagerMockContext mMockContext;
private MockContentProvider mContactsProvider;
@Override
protected void setUp() throws Exception {
super.setUp();
- mMockContext = new ContactsMockContext(getContext());
+ mMockContext = new ContactsAccountManagerMockContext(getContext());
mContactsProvider = mMockContext.getContactsProvider();
InjectedServices services = new InjectedServices();
@@ -65,7 +64,7 @@
mMockContext.setMockAccountTypeManager(
new MockAccountTypeManager(
- new AccountType[] { accountType }, new AccountWithDataSet[] { account }));
+ new AccountType[]{accountType}, new AccountWithDataSet[]{account}));
}
@Override
diff --git a/tests/src/com/android/contacts/tests/mocks/ContactsAccountManagerMockContext.java b/tests/src/com/android/contacts/tests/mocks/ContactsAccountManagerMockContext.java
new file mode 100644
index 0000000..c0ba9d3
--- /dev/null
+++ b/tests/src/com/android/contacts/tests/mocks/ContactsAccountManagerMockContext.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 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.tests.mocks;
+
+import android.content.Context;
+
+import com.android.contacts.common.test.mocks.ContactsMockContext;
+import com.android.contacts.model.AccountTypeManager;
+
+/**
+ * A ContactsMockContext with an additional mock AccountTypeManager.
+ */
+public class ContactsAccountManagerMockContext extends ContactsMockContext {
+
+ private MockAccountTypeManager mMockAccountTypeManager;
+
+
+ public ContactsAccountManagerMockContext(Context base) {
+ super(base);
+ }
+
+ public void setMockAccountTypeManager(MockAccountTypeManager mockAccountTypeManager) {
+ mMockAccountTypeManager = mockAccountTypeManager;
+ }
+
+ @Override
+ public Object getSystemService(String name) {
+ if (AccountTypeManager.ACCOUNT_TYPE_SERVICE.equals(name)) {
+ return mMockAccountTypeManager;
+ }
+ return super.getSystemService(name);
+ }
+}
diff --git a/tests/src/com/android/contacts/tests/mocks/ContactsMockContext.java b/tests/src/com/android/contacts/tests/mocks/ContactsMockContext.java
deleted file mode 100644
index a384dea..0000000
--- a/tests/src/com/android/contacts/tests/mocks/ContactsMockContext.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2010 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.tests.mocks;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ProviderInfo;
-import android.provider.ContactsContract;
-import android.provider.Settings;
-import android.test.mock.MockContentResolver;
-
-import com.android.contacts.model.AccountTypeManager;
-
-/**
- * A mock context for contacts unit tests. Forwards everything to
- * a supplied context, except content resolver operations, which are sent
- * to mock content providers.
- */
-public class ContactsMockContext extends ContextWrapper {
- private ContactsMockPackageManager mPackageManager;
- private MockContentResolver mContentResolver;
- private MockContentProvider mContactsProvider;
- private MockContentProvider mSettingsProvider;
- private MockAccountTypeManager mMockAccountTypeManager;
- private Intent mIntentForStartActivity;
-
- public ContactsMockContext(Context base) {
- super(base);
- mPackageManager = new ContactsMockPackageManager();
- mContentResolver = new MockContentResolver();
- mContactsProvider = new MockContentProvider();
- mContentResolver.addProvider(ContactsContract.AUTHORITY, mContactsProvider);
- mContactsProvider.attachInfo(this, new ProviderInfo());
- mSettingsProvider = new MockContentProvider();
- mSettingsProvider.attachInfo(this, new ProviderInfo());
- mContentResolver.addProvider(Settings.AUTHORITY, mSettingsProvider);
- }
-
- public void setMockAccountTypeManager(MockAccountTypeManager mockAccountTypeManager) {
- mMockAccountTypeManager = mockAccountTypeManager;
- }
-
- @Override
- public ContentResolver getContentResolver() {
- return mContentResolver;
- }
-
- public MockContentProvider getContactsProvider() {
- return mContactsProvider;
- }
-
- public MockContentProvider getSettingsProvider() {
- return mSettingsProvider;
- }
-
- @Override
- public PackageManager getPackageManager() {
- return mPackageManager;
- }
-
- @Override
- public Context getApplicationContext() {
- return this;
- }
-
- /**
- * Instead of actually sending Intent, this method just remembers what Intent was supplied last.
- * You can check the content via {@link #getIntentForStartActivity()} for verification.
- */
- @Override
- public void startActivity(Intent intent) {
- mIntentForStartActivity = intent;
- }
-
- public Intent getIntentForStartActivity() {
- return mIntentForStartActivity;
- }
-
- public void verify() {
- mContactsProvider.verify();
- mSettingsProvider.verify();
- }
-
- @Override
- public Object getSystemService(String name) {
- if (AccountTypeManager.ACCOUNT_TYPE_SERVICE.equals(name)) {
- return mMockAccountTypeManager;
- }
- return super.getSystemService(name);
- }
-}
diff --git a/tests/src/com/android/contacts/tests/mocks/ContactsMockPackageManager.java b/tests/src/com/android/contacts/tests/mocks/ContactsMockPackageManager.java
deleted file mode 100644
index 0f893fe..0000000
--- a/tests/src/com/android/contacts/tests/mocks/ContactsMockPackageManager.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2010 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.tests.mocks;
-
-import android.content.ComponentName;
-import android.content.pm.ApplicationInfo;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
-import android.test.mock.MockPackageManager;
-
-/**
- */
-public class ContactsMockPackageManager extends MockPackageManager {
- public ContactsMockPackageManager() {
- }
-
- @Override
- public Drawable getActivityLogo(ComponentName activityName) throws NameNotFoundException {
- return new ColorDrawable();
- }
-
- @Override
- public Drawable getActivityIcon(ComponentName activityName) {
- return new ColorDrawable();
- }
-
- @Override
- public Drawable getDrawable(String packageName, int resid, ApplicationInfo appInfo) {
- // TODO: make programmable
- return new ColorDrawable();
- }
-}
diff --git a/tests/src/com/android/contacts/tests/mocks/MockContentProvider.java b/tests/src/com/android/contacts/tests/mocks/MockContentProvider.java
deleted file mode 100644
index 71b434d..0000000
--- a/tests/src/com/android/contacts/tests/mocks/MockContentProvider.java
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * Copyright (C) 2010 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.tests.mocks;
-
-import android.content.ContentProvider;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.database.MatrixCursor;
-import android.net.Uri;
-import android.text.TextUtils;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-import junit.framework.Assert;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Iterator;
-
-/**
- * A programmable mock content provider.
- */
-public class MockContentProvider extends ContentProvider {
- private static final String TAG = "MockContentProvider";
-
- public static class Query {
-
- private final Uri mUri;
- private String[] mProjection;
- private String[] mDefaultProjection;
- private String mSelection;
- private String[] mSelectionArgs;
- private String mSortOrder;
- private ArrayList<Object> mRows = new ArrayList<Object>();
- private boolean mAnyProjection;
- private boolean mAnySelection;
- private boolean mAnySortOrder;
- private boolean mAnyNumberOfTimes;
-
- private boolean mExecuted;
-
- public Query(Uri uri) {
- mUri = uri;
- }
-
- @Override
- public String toString() {
- return queryToString(mUri, mProjection, mSelection, mSelectionArgs, mSortOrder);
- }
-
- public Query withProjection(String... projection) {
- mProjection = projection;
- return this;
- }
-
- public Query withDefaultProjection(String... projection) {
- mDefaultProjection = projection;
- return this;
- }
-
- public Query withAnyProjection() {
- mAnyProjection = true;
- return this;
- }
-
- public Query withSelection(String selection, String... selectionArgs) {
- mSelection = selection;
- mSelectionArgs = selectionArgs;
- return this;
- }
-
- public Query withAnySelection() {
- mAnySelection = true;
- return this;
- }
-
- public Query withSortOrder(String sortOrder) {
- mSortOrder = sortOrder;
- return this;
- }
-
- public Query withAnySortOrder() {
- mAnySortOrder = true;
- return this;
- }
-
- public Query returnRow(ContentValues values) {
- mRows.add(values);
- return this;
- }
-
- public Query returnRow(Object... row) {
- mRows.add(row);
- return this;
- }
-
- public Query returnEmptyCursor() {
- mRows.clear();
- return this;
- }
-
- public Query anyNumberOfTimes() {
- mAnyNumberOfTimes = true;
- return this;
- }
-
- public boolean equals(Uri uri, String[] projection, String selection,
- String[] selectionArgs, String sortOrder) {
- if (!uri.equals(mUri)) {
- return false;
- }
-
- if (!mAnyProjection && !equals(projection, mProjection)) {
- return false;
- }
-
- if (!mAnySelection && !equals(selection, mSelection)) {
- return false;
- }
-
- if (!mAnySelection && !equals(selectionArgs, mSelectionArgs)) {
- return false;
- }
-
- if (!mAnySortOrder && !equals(sortOrder, mSortOrder)) {
- return false;
- }
-
- return true;
- }
-
- private boolean equals(String string1, String string2) {
- if (TextUtils.isEmpty(string1)) {
- string1 = null;
- }
- if (TextUtils.isEmpty(string2)) {
- string2 = null;
- }
- return TextUtils.equals(string1, string2);
- }
-
- private static boolean equals(String[] array1, String[] array2) {
- boolean empty1 = array1 == null || array1.length == 0;
- boolean empty2 = array2 == null || array2.length == 0;
- if (empty1 && empty2) {
- return true;
- }
- if (empty1 != empty2 && (empty1 || empty2)) {
- return false;
- }
-
- if (array1.length != array2.length) return false;
-
- for (int i = 0; i < array1.length; i++) {
- if (!array1[i].equals(array2[i])) {
- return false;
- }
- }
- return true;
- }
-
- public Cursor getResult(String[] projection) {
- String[] columnNames;
- if (mAnyProjection) {
- columnNames = projection;
- } else {
- columnNames = mProjection != null ? mProjection : mDefaultProjection;
- }
-
- MatrixCursor cursor = new MatrixCursor(columnNames);
- for (Object row : mRows) {
- if (row instanceof Object[]) {
- cursor.addRow((Object[]) row);
- } else {
- ContentValues values = (ContentValues) row;
- Object[] columns = new Object[projection.length];
- for (int i = 0; i < projection.length; i++) {
- columns[i] = values.get(projection[i]);
- }
- cursor.addRow(columns);
- }
- }
- return cursor;
- }
- }
-
- public static class TypeQuery {
- private final Uri mUri;
- private final String mType;
-
- public TypeQuery(Uri uri, String type) {
- mUri = uri;
- mType = type;
- }
-
- public Uri getUri() {
- return mUri;
- }
-
- public String getType() {
- return mType;
- }
-
- @Override
- public String toString() {
- return mUri + " --> " + mType;
- }
-
- public boolean equals(Uri uri) {
- return getUri().equals(uri);
- }
- }
-
- private ArrayList<Query> mExpectedQueries = new ArrayList<Query>();
- private HashMap<Uri, String> mExpectedTypeQueries = Maps.newHashMap();
-
- @Override
- public boolean onCreate() {
- return true;
- }
-
- public Query expectQuery(Uri contentUri) {
- Query query = new Query(contentUri);
- mExpectedQueries.add(query);
- return query;
- }
-
- public void expectTypeQuery(Uri uri, String type) {
- mExpectedTypeQueries.put(uri, type);
- }
-
- @Override
- public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
- String sortOrder) {
-
- for (Iterator<Query> iterator = mExpectedQueries.iterator(); iterator.hasNext();) {
- Query query = iterator.next();
- if (query.equals(uri, projection, selection, selectionArgs, sortOrder)) {
- query.mExecuted = true;
- if (!query.mAnyNumberOfTimes) {
- iterator.remove();
- }
- return query.getResult(projection);
- }
- }
-
- if (mExpectedQueries.isEmpty()) {
- Assert.fail("Unexpected query: "
- + queryToString(uri, projection, selection, selectionArgs, sortOrder));
- } else {
- StringBuilder sb = new StringBuilder();
- sb.append(mExpectedQueries.get(0));
- for (int i = 1; i < mExpectedQueries.size(); i++) {
- sb.append("\n ").append(mExpectedQueries.get(i));
- }
- Assert.fail("Incorrect query.\n Expected: " + sb + "\n Actual: " +
- queryToString(uri, projection, selection, selectionArgs, sortOrder));
- }
- return null;
- }
-
- @Override
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String getType(Uri uri) {
- if (mExpectedTypeQueries.isEmpty()) {
- Assert.fail("Unexpected getType query: " + uri);
- }
-
- String mimeType = mExpectedTypeQueries.get(uri);
- if (mimeType != null) {
- return mimeType;
- }
-
- Assert.fail("Unknown mime type for: " + uri);
- return null;
- }
-
- @Override
- public Uri insert(Uri uri, ContentValues values) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
- throw new UnsupportedOperationException();
- }
-
- private static String queryToString(Uri uri, String[] projection, String selection,
- String[] selectionArgs, String sortOrder) {
- StringBuilder sb = new StringBuilder();
- sb.append(uri).append(" ");
- if (projection != null) {
- sb.append(Arrays.toString(projection));
- } else {
- sb.append("[]");
- }
- if (selection != null) {
- sb.append(" selection: '").append(selection).append("'");
- if (selectionArgs != null) {
- sb.append(Arrays.toString(selectionArgs));
- } else {
- sb.append("[]");
- }
- }
- if (sortOrder != null) {
- sb.append(" sort: '").append(sortOrder).append("'");
- }
- return sb.toString();
- }
-
- public void verify() {
- ArrayList<Query> mMissedQueries = Lists.newArrayList();
- for (Query query : mExpectedQueries) {
- if (!query.mExecuted) {
- mMissedQueries.add(query);
- }
- }
- Assert.assertTrue("Not all expected queries have been called: " +
- mMissedQueries, mMissedQueries.isEmpty());
- }
-}