From 45258c5b6badb9171b237d6f128862eb44e7226f Mon Sep 17 00:00:00 2001 From: Jeffrey Sharkey <> Date: Tue, 31 Mar 2009 14:44:18 -0700 Subject: [PATCH] AI 143778: am: CL 143722 Correctly format phone numbers in call log, instead of leaving raw numbers. Caches Editable and Locale values to minimize allocations, and caches formatted values along with other ContactInfo details. We need to be extremely careful with this change, as it impacts a performance-sensitive codepath: scrolling through the call log. Original author: jsharkey Merged from: //branches/cupcake/... Automated import of CL 143778 --- .../android/contacts/RecentCallsListActivity.java | 65 +++++++++++++++++++++- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/src/com/android/contacts/RecentCallsListActivity.java b/src/com/android/contacts/RecentCallsListActivity.java index 8949f6e..6abaf23 100644 --- a/src/com/android/contacts/RecentCallsListActivity.java +++ b/src/com/android/contacts/RecentCallsListActivity.java @@ -39,6 +39,7 @@ import android.provider.Contacts.Phones; import android.provider.Contacts.Intents.Insert; import android.telephony.PhoneNumberUtils; import android.telephony.TelephonyManager; +import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.text.format.DateUtils; import android.util.Log; @@ -62,6 +63,7 @@ import com.android.internal.telephony.ITelephony; import java.util.HashMap; import java.util.LinkedList; +import java.util.Locale; import java.lang.ref.WeakReference; /** @@ -124,6 +126,7 @@ public class RecentCallsListActivity extends ListActivity public int type; public String label; public String number; + public String formattedNumber; public static ContactInfo EMPTY = new ContactInfo(); } @@ -144,6 +147,23 @@ public class RecentCallsListActivity extends ListActivity int numberType; String numberLabel; } + + /** + * Shared builder used by {@link #formatPhoneNumber(String)} to minimize + * allocations when formatting phone numbers. + */ + private static final SpannableStringBuilder sEditable = new SpannableStringBuilder(); + + /** + * Invalid formatting type constant for {@link #sFormattingType}. + */ + private static final int FORMATTING_TYPE_INVALID = -1; + + /** + * Cached formatting type for current {@link Locale}, as provided by + * {@link PhoneNumberUtils#getFormatTypeForLocale(Locale)}. + */ + private static int sFormattingType = FORMATTING_TYPE_INVALID; /** Adapter class to fill in data for the Call Log */ final class RecentCallsAdapter extends ResourceCursorAdapter @@ -300,6 +320,10 @@ public class RecentCallsListActivity extends ListActivity info.type = phonesCursor.getInt(PHONE_TYPE_COLUMN_INDEX); info.label = phonesCursor.getString(LABEL_COLUMN_INDEX); info.number = phonesCursor.getString(MATCHED_NUMBER_COLUMN_INDEX); + + // New incoming phone number invalidates our formatted + // cache. Any cache fills happen only on the GUI thread. + info.formattedNumber = null; mContactInfo.put(ciq.number, info); // Inform list to update this item, if in view @@ -366,6 +390,7 @@ public class RecentCallsListActivity extends ListActivity final RecentCallsListItemViews views = (RecentCallsListItemViews) view.getTag(); String number = c.getString(NUMBER_COLUMN_INDEX); + String formattedNumber = null; String callerName = c.getString(CALLER_NAME_COLUMN_INDEX); int callerNumberType = c.getInt(CALLER_NUMBERTYPE_COLUMN_INDEX); String callerNumberLabel = c.getString(CALLER_NUMBERLABEL_COLUMN_INDEX); @@ -393,6 +418,12 @@ public class RecentCallsListActivity extends ListActivity enqueueRequest(number, c.getPosition(), callerName, callerNumberType, callerNumberLabel); } + + // Format and cache phone number for found contact + if (info.formattedNumber == null) { + info.formattedNumber = formatPhoneNumber(info.number); + } + formattedNumber = info.formattedNumber; } String name = info.name; @@ -405,6 +436,9 @@ public class RecentCallsListActivity extends ListActivity name = callerName; ntype = callerNumberType; label = callerNumberLabel; + + // Format the cached call_log phone number + formattedNumber = formatPhoneNumber(number); } // Set the text lines if (!TextUtils.isEmpty(name)) { @@ -413,7 +447,7 @@ public class RecentCallsListActivity extends ListActivity CharSequence numberLabel = Phones.getDisplayLabel(context, ntype, label, mLabelArray); views.numberView.setVisibility(View.VISIBLE); - views.numberView.setText(number); + views.numberView.setText(formattedNumber); if (!TextUtils.isEmpty(numberLabel)) { views.labelView.setText(numberLabel); views.labelView.setVisibility(View.VISIBLE); @@ -430,8 +464,8 @@ public class RecentCallsListActivity extends ListActivity } else if (number.equals(mVoiceMailNumber)) { number = getString(R.string.voicemail); } else { - // Just a raw number, format it to look pretty - number = PhoneNumberUtils.formatNumber(number); + // Just a raw number, and no cache, so format it nicely + number = formatPhoneNumber(number); } views.line1View.setText(number); @@ -510,6 +544,9 @@ public class RecentCallsListActivity extends ListActivity mVoiceMailNumber = ((TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE)) .getVoiceMailNumber(); mQueryHandler = new QueryHandler(this); + + // Reset locale-based formatting cache + sFormattingType = FORMATTING_TYPE_INVALID; } @Override @@ -568,6 +605,28 @@ public class RecentCallsListActivity extends ListActivity } } + /** + * Format the given phone number using + * {@link PhoneNumberUtils#formatNumber(android.text.Editable, int)}. This + * helper method uses {@link #sEditable} and {@link #sFormattingType} to + * prevent allocations between multiple calls. + *

+ * Because of the shared {@link #sEditable} builder, this method is not + * thread safe, and should only be called from the GUI thread. + */ + private String formatPhoneNumber(String number) { + // Cache formatting type if not already present + if (sFormattingType == FORMATTING_TYPE_INVALID) { + sFormattingType = PhoneNumberUtils.getFormatTypeForLocale(Locale.getDefault()); + } + + sEditable.clear(); + sEditable.append(number); + + PhoneNumberUtils.formatNumber(sEditable, sFormattingType); + return sEditable.toString(); + } + private void resetNewCallsFlag() { // Mark all "new" missed calls as not new anymore StringBuilder where = new StringBuilder("type="); -- 2.11.0