Loading src/com/android/contacts/calllog/CallLogAdapter.java +52 −13 Original line number Diff line number Diff line Loading @@ -54,6 +54,37 @@ import libcore.util.Objects; public void fetchCalls(); } /** * Stores a phone number of a call with the country code where it originally occurred. * <p> * Note the country does not necessarily specifies the country of the phone number itself, but * it is the country in which the user was in when the call was placed or received. */ private static final class NumberWithCountryIso { public final String number; public final String countryIso; public NumberWithCountryIso(String number, String countryIso) { this.number = number; this.countryIso = countryIso; } @Override public boolean equals(Object o) { if (o == null) return false; if (!(o instanceof NumberWithCountryIso)) return false; NumberWithCountryIso other = (NumberWithCountryIso) o; return TextUtils.equals(number, other.number) && TextUtils.equals(countryIso, other.countryIso); } @Override public int hashCode() { return (number == null ? 0 : number.hashCode()) ^ (countryIso == null ? 0 : countryIso.hashCode()); } } /** The time in millis to delay starting the thread processing requests. */ private static final int START_PROCESSING_REQUESTS_DELAY_MILLIS = 1000; Loading @@ -69,8 +100,10 @@ import libcore.util.Objects; * <p> * The content of the cache is expired (but not purged) whenever the application comes to * the foreground. * <p> * The key is number with the country in which the call was placed or received. */ private ExpirableCache<String, ContactInfo> mContactInfoCache; private ExpirableCache<NumberWithCountryIso, ContactInfo> mContactInfoCache; /** * A request for contact details for the given number. Loading Loading @@ -317,14 +350,15 @@ import libcore.util.Objects; // Check the existing entry in the cache: only if it has changed we should update the // view. ContactInfo existingInfo = mContactInfoCache.getPossiblyExpired(number); NumberWithCountryIso numberCountryIso = new NumberWithCountryIso(number, countryIso); ContactInfo existingInfo = mContactInfoCache.getPossiblyExpired(numberCountryIso); boolean updated = !info.equals(existingInfo); // Store the data in the cache so that the UI thread can use to display it. Store it // even if it has not changed so that it is marked as not expired. mContactInfoCache.put(number, info); mContactInfoCache.put(numberCountryIso, info); // Update the call log even if the cache it is up-to-date: it is possible that the cache // contains the value from a different call log entry. updateCallLogContactInfoCache(number, info, callLogInfo); updateCallLogContactInfoCache(number, countryIso, info, callLogInfo); return updated; } /* Loading Loading @@ -471,8 +505,9 @@ import libcore.util.Objects; } // Lookup contacts with this number NumberWithCountryIso numberCountryIso = new NumberWithCountryIso(number, countryIso); ExpirableCache.CachedValue<ContactInfo> cachedInfo = mContactInfoCache.getCachedValue(number); mContactInfoCache.getCachedValue(numberCountryIso); ContactInfo info = cachedInfo == null ? null : cachedInfo.getValue(); if (!mPhoneNumberHelper.canPlaceCallsTo(number) || mPhoneNumberHelper.isVoicemailNumber(number)) { Loading @@ -480,7 +515,7 @@ import libcore.util.Objects; // for it. info = ContactInfo.EMPTY; } else if (cachedInfo == null) { mContactInfoCache.put(number, ContactInfo.EMPTY); mContactInfoCache.put(numberCountryIso, ContactInfo.EMPTY); // Use the cached contact info from the call log. info = cachedContactInfo; // The db request should happen on a non-UI thread. Loading Loading @@ -558,8 +593,8 @@ import libcore.util.Objects; } /** Stores the updated contact info in the call log if it is different from the current one. */ private void updateCallLogContactInfoCache(String number, ContactInfo updatedInfo, ContactInfo callLogInfo) { private void updateCallLogContactInfoCache(String number, String countryIso, ContactInfo updatedInfo, ContactInfo callLogInfo) { final ContentValues values = new ContentValues(); boolean needsUpdate = false; Loading Loading @@ -617,10 +652,12 @@ import libcore.util.Objects; StringBuilder where = new StringBuilder(); where.append(Calls.NUMBER); where.append(" = ? AND "); where.append(Calls.COUNTRY_ISO); where.append(" = ?"); mContext.getContentResolver().update(Calls.CONTENT_URI_WITH_VOICEMAIL, values, where.toString(), new String[]{ number }); where.toString(), new String[]{ number, countryIso }); } /** Returns the contact information as stored in the call log. */ Loading Loading @@ -674,8 +711,9 @@ import libcore.util.Objects; } @VisibleForTesting void injectContactInfoForTest(String number, ContactInfo contactInfo) { mContactInfoCache.put(number, contactInfo); void injectContactInfoForTest(String number, String countryIso, ContactInfo contactInfo) { NumberWithCountryIso numberCountryIso = new NumberWithCountryIso(number, countryIso); mContactInfoCache.put(numberCountryIso, contactInfo); } @Override Loading @@ -692,10 +730,11 @@ import libcore.util.Objects; * Else if the number in the contacts starts with a "+", use that one * Else if the number in the contacts is longer, use that one */ public String getBetterNumberFromContacts(String number) { public String getBetterNumberFromContacts(String number, String countryIso) { String matchingNumber = null; // Look in the cache first. If it's not found then query the Phones db ContactInfo ci = mContactInfoCache.getPossiblyExpired(number); NumberWithCountryIso numberCountryIso = new NumberWithCountryIso(number, countryIso); ContactInfo ci = mContactInfoCache.getPossiblyExpired(numberCountryIso); if (ci != null && ci != ContactInfo.EMPTY) { matchingNumber = ci.number; } else { Loading src/com/android/contacts/calllog/CallLogFragment.java +2 −1 Original line number Diff line number Diff line Loading @@ -334,7 +334,8 @@ public class CallLogFragment extends ListFragment implements ViewPagerVisibility (callType == Calls.INCOMING_TYPE || callType == Calls.MISSED_TYPE)) { // If the caller-id matches a contact with a better qualified number, use it number = mAdapter.getBetterNumberFromContacts(number); String countryIso = cursor.getString(CallLogQuery.COUNTRY_ISO); number = mAdapter.getBetterNumberFromContacts(number, countryIso); } intent = new Intent(Intent.ACTION_CALL_PRIVILEGED, Uri.fromParts("tel", number, null)); Loading tests/src/com/android/contacts/calllog/CallLogAdapterTest.java +3 −3 Original line number Diff line number Diff line Loading @@ -117,7 +117,7 @@ public class CallLogAdapterTest extends AndroidTestCase { public void testBindView_NoCallLogButMemoryCache_EnqueueRequest() { mCursor.addRow(createCallLogEntry()); mAdapter.injectContactInfoForTest(TEST_NUMBER, createContactInfo()); mAdapter.injectContactInfoForTest(TEST_NUMBER, TEST_COUNTRY_ISO, createContactInfo()); // Bind the views of a single row. mAdapter.bindStandAloneView(mView, getContext(), mCursor); Loading @@ -132,7 +132,7 @@ public class CallLogAdapterTest extends AndroidTestCase { public void testBindView_BothCallLogAndMemoryCache_NoEnqueueRequest() { mCursor.addRow(createCallLogEntryWithCachedValues()); mAdapter.injectContactInfoForTest(TEST_NUMBER, createContactInfo()); mAdapter.injectContactInfoForTest(TEST_NUMBER, TEST_COUNTRY_ISO, createContactInfo()); // Bind the views of a single row. mAdapter.bindStandAloneView(mView, getContext(), mCursor); Loading @@ -147,7 +147,7 @@ public class CallLogAdapterTest extends AndroidTestCase { // Contact info contains a different name. ContactInfo info = createContactInfo(); info.name = "new name"; mAdapter.injectContactInfoForTest(TEST_NUMBER, info); mAdapter.injectContactInfoForTest(TEST_NUMBER, TEST_COUNTRY_ISO, info); // Bind the views of a single row. mAdapter.bindStandAloneView(mView, getContext(), mCursor); Loading tests/src/com/android/contacts/calllog/CallLogFragmentTest.java +1 −1 Original line number Diff line number Diff line Loading @@ -482,7 +482,7 @@ public class CallLogFragmentTest extends ActivityInstrumentationTestCase2<Fragme contactInfo.formattedNumber = formattedNumber; contactInfo.normalizedNumber = number; contactInfo.photoId = 0; mAdapter.injectContactInfoForTest(number, contactInfo); mAdapter.injectContactInfoForTest(number, TEST_COUNTRY_ISO, contactInfo); } /** Loading Loading
src/com/android/contacts/calllog/CallLogAdapter.java +52 −13 Original line number Diff line number Diff line Loading @@ -54,6 +54,37 @@ import libcore.util.Objects; public void fetchCalls(); } /** * Stores a phone number of a call with the country code where it originally occurred. * <p> * Note the country does not necessarily specifies the country of the phone number itself, but * it is the country in which the user was in when the call was placed or received. */ private static final class NumberWithCountryIso { public final String number; public final String countryIso; public NumberWithCountryIso(String number, String countryIso) { this.number = number; this.countryIso = countryIso; } @Override public boolean equals(Object o) { if (o == null) return false; if (!(o instanceof NumberWithCountryIso)) return false; NumberWithCountryIso other = (NumberWithCountryIso) o; return TextUtils.equals(number, other.number) && TextUtils.equals(countryIso, other.countryIso); } @Override public int hashCode() { return (number == null ? 0 : number.hashCode()) ^ (countryIso == null ? 0 : countryIso.hashCode()); } } /** The time in millis to delay starting the thread processing requests. */ private static final int START_PROCESSING_REQUESTS_DELAY_MILLIS = 1000; Loading @@ -69,8 +100,10 @@ import libcore.util.Objects; * <p> * The content of the cache is expired (but not purged) whenever the application comes to * the foreground. * <p> * The key is number with the country in which the call was placed or received. */ private ExpirableCache<String, ContactInfo> mContactInfoCache; private ExpirableCache<NumberWithCountryIso, ContactInfo> mContactInfoCache; /** * A request for contact details for the given number. Loading Loading @@ -317,14 +350,15 @@ import libcore.util.Objects; // Check the existing entry in the cache: only if it has changed we should update the // view. ContactInfo existingInfo = mContactInfoCache.getPossiblyExpired(number); NumberWithCountryIso numberCountryIso = new NumberWithCountryIso(number, countryIso); ContactInfo existingInfo = mContactInfoCache.getPossiblyExpired(numberCountryIso); boolean updated = !info.equals(existingInfo); // Store the data in the cache so that the UI thread can use to display it. Store it // even if it has not changed so that it is marked as not expired. mContactInfoCache.put(number, info); mContactInfoCache.put(numberCountryIso, info); // Update the call log even if the cache it is up-to-date: it is possible that the cache // contains the value from a different call log entry. updateCallLogContactInfoCache(number, info, callLogInfo); updateCallLogContactInfoCache(number, countryIso, info, callLogInfo); return updated; } /* Loading Loading @@ -471,8 +505,9 @@ import libcore.util.Objects; } // Lookup contacts with this number NumberWithCountryIso numberCountryIso = new NumberWithCountryIso(number, countryIso); ExpirableCache.CachedValue<ContactInfo> cachedInfo = mContactInfoCache.getCachedValue(number); mContactInfoCache.getCachedValue(numberCountryIso); ContactInfo info = cachedInfo == null ? null : cachedInfo.getValue(); if (!mPhoneNumberHelper.canPlaceCallsTo(number) || mPhoneNumberHelper.isVoicemailNumber(number)) { Loading @@ -480,7 +515,7 @@ import libcore.util.Objects; // for it. info = ContactInfo.EMPTY; } else if (cachedInfo == null) { mContactInfoCache.put(number, ContactInfo.EMPTY); mContactInfoCache.put(numberCountryIso, ContactInfo.EMPTY); // Use the cached contact info from the call log. info = cachedContactInfo; // The db request should happen on a non-UI thread. Loading Loading @@ -558,8 +593,8 @@ import libcore.util.Objects; } /** Stores the updated contact info in the call log if it is different from the current one. */ private void updateCallLogContactInfoCache(String number, ContactInfo updatedInfo, ContactInfo callLogInfo) { private void updateCallLogContactInfoCache(String number, String countryIso, ContactInfo updatedInfo, ContactInfo callLogInfo) { final ContentValues values = new ContentValues(); boolean needsUpdate = false; Loading Loading @@ -617,10 +652,12 @@ import libcore.util.Objects; StringBuilder where = new StringBuilder(); where.append(Calls.NUMBER); where.append(" = ? AND "); where.append(Calls.COUNTRY_ISO); where.append(" = ?"); mContext.getContentResolver().update(Calls.CONTENT_URI_WITH_VOICEMAIL, values, where.toString(), new String[]{ number }); where.toString(), new String[]{ number, countryIso }); } /** Returns the contact information as stored in the call log. */ Loading Loading @@ -674,8 +711,9 @@ import libcore.util.Objects; } @VisibleForTesting void injectContactInfoForTest(String number, ContactInfo contactInfo) { mContactInfoCache.put(number, contactInfo); void injectContactInfoForTest(String number, String countryIso, ContactInfo contactInfo) { NumberWithCountryIso numberCountryIso = new NumberWithCountryIso(number, countryIso); mContactInfoCache.put(numberCountryIso, contactInfo); } @Override Loading @@ -692,10 +730,11 @@ import libcore.util.Objects; * Else if the number in the contacts starts with a "+", use that one * Else if the number in the contacts is longer, use that one */ public String getBetterNumberFromContacts(String number) { public String getBetterNumberFromContacts(String number, String countryIso) { String matchingNumber = null; // Look in the cache first. If it's not found then query the Phones db ContactInfo ci = mContactInfoCache.getPossiblyExpired(number); NumberWithCountryIso numberCountryIso = new NumberWithCountryIso(number, countryIso); ContactInfo ci = mContactInfoCache.getPossiblyExpired(numberCountryIso); if (ci != null && ci != ContactInfo.EMPTY) { matchingNumber = ci.number; } else { Loading
src/com/android/contacts/calllog/CallLogFragment.java +2 −1 Original line number Diff line number Diff line Loading @@ -334,7 +334,8 @@ public class CallLogFragment extends ListFragment implements ViewPagerVisibility (callType == Calls.INCOMING_TYPE || callType == Calls.MISSED_TYPE)) { // If the caller-id matches a contact with a better qualified number, use it number = mAdapter.getBetterNumberFromContacts(number); String countryIso = cursor.getString(CallLogQuery.COUNTRY_ISO); number = mAdapter.getBetterNumberFromContacts(number, countryIso); } intent = new Intent(Intent.ACTION_CALL_PRIVILEGED, Uri.fromParts("tel", number, null)); Loading
tests/src/com/android/contacts/calllog/CallLogAdapterTest.java +3 −3 Original line number Diff line number Diff line Loading @@ -117,7 +117,7 @@ public class CallLogAdapterTest extends AndroidTestCase { public void testBindView_NoCallLogButMemoryCache_EnqueueRequest() { mCursor.addRow(createCallLogEntry()); mAdapter.injectContactInfoForTest(TEST_NUMBER, createContactInfo()); mAdapter.injectContactInfoForTest(TEST_NUMBER, TEST_COUNTRY_ISO, createContactInfo()); // Bind the views of a single row. mAdapter.bindStandAloneView(mView, getContext(), mCursor); Loading @@ -132,7 +132,7 @@ public class CallLogAdapterTest extends AndroidTestCase { public void testBindView_BothCallLogAndMemoryCache_NoEnqueueRequest() { mCursor.addRow(createCallLogEntryWithCachedValues()); mAdapter.injectContactInfoForTest(TEST_NUMBER, createContactInfo()); mAdapter.injectContactInfoForTest(TEST_NUMBER, TEST_COUNTRY_ISO, createContactInfo()); // Bind the views of a single row. mAdapter.bindStandAloneView(mView, getContext(), mCursor); Loading @@ -147,7 +147,7 @@ public class CallLogAdapterTest extends AndroidTestCase { // Contact info contains a different name. ContactInfo info = createContactInfo(); info.name = "new name"; mAdapter.injectContactInfoForTest(TEST_NUMBER, info); mAdapter.injectContactInfoForTest(TEST_NUMBER, TEST_COUNTRY_ISO, info); // Bind the views of a single row. mAdapter.bindStandAloneView(mView, getContext(), mCursor); Loading
tests/src/com/android/contacts/calllog/CallLogFragmentTest.java +1 −1 Original line number Diff line number Diff line Loading @@ -482,7 +482,7 @@ public class CallLogFragmentTest extends ActivityInstrumentationTestCase2<Fragme contactInfo.formattedNumber = formattedNumber; contactInfo.normalizedNumber = number; contactInfo.photoId = 0; mAdapter.injectContactInfoForTest(number, contactInfo); mAdapter.injectContactInfoForTest(number, TEST_COUNTRY_ISO, contactInfo); } /** Loading