From 774321318c2b779d9edaf02e9a7e10ef2a8cad90 Mon Sep 17 00:00:00 2001 From: Brandon Maxwell Date: Wed, 28 Oct 2015 15:29:58 -0700 Subject: Speed dial respects display order prefs - Speed dial names change based on whether user wants first name first or last name first - Sort order preferece is respected if ContactEntries have conflicting pinned positions - Added tests for PhoneFavoritesTileAdapter.arrangeContactsByPinnedPosition method Bug:19364093 Change-Id: I81214abce572e297cc21fcb4f5a901ecad958380 --- .../dialer/list/PhoneFavoriteSquareTileView.java | 5 + .../dialer/list/PhoneFavoritesTileAdapter.java | 48 ++-- src/com/android/dialer/list/SpeedDialFragment.java | 4 +- .../dialer/list/PhoneFavoritesTileAdapterTest.java | 248 ++++++++++++++++++--- 4 files changed, 263 insertions(+), 42 deletions(-) diff --git a/src/com/android/dialer/list/PhoneFavoriteSquareTileView.java b/src/com/android/dialer/list/PhoneFavoriteSquareTileView.java index 05780c66a..c12bed737 100644 --- a/src/com/android/dialer/list/PhoneFavoriteSquareTileView.java +++ b/src/com/android/dialer/list/PhoneFavoriteSquareTileView.java @@ -95,6 +95,11 @@ public class PhoneFavoriteSquareTileView extends PhoneFavoriteTileView { setMeasuredDimension(width, height); } + @Override + protected String getNameForView(ContactEntry contactEntry) { + return contactEntry.getPreferredDisplayName(); + } + public ContactEntry getContactEntry() { return mContactEntry; } diff --git a/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java b/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java index e957c8321..cd4c10b59 100644 --- a/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java +++ b/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java @@ -38,13 +38,13 @@ import android.util.LongSparseArray; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; -import android.widget.FrameLayout; import com.android.contacts.common.ContactPhotoManager; import com.android.contacts.common.ContactTileLoaderFactory; import com.android.contacts.common.list.ContactEntry; import com.android.contacts.common.list.ContactTileAdapter.DisplayType; import com.android.contacts.common.list.ContactTileView; +import com.android.contacts.common.preference.ContactsPreferences; import com.android.dialer.R; import java.util.ArrayList; @@ -70,6 +70,7 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements private Context mContext; private Resources mResources; + private ContactsPreferences mContactsPreferences; /** Contact data stored in cache. This is used to populate the associated view. */ protected ArrayList mContactEntries = null; @@ -92,7 +93,8 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements protected int mIdIndex; protected int mLookupIndex; protected int mPhotoUriIndex; - protected int mNameIndex; + protected int mNamePrimaryIndex; + protected int mNameAlternativeIndex; protected int mPresenceIndex; protected int mStatusIndex; @@ -124,9 +126,17 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements public int compare(ContactEntry lhs, ContactEntry rhs) { return ComparisonChain.start() .compare(lhs.pinned, rhs.pinned) - .compare(lhs.name, rhs.name) + .compare(getPreferredSortName(lhs), getPreferredSortName(rhs)) .result(); } + + private String getPreferredSortName(ContactEntry contactEntry) { + if (mContactsPreferences.getSortOrder() == ContactsPreferences.SORT_ORDER_PRIMARY + || TextUtils.isEmpty(contactEntry.nameAlternative)) { + return contactEntry.namePrimary; + } + return contactEntry.nameAlternative; + } }; public interface OnDataSetChangedForAnimationListener { @@ -140,6 +150,7 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements mListener = listener; mContext = context; mResources = context.getResources(); + mContactsPreferences = new ContactsPreferences(mContext); mNumFrequents = 0; mContactEntries = new ArrayList(); @@ -172,19 +183,26 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements */ protected void bindColumnIndices() { mIdIndex = ContactTileLoaderFactory.CONTACT_ID; - mLookupIndex = ContactTileLoaderFactory.LOOKUP_KEY; - mPhotoUriIndex = ContactTileLoaderFactory.PHOTO_URI; - mNameIndex = ContactTileLoaderFactory.DISPLAY_NAME; + mNamePrimaryIndex = ContactTileLoaderFactory.DISPLAY_NAME; + mNameAlternativeIndex = ContactTileLoaderFactory.DISPLAY_NAME_ALTERNATIVE; mStarredIndex = ContactTileLoaderFactory.STARRED; - mPresenceIndex = ContactTileLoaderFactory.CONTACT_PRESENCE; - mStatusIndex = ContactTileLoaderFactory.CONTACT_STATUS; - + mPhotoUriIndex = ContactTileLoaderFactory.PHOTO_URI; + mLookupIndex = ContactTileLoaderFactory.LOOKUP_KEY; mPhoneNumberIndex = ContactTileLoaderFactory.PHONE_NUMBER; mPhoneNumberTypeIndex = ContactTileLoaderFactory.PHONE_NUMBER_TYPE; mPhoneNumberLabelIndex = ContactTileLoaderFactory.PHONE_NUMBER_LABEL; - mIsDefaultNumberIndex = ContactTileLoaderFactory.IS_DEFAULT_NUMBER; mPinnedIndex = ContactTileLoaderFactory.PINNED; - mContactIdIndex = ContactTileLoaderFactory.CONTACT_ID_FOR_DATA; + mContactIdIndex = ContactTileLoaderFactory.CONTACT_ID; + + + mPresenceIndex = ContactTileLoaderFactory.CONTACT_PRESENCE; + mStatusIndex = ContactTileLoaderFactory.CONTACT_STATUS; + mIsDefaultNumberIndex = ContactTileLoaderFactory.IS_DEFAULT_NUMBER; + } + + public void refreshContactsPreferences() { + mContactsPreferences.refreshValue(ContactsPreferences.DISPLAY_ORDER_KEY); + mContactsPreferences.refreshValue(ContactsPreferences.SORT_ORDER_KEY); } /** @@ -261,15 +279,19 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements final String photoUri = cursor.getString(mPhotoUriIndex); final String lookupKey = cursor.getString(mLookupIndex); final int pinned = cursor.getInt(mPinnedIndex); - final String name = cursor.getString(mNameIndex); + final String name = cursor.getString(mNamePrimaryIndex); + final String nameAlternative = cursor.getString(mNameAlternativeIndex); final boolean isStarred = cursor.getInt(mStarredIndex) > 0; final boolean isDefaultNumber = cursor.getInt(mIsDefaultNumberIndex) > 0; final ContactEntry contact = new ContactEntry(); contact.id = id; - contact.name = (!TextUtils.isEmpty(name)) ? name : + contact.namePrimary = (!TextUtils.isEmpty(name)) ? name : + mResources.getString(R.string.missing_name); + contact.nameAlternative = (!TextUtils.isEmpty(nameAlternative)) ? nameAlternative : mResources.getString(R.string.missing_name); + contact.nameDisplayOrder = mContactsPreferences.getDisplayOrder(); contact.photoUri = (photoUri != null ? Uri.parse(photoUri) : null); contact.lookupKey = lookupKey; contact.lookupUri = ContentUris.withAppendedId( diff --git a/src/com/android/dialer/list/SpeedDialFragment.java b/src/com/android/dialer/list/SpeedDialFragment.java index 64129cdea..e30f40633 100644 --- a/src/com/android/dialer/list/SpeedDialFragment.java +++ b/src/com/android/dialer/list/SpeedDialFragment.java @@ -202,7 +202,9 @@ public class SpeedDialFragment extends Fragment implements OnItemClickListener, public void onResume() { Trace.beginSection(TAG + " onResume"); super.onResume(); - + if (mContactTileAdapter != null) { + mContactTileAdapter.refreshContactsPreferences(); + } if (PermissionsUtil.hasContactsPermissions(getActivity())) { if (getLoaderManager().getLoader(LOADER_ID_CONTACT_TILE) == null) { getLoaderManager().initLoader(LOADER_ID_CONTACT_TILE, null, diff --git a/tests/src/com/android/dialer/list/PhoneFavoritesTileAdapterTest.java b/tests/src/com/android/dialer/list/PhoneFavoritesTileAdapterTest.java index d0547bda8..881938400 100644 --- a/tests/src/com/android/dialer/list/PhoneFavoritesTileAdapterTest.java +++ b/tests/src/com/android/dialer/list/PhoneFavoritesTileAdapterTest.java @@ -1,5 +1,8 @@ package com.android.dialer.list; +import com.google.common.collect.Lists; + +import android.content.Context; import android.database.Cursor; import android.database.MatrixCursor; import android.provider.ContactsContract.PinnedPositions; @@ -8,15 +11,18 @@ import android.test.suitebuilder.annotation.SmallTest; import com.android.contacts.common.ContactTileLoaderFactory; import com.android.contacts.common.list.ContactEntry; +import com.android.contacts.common.preference.ContactsPreferences; import com.android.dialer.list.PhoneFavoritesTileAdapter.OnDataSetChangedForAnimationListener; +import junit.framework.Assert; + import java.util.ArrayList; @SmallTest public class PhoneFavoritesTileAdapterTest extends AndroidTestCase { - private PhoneFavoritesTileAdapter mAdapter; - private static final OnDataSetChangedForAnimationListener - sOnDataSetChangedForAnimationListener = new OnDataSetChangedForAnimationListener() { + + private static final OnDataSetChangedForAnimationListener NOOP_ANIMATION_LISTENER = + new OnDataSetChangedForAnimationListener() { @Override public void onDataSetChangedForAnimation(long... idsInPlace) {} @@ -24,18 +30,161 @@ public class PhoneFavoritesTileAdapterTest extends AndroidTestCase { public void cacheOffsetsForDatasetChange() {} }; + private PhoneFavoritesTileAdapter mAdapter; + + @Override + public void setUp() { + this.mAdapter = new PhoneFavoritesTileAdapter(getContext(), null, NOOP_ANIMATION_LISTENER); + } + /** - * TODO: Add tests - * - * Test cases (various combinations of): - * No pinned contacts - * One pinned contact - * Multiple pinned contacts with differing pinned positions - * Multiple pinned contacts with conflicting pinned positions - * Pinned contacts with pinned positions at the start, middle, end, and outside the list + * For all arrangeContactsByPinnedPosition tests, the id for a particular ContactEntry + * represents the index at which it should be located after calling + * arrangeContactsByPinnedPosition */ - public void testArrangeContactsByPinnedPosition() { + public void testArrangeContactsByPinnedPosition_NoPinned() { + ArrayList toArrange = Lists.newArrayList(getTestContactEntry(0), + getTestContactEntry(1), getTestContactEntry(2)); + mAdapter.arrangeContactsByPinnedPosition(toArrange); + + assertContactEntryListPositionsMatchId(toArrange, 3); + } + + public void testArrangeContactsByPinnedPosition_NoPinned_RemoveDemoted() { + ArrayList toArrange = Lists.newArrayList(getTestContactEntry(0), + getTestContactEntry(-1, PinnedPositions.DEMOTED), getTestContactEntry(1)); + mAdapter.arrangeContactsByPinnedPosition(toArrange); + + assertContactEntryListPositionsMatchId(toArrange, 2); + } + + public void testArrangeContactsByPinnedPosition_OnePinned_Beginning() { + ArrayList toArrange = Lists.newArrayList(getTestContactEntry(1), + getTestContactEntry(0, 1), getTestContactEntry(2)); + mAdapter.arrangeContactsByPinnedPosition(toArrange); + + assertContactEntryListPositionsMatchId(toArrange, 3); + } + + public void testArrangeContactsByPinnedPosition_OnePinned_Middle() { + ArrayList toArrange = Lists.newArrayList(getTestContactEntry(0), + getTestContactEntry(1, 2), getTestContactEntry(2)); + mAdapter.arrangeContactsByPinnedPosition(toArrange); + + assertContactEntryListPositionsMatchId(toArrange, 3); + } + + public void testArrangeContactsByPinnedPosition_OnePinned_End() { + ArrayList toArrange = Lists.newArrayList(getTestContactEntry(0), + getTestContactEntry(2, 3), getTestContactEntry(1)); + mAdapter.arrangeContactsByPinnedPosition(toArrange); + + assertContactEntryListPositionsMatchId(toArrange, 3); + } + + public void testArrangeContactsByPinnedPosition_OnePinned_Outside() { + ArrayList toArrange = Lists.newArrayList(getTestContactEntry(0), + getTestContactEntry(2, 5), getTestContactEntry(1)); + mAdapter.arrangeContactsByPinnedPosition(toArrange); + + assertContactEntryListPositionsMatchId(toArrange, 3); + } + + public void testArrangeContactsByPinnedPosition_OnePinned_RemoveDemoted() { + ArrayList toArrange = Lists.newArrayList(getTestContactEntry(1, 2), + getTestContactEntry(-1, PinnedPositions.DEMOTED), getTestContactEntry(0)); + mAdapter.arrangeContactsByPinnedPosition(toArrange); + + assertContactEntryListPositionsMatchId(toArrange, 2); + } + + public void testArrangeContactsByPinnedPosition_TwoPinned_Split() { + ArrayList toArrange = Lists.newArrayList(getTestContactEntry(0, 1), + getTestContactEntry(1), getTestContactEntry(2, 3)); + mAdapter.arrangeContactsByPinnedPosition(toArrange); + + assertContactEntryListPositionsMatchId(toArrange, 3); + } + + public void testArrangeContactsByPinnedPosition_TwoPinned_Adjacent() { + ArrayList toArrange = Lists.newArrayList(getTestContactEntry(1, 2), + getTestContactEntry(0), getTestContactEntry(2, 3)); + mAdapter.arrangeContactsByPinnedPosition(toArrange); + + assertContactEntryListPositionsMatchId(toArrange, 3); + } + + public void testArrangeContactsByPinnedPosition_TwoPinned_Conflict_UnpinnedBefore() { + ArrayList toArrange = Lists.newArrayList(getTestContactEntry(1, 2), + getTestContactEntry(0), getTestContactEntry(2, 2)); + mAdapter.arrangeContactsByPinnedPosition(toArrange); + + assertContactEntryListPositionsMatchId(toArrange, 3); + } + + public void testArrangeContactsByPinnedPosition_TwoPinned_Conflict_UnpinnedAfter() { + ArrayList toArrange = Lists.newArrayList(getTestContactEntry(0, 1), + getTestContactEntry(2), getTestContactEntry(1, 1)); + mAdapter.arrangeContactsByPinnedPosition(toArrange); + + assertContactEntryListPositionsMatchId(toArrange, 3); + } + + public void testArrangeContactsByPinnedPosition_TwoPinned_Conflict_RemoveDemoted() { + ArrayList toArrange = Lists.newArrayList(getTestContactEntry(1, 2), + getTestContactEntry(-1, PinnedPositions.DEMOTED), getTestContactEntry(0, 2)); + mAdapter.arrangeContactsByPinnedPosition(toArrange); + + assertContactEntryListPositionsMatchId(toArrange, 2); + } + + public void testArrangeContactsByPinnedPosition_AllPinned() { + ArrayList toArrange = Lists.newArrayList(getTestContactEntry(1, 2), + getTestContactEntry(0, 1), getTestContactEntry(2, 3)); + mAdapter.arrangeContactsByPinnedPosition(toArrange); + + assertContactEntryListPositionsMatchId(toArrange, 3); + } + + public void testArrangeContactsByPinnedPosition_AllPinned_TwoConflicts_ConflictsFirst() { + ArrayList toArrange = Lists.newArrayList(getTestContactEntry(1, 2), + getTestContactEntry(0, 2), getTestContactEntry(2, 3)); + mAdapter.arrangeContactsByPinnedPosition(toArrange); + + assertContactEntryListPositionsMatchId(toArrange, 3); + } + + public void testArrangeContactsByPinnedPosition_AllPinned_TwoConflicts_ConflictsLast() { + ArrayList toArrange = Lists.newArrayList(getTestContactEntry(0, 2), + getTestContactEntry(1, 3), getTestContactEntry(2, 3)); + mAdapter.arrangeContactsByPinnedPosition(toArrange); + + assertContactEntryListPositionsMatchId(toArrange, 3); + } + + public void testArrangeContactsByPinnedPosition_AllPinned_AllConflicts() { + ArrayList toArrange = Lists.newArrayList(getTestContactEntry(2, 3), + getTestContactEntry(1, 3), getTestContactEntry(0, 3)); + mAdapter.arrangeContactsByPinnedPosition(toArrange); + + assertContactEntryListPositionsMatchId(toArrange, 3); + } + + public void testArrangeContactsByPinnedPosition_All_Pinned_AllConflicts_SortNameAlternative() { + Context context = getContext(); + context.getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE).edit() + .putInt(ContactsPreferences.SORT_ORDER_KEY, + ContactsPreferences.SORT_ORDER_ALTERNATIVE) + .commit(); + ArrayList actual = Lists.newArrayList( + getTestContactEntry(1, 3, "2", "1"), + getTestContactEntry(2, 3, "0", "2"), + getTestContactEntry(0, 3, "1", "0") + ); + mAdapter.arrangeContactsByPinnedPosition(actual); + + assertContactEntryListPositionsMatchId(actual, 3); } /** @@ -55,6 +204,45 @@ public class PhoneFavoritesTileAdapterTest extends AndroidTestCase { } + public void testSetContactCursor_DisplayNameOrder_Primary() { + setNameDisplayOrder(getContext(), ContactsPreferences.DISPLAY_ORDER_PRIMARY); + Cursor testCursor = getCursorForTest(1, 0); + mAdapter.setContactCursor(testCursor); + Assert.assertEquals(1, mAdapter.mContactEntries.size()); + Assert.assertEquals(ContactsPreferences.DISPLAY_ORDER_PRIMARY, + mAdapter.mContactEntries.get(0).nameDisplayOrder); + } + + public void testSetContactCursor_DisplayNameOrder_Alternative() { + setNameDisplayOrder(getContext(), ContactsPreferences.DISPLAY_ORDER_ALTERNATIVE); + Cursor testCursor = getCursorForTest(1, 0); + mAdapter.setContactCursor(testCursor); + Assert.assertEquals(1, mAdapter.mContactEntries.size()); + Assert.assertEquals(ContactsPreferences.DISPLAY_ORDER_ALTERNATIVE, + mAdapter.mContactEntries.get(0).nameDisplayOrder); + } + + public void testSetContactCursor_DisplayNameOrder_Changed() { + setNameDisplayOrder(getContext(), ContactsPreferences.DISPLAY_ORDER_PRIMARY); + Cursor testCursor = getCursorForTest(1, 0); + mAdapter.setContactCursor(testCursor); + Assert.assertEquals(1, mAdapter.mContactEntries.size()); + Assert.assertEquals(ContactsPreferences.DISPLAY_ORDER_PRIMARY, + mAdapter.mContactEntries.get(0).nameDisplayOrder); + + setNameDisplayOrder(getContext(), ContactsPreferences.DISPLAY_ORDER_ALTERNATIVE); + mAdapter.refreshContactsPreferences(); + mAdapter.setContactCursor(testCursor); + Assert.assertEquals(1, mAdapter.mContactEntries.size()); + Assert.assertEquals(ContactsPreferences.DISPLAY_ORDER_ALTERNATIVE, + mAdapter.mContactEntries.get(0).nameDisplayOrder); + } + + private void setNameDisplayOrder(Context context, int displayOrder) { + context.getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE).edit().putInt( + ContactsPreferences.DISPLAY_ORDER_KEY, displayOrder).commit(); + } + /** * Returns a cursor containing starred and frequent contacts for test purposes. * @@ -72,38 +260,42 @@ public class PhoneFavoritesTileAdapterTest extends AndroidTestCase { // The only field that really matters for testing is the contact id. for (int i = 0; i < numStarred; i++) { c.addRow(new Object[] {countId, null, 1, null, null, 0, 0, null, 0, - PinnedPositions.UNPINNED, countId}); + PinnedPositions.UNPINNED, countId, null}); countId++; } // Add frequent contact entries. These entries have the starred field set to 0 (false). for (int i = 0; i < numFrequents; i++) { c.addRow(new Object[] {countId, null, 0, null, null, 0, 0, null, 0, - PinnedPositions.UNPINNED, countId}); + PinnedPositions.UNPINNED, countId, null}); countId++; } return c; } - /** - * Returns a ContactEntry with test data corresponding to the provided contact Id - * - * @param id Non-negative id - * @return ContactEntry item used for testing - */ - private ContactEntry getTestContactEntry(int id, boolean isFavorite) { + private ContactEntry getTestContactEntry(int id) { + return getTestContactEntry(id, PinnedPositions.UNPINNED); + } + + private ContactEntry getTestContactEntry(int id, int pinned) { + return getTestContactEntry(id, pinned, String.valueOf(id), String.valueOf(id)); + } + + private ContactEntry getTestContactEntry(int id, int pinned, String namePrimaryAppend, + String nameAlternativeAppend) { ContactEntry contactEntry = new ContactEntry(); contactEntry.id = id; - contactEntry.isFavorite = isFavorite; + contactEntry.pinned = pinned; + contactEntry.namePrimary = namePrimaryAppend; + contactEntry.nameAlternative = nameAlternativeAppend; return contactEntry; } - private void assertContactEntryRowsEqual(ArrayList expected, - ArrayList actual) { - assertEquals(expected.size(), actual.size()); - for (int i = 0; i < actual.size(); i++) { - assertEquals(expected.get(i).id, actual.get(i).id); - assertEquals(expected.get(i).isFavorite, actual.get(i).isFavorite); + private void assertContactEntryListPositionsMatchId(ArrayList contactEntries, + int expectedSize) { + Assert.assertEquals(expectedSize, contactEntries.size()); + for (int i = 0; i < expectedSize; ++i) { + Assert.assertEquals(i, contactEntries.get(i).id); } } } -- cgit v1.2.3