Format the number through new method

Change-Id: I536d7d94ab360daedfb36e645351d24d28cd2f37
diff --git a/src/com/android/contacts/CallDetailActivity.java b/src/com/android/contacts/CallDetailActivity.java
index 14f54c9..b3c68ef 100644
--- a/src/com/android/contacts/CallDetailActivity.java
+++ b/src/com/android/contacts/CallDetailActivity.java
@@ -63,6 +63,7 @@
     private TextView mCallDuration;
 
     private String mNumber = null;
+    private String mDefaultCountryIso;
 
     /* package */ LayoutInflater mInflater;
     /* package */ Resources mResources;
@@ -72,12 +73,14 @@
         CallLog.Calls.DURATION,
         CallLog.Calls.NUMBER,
         CallLog.Calls.TYPE,
+        CallLog.Calls.COUNTRY_ISO,
     };
 
     static final int DATE_COLUMN_INDEX = 0;
     static final int DURATION_COLUMN_INDEX = 1;
     static final int NUMBER_COLUMN_INDEX = 2;
     static final int CALL_TYPE_COLUMN_INDEX = 3;
+    static final int COUNTRY_ISO_COLUMN_INDEX = 4;
 
     static final String[] PHONES_PROJECTION = new String[] {
         PhoneLookup._ID,
@@ -85,12 +88,14 @@
         PhoneLookup.TYPE,
         PhoneLookup.LABEL,
         PhoneLookup.NUMBER,
+        PhoneLookup.NORMALIZED_NUMBER,
     };
     static final int COLUMN_INDEX_ID = 0;
     static final int COLUMN_INDEX_NAME = 1;
     static final int COLUMN_INDEX_TYPE = 2;
     static final int COLUMN_INDEX_LABEL = 3;
     static final int COLUMN_INDEX_NUMBER = 4;
+    static final int COLUMN_INDEX_NORMALIZED_NUMBER = 5;
 
     @Override
     protected void onCreate(Bundle icicle) {
@@ -105,6 +110,7 @@
         mCallTypeIcon = (ImageView) findViewById(R.id.icon);
         mCallTime = (TextView) findViewById(R.id.time);
         mCallDuration = (TextView) findViewById(R.id.duration);
+        mDefaultCountryIso = ContactsUtils.getCurrentCountryIso(this);
 
         getListView().setOnItemClickListener(this);
     }
@@ -149,7 +155,10 @@
                 long date = callCursor.getLong(DATE_COLUMN_INDEX);
                 long duration = callCursor.getLong(DURATION_COLUMN_INDEX);
                 int callType = callCursor.getInt(CALL_TYPE_COLUMN_INDEX);
-
+                String countryIso = callCursor.getString(COUNTRY_ISO_COLUMN_INDEX);
+                if (TextUtils.isEmpty(countryIso)) {
+                    countryIso = mDefaultCountryIso;
+                }
                 // Pull out string in format [relative], [date]
                 CharSequence dateClause = DateUtils.formatDateRange(this, date, date,
                         DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE |
@@ -209,12 +218,14 @@
                             callText = getString(R.string.recentCalls_callNumber,
                                     phonesCursor.getString(COLUMN_INDEX_NAME));
                             mNumber = PhoneNumberUtils.formatNumber(
-                                    phonesCursor.getString(COLUMN_INDEX_NUMBER));
+                                    phonesCursor.getString(COLUMN_INDEX_NUMBER),
+                                    phonesCursor.getString(COLUMN_INDEX_NORMALIZED_NUMBER),
+                                    countryIso);
                             callLabel = Phone.getDisplayLabel(this,
                                     phonesCursor.getInt(COLUMN_INDEX_TYPE),
                                     phonesCursor.getString(COLUMN_INDEX_LABEL)).toString();
                         } else {
-                            mNumber = PhoneNumberUtils.formatNumber(mNumber);
+                            mNumber = PhoneNumberUtils.formatNumber(mNumber, countryIso);
                         }
                     } finally {
                         if (phonesCursor != null) phonesCursor.close();
diff --git a/src/com/android/contacts/ContactsUtils.java b/src/com/android/contacts/ContactsUtils.java
index 2bc2721..4e5a20a 100644
--- a/src/com/android/contacts/ContactsUtils.java
+++ b/src/com/android/contacts/ContactsUtils.java
@@ -28,7 +28,6 @@
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.drawable.Drawable;
-import android.location.Country;
 import android.location.CountryDetector;
 import android.net.Uri;
 import android.provider.ContactsContract.Contacts;
@@ -570,7 +569,6 @@
     public static final String getCurrentCountryIso(Context context) {
         CountryDetector detector =
                 (CountryDetector) context.getSystemService(Context.COUNTRY_DETECTOR);
-        Country country = detector.detectCountry();
-        return country.getCountryIso();
+        return detector.detectCountry().getCountryIso();
     }
 }
diff --git a/src/com/android/contacts/RecentCallsListActivity.java b/src/com/android/contacts/RecentCallsListActivity.java
index b84fcd4..85fd4e2 100644
--- a/src/com/android/contacts/RecentCallsListActivity.java
+++ b/src/com/android/contacts/RecentCallsListActivity.java
@@ -53,7 +53,6 @@
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 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;
@@ -75,7 +74,6 @@
 import java.lang.ref.WeakReference;
 import java.util.HashMap;
 import java.util.LinkedList;
-import java.util.Locale;
 
 /**
  * Displays a list of call log entries.
@@ -93,8 +91,8 @@
             Calls.TYPE,
             Calls.CACHED_NAME,
             Calls.CACHED_NUMBER_TYPE,
-            Calls.CACHED_NUMBER_LABEL
-    };
+            Calls.CACHED_NUMBER_LABEL,
+            Calls.COUNTRY_ISO};
 
     static final int ID_COLUMN_INDEX = 0;
     static final int NUMBER_COLUMN_INDEX = 1;
@@ -104,6 +102,7 @@
     static final int CALLER_NAME_COLUMN_INDEX = 5;
     static final int CALLER_NUMBERTYPE_COLUMN_INDEX = 6;
     static final int CALLER_NUMBERLABEL_COLUMN_INDEX = 7;
+    static final int COUNTRY_ISO_COLUMN_INDEX = 8;
 
     /** The projection to use when querying the phones table */
     static final String[] PHONES_PROJECTION = new String[] {
@@ -111,14 +110,15 @@
             PhoneLookup.DISPLAY_NAME,
             PhoneLookup.TYPE,
             PhoneLookup.LABEL,
-            PhoneLookup.NUMBER
-    };
+            PhoneLookup.NUMBER,
+            PhoneLookup.NORMALIZED_NUMBER};
 
     static final int PERSON_ID_COLUMN_INDEX = 0;
     static final int NAME_COLUMN_INDEX = 1;
     static final int PHONE_TYPE_COLUMN_INDEX = 2;
     static final int LABEL_COLUMN_INDEX = 3;
     static final int MATCHED_NUMBER_COLUMN_INDEX = 4;
+    static final int NORMALIZED_NUMBER_COLUMN_INDEX = 5;
 
     private static final int MENU_ITEM_DELETE = 1;
     private static final int MENU_ITEM_DELETE_ALL = 2;
@@ -132,6 +132,7 @@
     RecentCallsAdapter mAdapter;
     private QueryHandler mQueryHandler;
     String mVoiceMailNumber;
+    private String mCurrentCountryIso;
 
     static final class ContactInfo {
         public long personId;
@@ -140,6 +141,7 @@
         public String label;
         public String number;
         public String formattedNumber;
+        public String normalizedNumber;
 
         public static ContactInfo EMPTY = new ContactInfo();
     }
@@ -163,23 +165,6 @@
         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 GroupingListAdapter
             implements Runnable, ViewTreeObserver.OnPreDrawListener, View.OnClickListener {
@@ -355,7 +340,8 @@
                         info.type = phonesCursor.getInt(PHONE_TYPE_COLUMN_INDEX);
                         info.label = phonesCursor.getString(LABEL_COLUMN_INDEX);
                         info.number = phonesCursor.getString(MATCHED_NUMBER_COLUMN_INDEX);
-
+                        info.normalizedNumber =
+                                phonesCursor.getString(NORMALIZED_NUMBER_COLUMN_INDEX);
                         // New incoming phone number invalidates our formatted
                         // cache. Any cache fills happen only on the GUI thread.
                         info.formattedNumber = null;
@@ -536,7 +522,7 @@
             String callerName = c.getString(CALLER_NAME_COLUMN_INDEX);
             int callerNumberType = c.getInt(CALLER_NUMBERTYPE_COLUMN_INDEX);
             String callerNumberLabel = c.getString(CALLER_NUMBERLABEL_COLUMN_INDEX);
-
+            String countryIso = c.getString(COUNTRY_ISO_COLUMN_INDEX);
             // Store away the number so we can call it directly if you click on the call icon
             views.callView.setTag(number);
 
@@ -563,7 +549,8 @@
 
                 // Format and cache phone number for found contact
                 if (info.formattedNumber == null) {
-                    info.formattedNumber = formatPhoneNumber(info.number);
+                    info.formattedNumber =
+                            formatPhoneNumber(info.number, info.normalizedNumber, countryIso);
                 }
                 formattedNumber = info.formattedNumber;
             }
@@ -580,7 +567,7 @@
                 label = callerNumberLabel;
 
                 // Format the cached call_log phone number
-                formattedNumber = formatPhoneNumber(number);
+                formattedNumber = formatPhoneNumber(number, null, countryIso);
             }
             // Set the text lines and call icon.
             // Assumes the call back feature is on most of the
@@ -614,7 +601,7 @@
                     number = getString(R.string.voicemail);
                 } else {
                     // Just a raw number, and no cache, so format it nicely
-                    number = formatPhoneNumber(number);
+                    number = formatPhoneNumber(number, null, countryIso);
                 }
 
                 views.line1View.setText(number);
@@ -726,8 +713,7 @@
                 .getVoiceMailNumber();
         mQueryHandler = new QueryHandler(this);
 
-        // Reset locale-based formatting cache
-        sFormattingType = FORMATTING_TYPE_INVALID;
+        mCurrentCountryIso = ContactsUtils.getCurrentCountryIso(this);
     }
 
     @Override
@@ -784,31 +770,24 @@
     }
 
     /**
-     * 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.
-     * <p>
-     * Because of the shared {@link #sEditable} builder, <b>this method is not
-     * thread safe</b>, and should only be called from the GUI thread.
-     * <p>
-     * If the given String object is null or empty, return an empty String.
+     * Format the given phone number
+     *
+     * @param number the number to be formatted.
+     * @param normalizedNumber the normalized number of the given number.
+     * @param countryIso the ISO 3166-1 two letters country code, the country's
+     *        convention will be used to format the number if the normalized
+     *        phone is null.
+     *
+     * @return the formatted number, or the given number if it was formatted.
      */
-    private String formatPhoneNumber(String number) {
+    private String formatPhoneNumber(String number, String normalizedNumber, String countryIso) {
         if (TextUtils.isEmpty(number)) {
             return "";
         }
-
-        // Cache formatting type if not already present
-        if (sFormattingType == FORMATTING_TYPE_INVALID) {
-            sFormattingType = PhoneNumberUtils.getFormatTypeForLocale(Locale.getDefault());
+        if (TextUtils.isEmpty(countryIso)) {
+            countryIso = mCurrentCountryIso;
         }
-
-        sEditable.clear();
-        sEditable.append(number);
-
-        PhoneNumberUtils.formatNumber(sEditable, sFormattingType);
-        return sEditable.toString();
+        return PhoneNumberUtils.formatNumber(number, normalizedNumber, countryIso);
     }
 
     private void resetNewCallsFlag() {
diff --git a/src/com/android/contacts/TwelveKeyDialer.java b/src/com/android/contacts/TwelveKeyDialer.java
index b9a65ae..b93375c 100644
--- a/src/com/android/contacts/TwelveKeyDialer.java
+++ b/src/com/android/contacts/TwelveKeyDialer.java
@@ -137,6 +137,8 @@
     /** Indicates if we are opening this dialer to add a call from the InCallScreen. */
     private boolean mIsAddCallMode;
 
+    private String mCurrentCountryIso;
+
     PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
             /**
              * Listen for phone state changes so that we can take down the
@@ -190,6 +192,7 @@
     protected void onCreate(Bundle icicle) {
         super.onCreate(icicle);
 
+        mCurrentCountryIso = ContactsUtils.getCurrentCountryIso(this);
         Resources r = getResources();
         // Do not show title in the case the device is in carmode.
         if ((r.getConfiguration().uiMode & Configuration.UI_MODE_TYPE_MASK) ==
@@ -268,8 +271,7 @@
     }
 
     protected void maybeAddNumberFormatting() {
-        mDigits.addTextChangedListener(
-                new PhoneNumberFormattingTextWatcher(ContactsUtils.getCurrentCountryIso(this)));
+        mDigits.addTextChangedListener(new PhoneNumberFormattingTextWatcher(mCurrentCountryIso));
     }
 
     /**
@@ -309,18 +311,19 @@
                 if ("tel".equals(uri.getScheme())) {
                     // Put the requested number into the input area
                     String data = uri.getSchemeSpecificPart();
-                    setFormattedDigits(data);
+                    setFormattedDigits(data, null);
                 } else {
                     String type = intent.getType();
                     if (People.CONTENT_ITEM_TYPE.equals(type)
                             || Phones.CONTENT_ITEM_TYPE.equals(type)) {
                         // Query the phone number
                         Cursor c = getContentResolver().query(intent.getData(),
-                                new String[] {PhonesColumns.NUMBER}, null, null, null);
+                                new String[] {PhonesColumns.NUMBER, PhonesColumns.NUMBER_KEY},
+                                null, null, null);
                         if (c != null) {
                             if (c.moveToFirst()) {
                                 // Put the number into the input area
-                                setFormattedDigits(c.getString(0));
+                                setFormattedDigits(c.getString(0), c.getString(1));
                             }
                             c.close();
                         }
@@ -360,10 +363,11 @@
         return ignoreState;
     }
 
-    protected void setFormattedDigits(String data) {
+    protected void setFormattedDigits(String data, String normalizedNumber) {
         // strip the non-dialable numbers out of the data string.
         String dialString = PhoneNumberUtils.extractNetworkPortion(data);
-        dialString = PhoneNumberUtils.formatNumber(dialString);
+        dialString =
+                PhoneNumberUtils.formatNumber(dialString, normalizedNumber, mCurrentCountryIso);
         if (!TextUtils.isEmpty(dialString)) {
             Editable digits = mDigits.getText();
             digits.replace(0, digits.length(), dialString);
diff --git a/src/com/android/contacts/ui/widget/ReadOnlyContactEditorView.java b/src/com/android/contacts/ui/widget/ReadOnlyContactEditorView.java
index 011bcb1..5c114d1 100644
--- a/src/com/android/contacts/ui/widget/ReadOnlyContactEditorView.java
+++ b/src/com/android/contacts/ui/widget/ReadOnlyContactEditorView.java
@@ -16,6 +16,7 @@
 
 package com.android.contacts.ui.widget;
 
+import com.android.contacts.ContactsUtils;
 import com.android.contacts.R;
 import com.android.contacts.model.ContactsSource;
 import com.android.contacts.model.EntityDelta;
@@ -163,7 +164,9 @@
                 v = (TextView) field.findViewById(R.id.label);
                 v.setText(mContext.getText(R.string.phoneLabelsGroup));
                 v = (TextView) field.findViewById(R.id.data);
-                v.setText(PhoneNumberUtils.formatNumber(phone.getAsString(Phone.NUMBER)));
+                v.setText(PhoneNumberUtils.formatNumber(phone.getAsString(Phone.NUMBER),
+                        phone.getAsString(Phone.NORMALIZED_NUMBER),
+                        ContactsUtils.getCurrentCountryIso(getContext())));
                 mGeneral.addView(field);
             }
         }
diff --git a/src/com/android/contacts/views/detail/ContactDetailFragment.java b/src/com/android/contacts/views/detail/ContactDetailFragment.java
index 8dbb3fd..030996b 100644
--- a/src/com/android/contacts/views/detail/ContactDetailFragment.java
+++ b/src/com/android/contacts/views/detail/ContactDetailFragment.java
@@ -73,6 +73,7 @@
 import android.provider.ContactsContract.Data;
 import android.provider.ContactsContract.Directory;
 import android.provider.ContactsContract.DisplayNameSources;
+import android.provider.ContactsContract.PhoneLookup;
 import android.provider.ContactsContract.RawContacts;
 import android.provider.ContactsContract.StatusUpdates;
 import android.telephony.PhoneNumberUtils;
@@ -120,6 +121,7 @@
     private boolean mAllRestricted;
     private final ArrayList<Long> mWritableRawContactIds = new ArrayList<Long>();
     private int mNumPhoneNumbers = 0;
+    private String mDefaultCountryIso;
 
     /**
      * Device capability: Set during buildEntries and used in the long-press context menu
@@ -174,6 +176,7 @@
     public void onAttach(Activity activity) {
         super.onAttach(activity);
         mContext = activity;
+        mDefaultCountryIso = ContactsUtils.getCurrentCountryIso(mContext);
     }
 
     @Override
@@ -327,7 +330,10 @@
                 } else if (Phone.CONTENT_ITEM_TYPE.equals(mimeType) && hasData) {
                     // Build phone entries
                     mNumPhoneNumbers++;
-
+                    String phoneNumberE164 =
+                            entryValues.getAsString(PhoneLookup.NORMALIZED_NUMBER);
+                    entry.data = PhoneNumberUtils.formatNumber(
+                            entry.data, phoneNumberE164, mDefaultCountryIso);
                     final Intent phoneIntent = mHasPhone ? new Intent(Intent.ACTION_CALL_PRIVILEGED,
                             Uri.fromParts(Constants.SCHEME_TEL, entry.data, null)) : null;
                     final Intent smsIntent = mHasSms ? new Intent(Intent.ACTION_SENDTO,