summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrandon Maxwell <maxwelb@google.com>2015-10-20 14:49:47 -0700
committerBrandon Maxwell <maxwelb@google.com>2015-10-23 11:21:02 -0700
commit327fb5bb609a6bee44a62888d671c951b19782fd (patch)
tree47834abcbe66ec4b9faed28349479dd758947d22
parent7844b1d11b6f8715ff2782cd3d01a3d1c397f052 (diff)
Call log respects display name order preferences
- Updated ContactInfoHelper to retrieve DISPLAY_NAME_ALTERNATIVE (name in last name first order) - Stored alternative name in ContactInfo object - Updated CallLogAdapter to choose between first name first and last name first when showing contact name - Added tests for ContactInfoHelper.lookupContactFromUri (changed to public method) - Fixed bug with ContactsPreferences so ChangeListener works Bug:19364093 Change-Id: I188d8fc2eccb87edbe56625c9a7537b3d5f0e19e
-rw-r--r--src/com/android/dialer/calllog/CallLogAdapter.java30
-rw-r--r--src/com/android/dialer/calllog/CallLogFragment.java3
-rw-r--r--src/com/android/dialer/calllog/ContactInfo.java10
-rw-r--r--src/com/android/dialer/calllog/ContactInfoHelper.java88
-rw-r--r--src/com/android/dialer/calllog/PhoneQuery.java19
-rw-r--r--src/com/android/dialer/contactinfo/ContactInfoCache.java5
-rw-r--r--tests/src/com/android/dialer/calllog/ContactInfoHelperTest.java112
7 files changed, 214 insertions, 53 deletions
diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java
index 3dccf27bb..ae20e4943 100644
--- a/src/com/android/dialer/calllog/CallLogAdapter.java
+++ b/src/com/android/dialer/calllog/CallLogAdapter.java
@@ -16,18 +16,20 @@
package com.android.dialer.calllog;
+import com.google.common.annotations.VisibleForTesting;
+
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.support.v7.widget.RecyclerView;
import android.os.Bundle;
import android.os.Trace;
import android.preference.PreferenceManager;
import android.provider.CallLog;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.telecom.PhoneAccountHandle;
import android.telephony.PhoneNumberUtils;
@@ -39,6 +41,7 @@ import android.view.View.AccessibilityDelegate;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
+import com.android.contacts.common.preference.ContactsPreferences;
import com.android.contacts.common.util.PermissionsUtil;
import com.android.dialer.PhoneCallDetails;
import com.android.dialer.R;
@@ -51,8 +54,6 @@ import com.android.dialer.filterednumber.FilterNumberDialogFragment;
import com.android.dialer.util.PhoneNumberUtil;
import com.android.dialer.voicemail.VoicemailPlaybackPresenter;
-import com.google.common.annotations.VisibleForTesting;
-
import java.util.HashMap;
import java.util.Map;
@@ -118,12 +119,14 @@ public class CallLogAdapter extends GroupingListAdapter
* its day group. This hashmap provides a means of determining the previous day group without
* having to reverse the cursor to the start of the previous day call log entry.
*/
- private HashMap<Long,Integer> mDayGroups = new HashMap<Long, Integer>();
+ private HashMap<Long, Integer> mDayGroups = new HashMap<>();
private boolean mLoading = true;
private SharedPreferences mPrefs;
+ private ContactsPreferences mContactsPreferences;
+
protected boolean mShowVoicemailPromoCard = false;
/** Instance of helper class for managing views. */
@@ -254,7 +257,7 @@ public class CallLogAdapter extends GroupingListAdapter
CallTypeHelper callTypeHelper = new CallTypeHelper(resources);
mTelecomCallLogCache = new TelecomCallLogCache(mContext);
- mBlockedIdCache = new HashMap<NumberWithCountryIso, Integer>();
+ mBlockedIdCache = new HashMap<>();
PhoneCallDetailsHelper phoneCallDetailsHelper =
new PhoneCallDetailsHelper(mContext, resources, mTelecomCallLogCache);
mCallLogListItemHelper =
@@ -264,6 +267,7 @@ public class CallLogAdapter extends GroupingListAdapter
new FilteredNumberAsyncQueryHandler(mContext.getContentResolver());
mPrefs = PreferenceManager.getDefaultSharedPreferences(context);
+ mContactsPreferences = new ContactsPreferences(mContext);
maybeShowVoicemailPromoCard();
}
@@ -311,6 +315,7 @@ public class CallLogAdapter extends GroupingListAdapter
if (PermissionsUtil.hasPermission(mContext, android.Manifest.permission.READ_CONTACTS)) {
mContactInfoCache.start();
}
+ mContactsPreferences.refreshValue(ContactsPreferences.DISPLAY_ORDER_KEY);
}
public void onPause() {
@@ -460,9 +465,10 @@ public class CallLogAdapter extends GroupingListAdapter
details.dataUsage = c.getLong(CallLogQuery.DATA_USAGE);
}
- if (!TextUtils.isEmpty(info.name)) {
+ String preferredName = getPreferredDisplayName(info);
+ if (!TextUtils.isEmpty(preferredName)) {
details.contactUri = info.lookupUri;
- details.name = info.name;
+ details.name = preferredName;
details.numberType = info.type;
details.numberLabel = info.label;
details.photoUri = info.photoUri;
@@ -532,6 +538,14 @@ public class CallLogAdapter extends GroupingListAdapter
mCallLogListItemHelper.setPhoneCallDetails(views, details);
}
+ private String getPreferredDisplayName(ContactInfo contactInfo) {
+ if (mContactsPreferences.getDisplayOrder() == ContactsPreferences.DISPLAY_ORDER_PRIMARY ||
+ TextUtils.isEmpty(contactInfo.nameAlternative)) {
+ return contactInfo.name;
+ }
+ return contactInfo.nameAlternative;
+ }
+
@Override
public int getItemCount() {
return super.getItemCount() + (mShowVoicemailPromoCard ? 1 : 0)
diff --git a/src/com/android/dialer/calllog/CallLogFragment.java b/src/com/android/dialer/calllog/CallLogFragment.java
index 369730d96..f84ffd5da 100644
--- a/src/com/android/dialer/calllog/CallLogFragment.java
+++ b/src/com/android/dialer/calllog/CallLogFragment.java
@@ -33,8 +33,8 @@ import android.provider.CallLog;
import android.provider.CallLog.Calls;
import android.provider.ContactsContract;
import android.provider.VoicemailContract.Status;
-import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -309,7 +309,6 @@ public class CallLogFragment extends Fragment implements CallLogQueryHandler.Lis
mVoicemailPlaybackPresenter,
mIsCallLogActivity);
mRecyclerView.setAdapter(mAdapter);
-
fetchCalls();
return view;
}
diff --git a/src/com/android/dialer/calllog/ContactInfo.java b/src/com/android/dialer/calllog/ContactInfo.java
index 357c832cf..30f60d9d3 100644
--- a/src/com/android/dialer/calllog/ContactInfo.java
+++ b/src/com/android/dialer/calllog/ContactInfo.java
@@ -34,6 +34,7 @@ public class ContactInfo {
*/
public String lookupKey;
public String name;
+ public String nameAlternative;
public int type;
public String label;
public String number;
@@ -70,6 +71,7 @@ public class ContactInfo {
ContactInfo other = (ContactInfo) obj;
if (!UriUtils.areEqual(lookupUri, other.lookupUri)) return false;
if (!TextUtils.equals(name, other.name)) return false;
+ if (!TextUtils.equals(nameAlternative, other.nameAlternative)) return false;
if (type != other.type) return false;
if (!TextUtils.equals(label, other.label)) return false;
if (!TextUtils.equals(number, other.number)) return false;
@@ -83,9 +85,11 @@ public class ContactInfo {
@Override
public String toString() {
- return Objects.toStringHelper(this).add("lookupUri", lookupUri).add("name", name).add(
- "type", type).add("label", label).add("number", number).add("formattedNumber",
- formattedNumber).add("normalizedNumber", normalizedNumber).add("photoId", photoId)
+ return Objects.toStringHelper(this).add("lookupUri", lookupUri).add("name", name)
+ .add("nameAlternative", nameAlternative)
+ .add("type", type).add("label", label)
+ .add("number", number).add("formattedNumber",formattedNumber)
+ .add("normalizedNumber", normalizedNumber).add("photoId", photoId)
.add("photoUri", photoUri).add("objectId", objectId).toString();
}
}
diff --git a/src/com/android/dialer/calllog/ContactInfoHelper.java b/src/com/android/dialer/calllog/ContactInfoHelper.java
index 2f97bc569..4b9d5532a 100644
--- a/src/com/android/dialer/calllog/ContactInfoHelper.java
+++ b/src/com/android/dialer/calllog/ContactInfoHelper.java
@@ -41,8 +41,6 @@ import com.android.dialerbind.ObjectFactory;
import org.json.JSONException;
import org.json.JSONObject;
-import java.util.List;
-
/**
* Utility class to look up the contact information for a given number.
*/
@@ -151,47 +149,70 @@ public class ContactInfoHelper {
* The {@link ContactInfo#formattedNumber} field is always set to {@code null} in the returned
* value.
*/
- private ContactInfo lookupContactFromUri(Uri uri) {
+ public ContactInfo lookupContactFromUri(Uri uri) {
if (uri == null) {
return null;
}
if (!PermissionsUtil.hasContactsPermissions(mContext)) {
return ContactInfo.EMPTY;
}
- final ContactInfo info;
- Cursor phonesCursor =
- mContext.getContentResolver().query(uri, PhoneQuery._PROJECTION, null, null, null);
-
- if (phonesCursor != null) {
- try {
- if (phonesCursor.moveToFirst()) {
- info = new ContactInfo();
- long contactId = phonesCursor.getLong(PhoneQuery.PERSON_ID);
- String lookupKey = phonesCursor.getString(PhoneQuery.LOOKUP_KEY);
- info.lookupKey = lookupKey;
- info.lookupUri = Contacts.getLookupUri(contactId, lookupKey);
- info.name = phonesCursor.getString(PhoneQuery.NAME);
- info.type = phonesCursor.getInt(PhoneQuery.PHONE_TYPE);
- info.label = phonesCursor.getString(PhoneQuery.LABEL);
- info.number = phonesCursor.getString(PhoneQuery.MATCHED_NUMBER);
- info.normalizedNumber = phonesCursor.getString(PhoneQuery.NORMALIZED_NUMBER);
- info.photoId = phonesCursor.getLong(PhoneQuery.PHOTO_ID);
- info.photoUri =
- UriUtils.parseUriOrNull(phonesCursor.getString(PhoneQuery.PHOTO_URI));
- info.formattedNumber = null;
- } else {
- info = ContactInfo.EMPTY;
- }
- } finally {
- phonesCursor.close();
+
+ Cursor phoneLookupCursor = mContext.getContentResolver().query(uri,
+ PhoneQuery.PHONE_LOOKUP_PROJECTION, null, null, null);
+
+ if (phoneLookupCursor == null) {
+ return null;
+ }
+
+ try {
+ if (!phoneLookupCursor.moveToFirst()) {
+ return ContactInfo.EMPTY;
}
- } else {
- // Failed to fetch the data, ignore this request.
- info = null;
+ String lookupKey = phoneLookupCursor.getString(PhoneQuery.LOOKUP_KEY);
+ ContactInfo contactInfo = createPhoneLookupContactInfo(phoneLookupCursor, lookupKey);
+ contactInfo.nameAlternative = lookUpDisplayNameAlternative(lookupKey);
+ return contactInfo;
+ } finally {
+ phoneLookupCursor.close();
}
+ }
+
+ private ContactInfo createPhoneLookupContactInfo(Cursor phoneLookupCursor, String lookupKey) {
+ ContactInfo info = new ContactInfo();
+ info.lookupKey = lookupKey;
+ info.lookupUri = Contacts.getLookupUri(phoneLookupCursor.getLong(PhoneQuery.PERSON_ID),
+ lookupKey);
+ info.name = phoneLookupCursor.getString(PhoneQuery.NAME);
+ info.type = phoneLookupCursor.getInt(PhoneQuery.PHONE_TYPE);
+ info.label = phoneLookupCursor.getString(PhoneQuery.LABEL);
+ info.number = phoneLookupCursor.getString(PhoneQuery.MATCHED_NUMBER);
+ info.normalizedNumber = phoneLookupCursor.getString(PhoneQuery.NORMALIZED_NUMBER);
+ info.photoId = phoneLookupCursor.getLong(PhoneQuery.PHOTO_ID);
+ info.photoUri = UriUtils.parseUriOrNull(phoneLookupCursor.getString(PhoneQuery.PHOTO_URI));
+ info.formattedNumber = null;
return info;
}
+ private String lookUpDisplayNameAlternative(String lookupKey) {
+ Uri uri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey);
+
+ Cursor cursor = mContext.getContentResolver().query(uri,
+ PhoneQuery.DISPLAY_NAME_ALTERNATIVE_PROJECTION, null, null, null);
+
+ if (cursor == null) {
+ return null;
+ }
+
+ try {
+ if (!cursor.moveToFirst()) {
+ return null;
+ }
+ return cursor.getString(PhoneQuery.NAME_ALTERNATIVE);
+ } finally {
+ cursor.close();
+ }
+ }
+
/**
* Determines the contact information for the given phone number.
* <p>
@@ -367,7 +388,6 @@ public class ContactInfoHelper {
*/
public static ContactInfo getContactInfo(Cursor c) {
ContactInfo info = new ContactInfo();
-
info.lookupUri = UriUtils.parseUriOrNull(c.getString(CallLogQuery.CACHED_LOOKUP_URI));
info.name = c.getString(CallLogQuery.CACHED_NAME);
info.type = c.getInt(CallLogQuery.CACHED_NUMBER_TYPE);
@@ -406,6 +426,4 @@ public class ContactInfoHelper {
return mCachedNumberLookupService != null
&& mCachedNumberLookupService.canReportAsInvalid(sourceType, objectId);
}
-
-
}
diff --git a/src/com/android/dialer/calllog/PhoneQuery.java b/src/com/android/dialer/calllog/PhoneQuery.java
index 719052204..200b5e1f4 100644
--- a/src/com/android/dialer/calllog/PhoneQuery.java
+++ b/src/com/android/dialer/calllog/PhoneQuery.java
@@ -16,13 +16,19 @@
package com.android.dialer.calllog;
+import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.PhoneLookup;
/**
- * The query to look up the {@link ContactInfo} for a given number in the Call Log.
+ * The queries to look up the {@link ContactInfo} for a given number in the Call Log.
*/
final class PhoneQuery {
- public static final String[] _PROJECTION = new String[] {
+
+ /**
+ * Projection to look up the ContactInfo. Does not include DISPLAY_NAME_ALTERNATIVE as that
+ * column isn't available in ContactsCommon.PhoneLookup
+ */
+ public static final String[] PHONE_LOOKUP_PROJECTION = new String[] {
PhoneLookup._ID,
PhoneLookup.DISPLAY_NAME,
PhoneLookup.TYPE,
@@ -42,4 +48,13 @@ final class PhoneQuery {
public static final int PHOTO_ID = 6;
public static final int LOOKUP_KEY = 7;
public static final int PHOTO_URI = 8;
+
+ /**
+ * Projection to look up a contact's DISPLAY_NAME_ALTERNATIVE
+ */
+ public static final String[] DISPLAY_NAME_ALTERNATIVE_PROJECTION = new String[] {
+ Contacts.DISPLAY_NAME_ALTERNATIVE,
+ };
+
+ public static final int NAME_ALTERNATIVE = 0;
}
diff --git a/src/com/android/dialer/contactinfo/ContactInfoCache.java b/src/com/android/dialer/contactinfo/ContactInfoCache.java
index 568f48886..1e2457957 100644
--- a/src/com/android/dialer/contactinfo/ContactInfoCache.java
+++ b/src/com/android/dialer/contactinfo/ContactInfoCache.java
@@ -162,7 +162,7 @@ public class ContactInfoCache {
// The contact info is no longer up to date, we should request it. However, we
// do not need to request them immediately.
enqueueRequest(number, countryIso, cachedContactInfo, false);
- } else if (!callLogInfoMatches(cachedContactInfo, info)) {
+ } else if (!callLogInfoMatches(cachedContactInfo, info)) {
// The call log information does not match the one we have, look it up again.
// We could simply update the call log directly, but that needs to be done in a
// background thread, so it is easier to simply request a new lookup, which will, as
@@ -309,8 +309,7 @@ public class ContactInfoCache {
* Checks whether the contact info from the call log matches the one from the contacts db.
*/
private boolean callLogInfoMatches(ContactInfo callLogInfo, ContactInfo info) {
- // The call log only contains a subset of the fields in the contacts db.
- // Only check those.
+ // The call log only contains a subset of the fields in the contacts db. Only check those.
return TextUtils.equals(callLogInfo.name, info.name)
&& callLogInfo.type == info.type
&& TextUtils.equals(callLogInfo.label, info.label);
diff --git a/tests/src/com/android/dialer/calllog/ContactInfoHelperTest.java b/tests/src/com/android/dialer/calllog/ContactInfoHelperTest.java
new file mode 100644
index 000000000..6d3e86042
--- /dev/null
+++ b/tests/src/com/android/dialer/calllog/ContactInfoHelperTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2015 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.dialer.calllog;
+
+import android.net.Uri;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.PhoneLookup;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+
+import com.android.contacts.common.test.mocks.ContactsMockContext;
+import com.android.contacts.common.test.mocks.MockContentProvider.Query;
+
+import junit.framework.Assert;
+
+@MediumTest
+public class ContactInfoHelperTest extends AndroidTestCase {
+
+ private static final String TEST_COUNTRY_ISO = "US";
+ private static final String TEST_DISPLAY_NAME = "Display Name";
+ private static final String TEST_DISPLAY_NAME_ALTERNATIVE = "Name, Display";
+ private static final String[] TEST_DISPLAY_NAME_ALTERNATIVE_ROW = new String[]{null,
+ TEST_DISPLAY_NAME_ALTERNATIVE};
+ private static final String TEST_LOOKUP_KEY = "lookupKey";
+ private static final String[] TEST_LOOKUP_ROW = new String[]{null, TEST_DISPLAY_NAME,
+ null, null, null, null, null, TEST_LOOKUP_KEY, null};
+
+ private Uri displayNameAlternativeUri;
+ private ContactsMockContext mContext;
+ private ContactInfo mContactInfo;
+ private ContactInfoHelper mContactInfoHelper;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ displayNameAlternativeUri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI,
+ TEST_LOOKUP_KEY);
+ mContext = new ContactsMockContext(getContext());
+ mContactInfo = new ContactInfo();
+ mContactInfo.name = TEST_DISPLAY_NAME;
+ mContactInfo.nameAlternative = TEST_DISPLAY_NAME_ALTERNATIVE;
+ mContactInfoHelper = new ContactInfoHelper(mContext, TEST_COUNTRY_ISO);
+ }
+
+ public void testLookupContactFromUriNullUri() {
+ Assert.assertNull(mContactInfoHelper.lookupContactFromUri(null));
+ }
+
+ public void testLookupContactFromUriNoResults() {
+ setUpQueryExpectations(PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI,
+ PhoneQuery.PHONE_LOOKUP_PROJECTION);
+
+ Assert.assertEquals(ContactInfo.EMPTY, mContactInfoHelper.lookupContactFromUri(
+ PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI));
+ mContext.verify();
+ }
+
+ public void testLookupContactFromUriNoDisplayNameAlternative() {
+ setUpQueryExpectations(PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI,
+ PhoneQuery.PHONE_LOOKUP_PROJECTION, TEST_LOOKUP_ROW);
+ setUpQueryExpectations(displayNameAlternativeUri,
+ PhoneQuery.DISPLAY_NAME_ALTERNATIVE_PROJECTION);
+
+ ContactInfo contactInfo = mContactInfoHelper.lookupContactFromUri(
+ PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI);
+ Assert.assertEquals(TEST_DISPLAY_NAME, contactInfo.name);
+ Assert.assertNull(contactInfo.nameAlternative);
+ mContext.verify();
+ }
+
+ public void testLookupContactFromUriWithDisplayNameAlternative() {
+ setUpQueryExpectations(PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI,
+ PhoneQuery.PHONE_LOOKUP_PROJECTION, TEST_LOOKUP_ROW);
+ setUpQueryExpectations(displayNameAlternativeUri,
+ PhoneQuery.DISPLAY_NAME_ALTERNATIVE_PROJECTION, TEST_DISPLAY_NAME_ALTERNATIVE_ROW);
+
+ ContactInfo contactInfo = mContactInfoHelper.lookupContactFromUri(
+ PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI);
+ Assert.assertEquals(TEST_DISPLAY_NAME, contactInfo.name);
+ Assert.assertEquals(TEST_DISPLAY_NAME_ALTERNATIVE, contactInfo.nameAlternative);
+ mContext.verify();
+ }
+
+ /*
+ * Sets up query expectations to return the given row for all queries for the given
+ * uri and projection. If row is null, an empty cursor is returned for query calls
+ */
+ private void setUpQueryExpectations(Uri uri, String[] projection, String...row) {
+ Query query = mContext.getContactsProvider().expectQuery(uri)
+ .withProjection(projection).withAnySelection().withAnySortOrder();
+ if (row == null || row.length == 0) {
+ query.returnEmptyCursor();
+ return;
+ }
+ query.returnRow(row);
+ }
+}