Handles special numbers in call details page.

Some numbers (unknown, private, payphones, and voicemails) should be
shown using text instead of the row number strings.

Change-Id: I297d44bd762548f08c975adc1ba56fc4a9edd146
diff --git a/src/com/android/contacts/CallDetailActivity.java b/src/com/android/contacts/CallDetailActivity.java
index 43b3bee..43376ca 100644
--- a/src/com/android/contacts/CallDetailActivity.java
+++ b/src/com/android/contacts/CallDetailActivity.java
@@ -114,8 +114,8 @@
         mInflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
         mResources = getResources();
 
-        mPhoneCallDetailsViews = new PhoneCallDetailsViews(getWindow().getDecorView());
-        mPhoneCallDetailsHelper = new PhoneCallDetailsHelper(getResources());
+        mPhoneCallDetailsViews = PhoneCallDetailsViews.fromView(getWindow().getDecorView());
+        mPhoneCallDetailsHelper = new PhoneCallDetailsHelper(getResources(), getVoicemailNumber());
         mCallActionView = findViewById(R.id.call);
         mContactPhotoView = (ImageView) findViewById(R.id.contact_photo);
         mContactBackgroundView = (ImageView) findViewById(R.id.contact_background);
@@ -307,6 +307,12 @@
         return getString(R.string.callDetailsDurationFormat, minutes, seconds);
     }
 
+    private String getVoicemailNumber() {
+        TelephonyManager telephonyManager =
+                (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
+        return telephonyManager.getVoiceMailNumber();
+    }
+
     static final class ViewEntry {
         public int icon = -1;
         public String text = null;
diff --git a/src/com/android/contacts/PhoneCallDetailsHelper.java b/src/com/android/contacts/PhoneCallDetailsHelper.java
index 6542f7d..fc96a89 100644
--- a/src/com/android/contacts/PhoneCallDetailsHelper.java
+++ b/src/com/android/contacts/PhoneCallDetailsHelper.java
@@ -17,6 +17,7 @@
 package com.android.contacts;
 
 import com.android.contacts.format.FormatUtils;
+import com.android.internal.telephony.CallerInfo;
 
 import android.content.res.Resources;
 import android.graphics.Typeface;
@@ -33,6 +34,7 @@
  */
 public class PhoneCallDetailsHelper {
     private final Resources mResources;
+    private final String mVoicemailNumber;
     private final String mTypeIncomingText;
     private final String mTypeOutgoingText;
     private final String mTypeMissedText;
@@ -44,8 +46,9 @@
      *
      * @param resources used to look up strings
      */
-    public PhoneCallDetailsHelper(Resources resources) {
+    public PhoneCallDetailsHelper(Resources resources, String voicemailNumber) {
         mResources = resources;
+        mVoicemailNumber = voicemailNumber;
         mTypeIncomingText = mResources.getString(R.string.type_incoming);
         mTypeOutgoingText = mResources.getString(R.string.type_outgoing);
         mTypeMissedText = mResources.getString(R.string.type_missed);
@@ -98,11 +101,11 @@
         CharSequence nameText;
         CharSequence numberText;
         if (TextUtils.isEmpty(name)) {
-            nameText = number;
+            nameText = getDisplayNumber(number);
             numberText = "";
         } else {
             nameText = name;
-            numberText = number;
+            numberText = getDisplayNumber(number);
             if (callType != 0 && numberFormattedLabel != null) {
                 numberText = FormatUtils.applyStyleToSpan(Typeface.BOLD,
                         numberFormattedLabel + " " + number, 0,
@@ -124,4 +127,23 @@
             views.mNumberView.setVisibility(View.GONE);
         }
     }
+
+    private CharSequence getDisplayNumber(CharSequence number) {
+        if (TextUtils.isEmpty(number)) {
+            return "";
+        }
+        if (number.equals(CallerInfo.UNKNOWN_NUMBER)) {
+            return mResources.getString(R.string.unknown);
+        }
+        if (number.equals(CallerInfo.PRIVATE_NUMBER)) {
+            return mResources.getString(R.string.private_num);
+        }
+        if (number.equals(CallerInfo.PAYPHONE_NUMBER)) {
+            return mResources.getString(R.string.payphone);
+        }
+        if (PhoneNumberUtils.extractNetworkPortion(number.toString()).equals(mVoicemailNumber)) {
+            return mResources.getString(R.string.voicemail);
+        }
+        return number;
+    }
 }
diff --git a/src/com/android/contacts/PhoneCallDetailsViews.java b/src/com/android/contacts/PhoneCallDetailsViews.java
index f9f8572..c2819c3 100644
--- a/src/com/android/contacts/PhoneCallDetailsViews.java
+++ b/src/com/android/contacts/PhoneCallDetailsViews.java
@@ -27,14 +27,27 @@
     public final TextView mCallTypeAndDateView;
     public final TextView mNumberView;
 
+    private PhoneCallDetailsViews(TextView nameView, TextView callTypeAndDateView,
+            TextView numberView) {
+        mNameView = nameView;
+        mCallTypeAndDateView = callTypeAndDateView;
+        mNumberView = numberView;
+    }
+
     /**
-     * Creates a new instance and caches its views.
-     *
-     * @param view the view which contains the elements to fill
+     * Create a new instance by extracting the elements from the given view.
+     * <p>
+     * The view should contain three text views with identifiers {@code R.id.name},
+     * {@code R.id.call_type}, and {@code R.id.number}.
      */
-    public PhoneCallDetailsViews(View view) {
-        mNameView = (TextView) view.findViewById(R.id.name);
-        mCallTypeAndDateView = (TextView) view.findViewById(R.id.call_type);
-        mNumberView = (TextView) view.findViewById(R.id.number);
+    public static PhoneCallDetailsViews fromView(View view) {
+        return new PhoneCallDetailsViews((TextView) view.findViewById(R.id.name),
+                (TextView) view.findViewById(R.id.call_type),
+                (TextView) view.findViewById(R.id.number));
+    }
+
+    public static PhoneCallDetailsViews createForTest(TextView nameView,
+            TextView callTypeAndDateView, TextView numberView) {
+        return new PhoneCallDetailsViews(nameView, callTypeAndDateView, numberView);
     }
 }
diff --git a/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java b/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java
new file mode 100644
index 0000000..ab00382
--- /dev/null
+++ b/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2010 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.contacts;
+
+import com.android.internal.telephony.CallerInfo;
+
+import android.content.Context;
+import android.provider.CallLog.Calls;
+import android.test.AndroidTestCase;
+import android.widget.TextView;
+
+/**
+ * Unit tests for {@link PhoneCallDetailsHelper}.
+ */
+public class PhoneCallDetailsHelperTest extends AndroidTestCase {
+    /** The number to be used to access the voicemail. */
+    private static final String TEST_VOICEMAIL_NUMBER = "125";
+    /** The date of the call log entry. */
+    private static final long TEST_DATE = 1300000000;
+
+    /** The object under test. */
+    private PhoneCallDetailsHelper mHelper;
+    /** The views to fill. */
+    private PhoneCallDetailsViews mViews;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        Context context = getContext();
+        mHelper = new PhoneCallDetailsHelper(context.getResources(), TEST_VOICEMAIL_NUMBER);
+        mViews = PhoneCallDetailsViews.createForTest(new TextView(context), new TextView(context),
+                new TextView(context));
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mViews = null;
+        mHelper = null;
+        super.tearDown();
+    }
+
+    public void testSetPhoneCallDetails_Unknown() {
+        setPhoneCallDetailsWithNumber(CallerInfo.UNKNOWN_NUMBER);
+        assertNameEqualsResource(R.string.unknown);
+    }
+
+    public void testSetPhoneCallDetails_Private() {
+        setPhoneCallDetailsWithNumber(CallerInfo.PRIVATE_NUMBER);
+        assertNameEqualsResource(R.string.private_num);
+    }
+
+    public void testSetPhoneCallDetails_Payphone() {
+        setPhoneCallDetailsWithNumber(CallerInfo.PAYPHONE_NUMBER);
+        assertNameEqualsResource(R.string.payphone);
+    }
+
+    public void testSetPhoneCallDetails_Voicemail() {
+        setPhoneCallDetailsWithNumber(TEST_VOICEMAIL_NUMBER);
+        assertNameEqualsResource(R.string.voicemail);
+    }
+
+    public void testSetPhoneCallDetails_Normal() {
+        setPhoneCallDetailsWithNumber("1-412-555-1212");
+        assertNameEquals("1-412-555-1212");
+    }
+
+    /** Asserts that the name text field contains the value of the given string resource. */
+    private void assertNameEqualsResource(int resId) {
+        assertNameEquals(getContext().getString(resId));
+    }
+
+    /** Asserts that the name text field contains the given string value. */
+    private void assertNameEquals(String text) {
+        assertEquals(text, mViews.mNameView.getText().toString());
+    }
+
+    /** Sets the phone call details with default values and the given number. */
+    private void setPhoneCallDetailsWithNumber(String number) {
+        mHelper.setPhoneCallDetails(mViews, TEST_DATE, Calls.INCOMING_TYPE, "", number, 0, "");
+    }
+}