Merge "Import revised translations."
diff --git a/res/layout/contact_tile_frequent_phone.xml b/res/layout/contact_tile_frequent_phone.xml
index 1cee5c6..aa2d9a8 100644
--- a/res/layout/contact_tile_frequent_phone.xml
+++ b/res/layout/contact_tile_frequent_phone.xml
@@ -69,6 +69,7 @@
                 android:layout_height="wrap_content"
                 android:layout_weight="?attr/list_item_data_width_weight"
                 android:textSize="14sp"
+                android:ellipsize="marquee"
                 android:textColor="@color/dialtacts_secondary_text_color"
                 android:layout_marginLeft="8dip"
                 android:singleLine="true"
@@ -80,7 +81,7 @@
                 android:layout_height="wrap_content"
                 android:layout_weight="?attr/list_item_label_width_weight"
                 android:textSize="12sp"
-                android:ellipsize="end"
+                android:ellipsize="marquee"
                 android:singleLine="true"
                 android:textAllCaps="true"
                 android:textColor="@color/dialtacts_secondary_text_color"
diff --git a/src/com/android/contacts/CallDetailActivity.java b/src/com/android/contacts/CallDetailActivity.java
index 012acc7..541b7bf 100644
--- a/src/com/android/contacts/CallDetailActivity.java
+++ b/src/com/android/contacts/CallDetailActivity.java
@@ -121,7 +121,11 @@
     private TextView mStatusMessageAction;
 
     /** Whether we should show "edit number before call" in the options menu. */
-    private boolean mHasEditNumberBeforeCall;
+    private boolean mHasEditNumberBeforeCallOption;
+    /** Whether we should show "trash" in the options menu. */
+    private boolean mHasTrashOption;
+    /** Whether we should show "remove from call log" in the options menu. */
+    private boolean mHasRemoveFromCallLogOption;
 
     private ProximitySensorManager mProximitySensorManager;
     private final ProximitySensorListener mProximitySensorListener = new ProximitySensorListener();
@@ -218,7 +222,7 @@
         mResources = getResources();
 
         mCallTypeHelper = new CallTypeHelper(getResources());
-        mPhoneNumberHelper = new PhoneNumberHelper(mResources, getVoicemailNumber());
+        mPhoneNumberHelper = new PhoneNumberHelper(mResources);
         mPhoneCallDetailsHelper = new PhoneCallDetailsHelper(mResources, mCallTypeHelper,
                 mPhoneNumberHelper);
         mVoicemailStatusHelper = new VoicemailStatusHelperImpl();
@@ -491,7 +495,10 @@
                     disableCallButton();
                 }
 
-                mHasEditNumberBeforeCall = canPlaceCallsTo && !isSipNumber && !isVoicemailNumber;
+                mHasEditNumberBeforeCallOption =
+                        canPlaceCallsTo && !isSipNumber && !isVoicemailNumber;
+                mHasTrashOption = hasVoicemail();
+                mHasRemoveFromCallLogOption = !hasVoicemail();
                 invalidateOptionsMenu();
 
                 ListView historyList = (ListView) findViewById(R.id.history);
@@ -564,6 +571,7 @@
             // If this is not a regular number, there is no point in looking it up in the contacts.
             ContactInfo info =
                     mPhoneNumberHelper.canPlaceCallsTo(number)
+                    && !mPhoneNumberHelper.isVoicemailNumber(number)
                             ? mContactInfoHelper.lookupNumber(number, countryIso)
                             : null;
             if (info == null) {
@@ -596,12 +604,6 @@
         mContactPhotoManager.loadPhoto(mContactBackgroundView, photoUri, true, true);
     }
 
-    private String getVoicemailNumber() {
-        TelephonyManager telephonyManager =
-                (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
-        return telephonyManager.getVoiceMailNumber();
-    }
-
     static final class ViewEntry {
         public final String text;
         public final Intent primaryIntent;
@@ -723,9 +725,9 @@
     public boolean onPrepareOptionsMenu(Menu menu) {
         // This action deletes all elements in the group from the call log.
         // We don't have this action for voicemails, because you can just use the trash button.
-        menu.findItem(R.id.menu_remove_from_call_log).setVisible(!hasVoicemail());
-        menu.findItem(R.id.menu_edit_number_before_call).setVisible(mHasEditNumberBeforeCall);
-        menu.findItem(R.id.menu_trash).setVisible(hasVoicemail());
+        menu.findItem(R.id.menu_remove_from_call_log).setVisible(mHasRemoveFromCallLogOption);
+        menu.findItem(R.id.menu_edit_number_before_call).setVisible(mHasEditNumberBeforeCallOption);
+        menu.findItem(R.id.menu_trash).setVisible(mHasTrashOption);
         return super.onPrepareOptionsMenu(menu);
     }
 
diff --git a/src/com/android/contacts/calllog/CallLogAdapter.java b/src/com/android/contacts/calllog/CallLogAdapter.java
index 7e6770b..ea3e03e 100644
--- a/src/com/android/contacts/calllog/CallLogAdapter.java
+++ b/src/com/android/contacts/calllog/CallLogAdapter.java
@@ -194,7 +194,7 @@
     };
 
     public CallLogAdapter(Context context, CallFetcher callFetcher,
-            ContactInfoHelper contactInfoHelper, String voicemailNumber) {
+            ContactInfoHelper contactInfoHelper) {
         super(context);
 
         mContext = context;
@@ -209,7 +209,7 @@
         CallTypeHelper callTypeHelper = new CallTypeHelper(resources);
 
         mContactPhotoManager = ContactPhotoManager.getInstance(mContext);
-        mPhoneNumberHelper = new PhoneNumberHelper(resources, voicemailNumber);
+        mPhoneNumberHelper = new PhoneNumberHelper(resources);
         PhoneCallDetailsHelper phoneCallDetailsHelper = new PhoneCallDetailsHelper(
                 resources, callTypeHelper, mPhoneNumberHelper);
         mCallLogViewsHelper =
diff --git a/src/com/android/contacts/calllog/CallLogFragment.java b/src/com/android/contacts/calllog/CallLogFragment.java
index 79f3499..7c889c8 100644
--- a/src/com/android/contacts/calllog/CallLogFragment.java
+++ b/src/com/android/contacts/calllog/CallLogFragment.java
@@ -39,7 +39,6 @@
 import android.os.ServiceManager;
 import android.provider.CallLog.Calls;
 import android.telephony.PhoneNumberUtils;
-import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.LayoutInflater;
@@ -62,7 +61,6 @@
 
     private CallLogAdapter mAdapter;
     private CallLogQueryHandler mCallLogQueryHandler;
-    private String mVoiceMailNumber;
     private boolean mScrollToTop;
 
     private boolean mShowOptionsMenu;
@@ -81,8 +79,6 @@
     public void onCreate(Bundle state) {
         super.onCreate(state);
 
-        mVoiceMailNumber = ((TelephonyManager) getActivity().getSystemService(
-                Context.TELEPHONY_SERVICE)).getVoiceMailNumber();
         mCallLogQueryHandler = new CallLogQueryHandler(getActivity().getContentResolver(), this);
         mKeyguardManager =
                 (KeyguardManager) getActivity().getSystemService(Context.KEYGUARD_SERVICE);
@@ -151,7 +147,7 @@
         super.onViewCreated(view, savedInstanceState);
         String currentCountryIso = ContactsUtils.getCurrentCountryIso(getActivity());
         mAdapter = new CallLogAdapter(getActivity(), this,
-                new ContactInfoHelper(getActivity(), currentCountryIso), mVoiceMailNumber);
+                new ContactInfoHelper(getActivity(), currentCountryIso));
         setListAdapter(mAdapter);
         getListView().setItemsCanFocus(true);
     }
@@ -326,11 +322,6 @@
         return mAdapter;
     }
 
-    @NeededForTesting
-    public String getVoiceMailNumber() {
-        return mVoiceMailNumber;
-    }
-
     @Override
     public void onVisibilityChanged(boolean visible) {
         if (mShowOptionsMenu != visible) {
diff --git a/src/com/android/contacts/calllog/ContactInfoHelper.java b/src/com/android/contacts/calllog/ContactInfoHelper.java
index c837c9a..f1987ce 100644
--- a/src/com/android/contacts/calllog/ContactInfoHelper.java
+++ b/src/com/android/contacts/calllog/ContactInfoHelper.java
@@ -67,7 +67,14 @@
             }
             info = sipInfo;
         } else {
-            info = queryContactInfoForPhoneNumber(number, countryIso);
+            // Look for a contact that has the given phone number.
+            ContactInfo phoneInfo = queryContactInfoForPhoneNumber(number, countryIso);
+
+            if (phoneInfo == null || phoneInfo == ContactInfo.EMPTY) {
+                // Check whether the phone number has been saved as an "Internet call" number.
+                phoneInfo = queryContactInfoForSipAddress(number);
+            }
+            info = phoneInfo;
         }
 
         final ContactInfo updatedInfo;
diff --git a/src/com/android/contacts/calllog/DefaultVoicemailNotifier.java b/src/com/android/contacts/calllog/DefaultVoicemailNotifier.java
index c4fb36c..c5e8f91 100644
--- a/src/com/android/contacts/calllog/DefaultVoicemailNotifier.java
+++ b/src/com/android/contacts/calllog/DefaultVoicemailNotifier.java
@@ -33,7 +33,6 @@
 import android.net.Uri;
 import android.provider.CallLog.Calls;
 import android.provider.ContactsContract.PhoneLookup;
-import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -319,8 +318,6 @@
      * called from the main thread.
      */
     public static PhoneNumberHelper createPhoneNumberHelper(Context context) {
-        TelephonyManager telephonyManager =
-            (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
-        return new PhoneNumberHelper(context.getResources(), telephonyManager.getVoiceMailNumber());
+        return new PhoneNumberHelper(context.getResources());
     }
 }
diff --git a/src/com/android/contacts/calllog/PhoneNumberHelper.java b/src/com/android/contacts/calllog/PhoneNumberHelper.java
index 4d96f4f..20031b2 100644
--- a/src/com/android/contacts/calllog/PhoneNumberHelper.java
+++ b/src/com/android/contacts/calllog/PhoneNumberHelper.java
@@ -29,11 +29,9 @@
  */
 public class PhoneNumberHelper {
     private final Resources mResources;
-    private final String mVoicemailNumber;
 
-    public PhoneNumberHelper(Resources resources, String voicemailNumber) {
+    public PhoneNumberHelper(Resources resources) {
         mResources = resources;
-        mVoicemailNumber = voicemailNumber;
     }
 
     /** Returns true if it is possible to place a call to the given number. */
@@ -68,7 +66,7 @@
         if (number.equals(CallerInfo.PAYPHONE_NUMBER)) {
             return mResources.getString(R.string.payphone);
         }
-        if (PhoneNumberUtils.extractNetworkPortion(number.toString()).equals(mVoicemailNumber)) {
+        if (isVoicemailNumber(number)) {
             return mResources.getString(R.string.voicemail);
         }
         if (TextUtils.isEmpty(formattedNumber)) {
@@ -91,7 +89,7 @@
 
     /** Returns true if the given number is the number of the configured voicemail. */
     public boolean isVoicemailNumber(CharSequence number) {
-        return PhoneNumberUtils.extractNetworkPortion(number.toString()).equals(mVoicemailNumber);
+        return PhoneNumberUtils.isVoiceMailNumber(number.toString());
     }
 
     /** Returns true if the given number is a SIP address. */
diff --git a/src/com/android/contacts/list/ContactListItemView.java b/src/com/android/contacts/list/ContactListItemView.java
index 18c4d29..5d549b8 100644
--- a/src/com/android/contacts/list/ContactListItemView.java
+++ b/src/com/android/contacts/list/ContactListItemView.java
@@ -35,6 +35,8 @@
 import android.os.Bundle;
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.Contacts;
+import android.text.Spannable;
+import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
 import android.text.TextUtils.TruncateAt;
 import android.util.AttributeSet;
@@ -176,7 +178,7 @@
 
     private int mNameTextViewHeight;
     private int mPhoneticNameTextViewHeight;
-    private int mLabelTextViewHeight;
+    private int mLabelViewHeight;
     private int mDataViewHeight;
     private int mSnippetTextViewHeight;
     private int mStatusTextViewHeight;
@@ -326,7 +328,7 @@
 
         mNameTextViewHeight = 0;
         mPhoneticNameTextViewHeight = 0;
-        mLabelTextViewHeight = 0;
+        mLabelViewHeight = 0;
         mDataViewHeight = 0;
         mLabelAndDataViewMaxHeight = 0;
         mSnippetTextViewHeight = 0;
@@ -394,9 +396,9 @@
         if (isVisible(mLabelView)) {
             mLabelView.measure(MeasureSpec.makeMeasureSpec(labelWidth, MeasureSpec.AT_MOST),
                     MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
-            mLabelTextViewHeight = mLabelView.getMeasuredHeight();
+            mLabelViewHeight = mLabelView.getMeasuredHeight();
         }
-        mLabelAndDataViewMaxHeight = Math.max(mLabelTextViewHeight, mDataViewHeight);
+        mLabelAndDataViewMaxHeight = Math.max(mLabelViewHeight, mDataViewHeight);
 
         if (isVisible(mSnippetView)) {
             mSnippetView.measure(
@@ -600,14 +602,15 @@
             if (mPhotoPosition == PhotoPosition.LEFT) {
                 // When photo is on left, label is placed on the right edge of the list item.
                 mLabelView.layout(rightBound - mLabelView.getMeasuredWidth(),
-                        textTopBound + mLabelAndDataViewMaxHeight - mLabelTextViewHeight,
+                        textTopBound + mLabelAndDataViewMaxHeight - mLabelViewHeight,
                         rightBound,
                         textTopBound + mLabelAndDataViewMaxHeight);
+                rightBound -= mLabelView.getMeasuredWidth();
             } else {
                 // When photo is on right, label is placed on the left of data view.
                 dataLeftBound = leftBound + mLabelView.getMeasuredWidth();
                 mLabelView.layout(leftBound,
-                        textTopBound + mLabelAndDataViewMaxHeight - mLabelTextViewHeight,
+                        textTopBound + mLabelAndDataViewMaxHeight - mLabelViewHeight,
                         dataLeftBound,
                         textTopBound + mLabelAndDataViewMaxHeight);
                 dataLeftBound += mGapBetweenLabelAndData;
@@ -783,7 +786,7 @@
                 mHeaderDivider.setBackgroundColor(mHeaderUnderlineColor);
                 addView(mHeaderDivider);
             }
-            mHeaderTextView.setText(title);
+            mHeaderTextView.setText(getMarqueeText(title));
             mHeaderTextView.setVisibility(View.VISIBLE);
             mHeaderDivider.setVisibility(View.VISIBLE);
             mHeaderTextView.setAllCaps(true);
@@ -929,7 +932,7 @@
             }
         } else {
             getPhoneticNameTextView();
-            mPhoneticNameTextView.setText(text, 0, size);
+            mPhoneticNameTextView.setText(getMarqueeText(text, size));
             mPhoneticNameTextView.setVisibility(VISIBLE);
         }
     }
@@ -960,7 +963,7 @@
             }
         } else {
             getLabelView();
-            mLabelView.setText(text);
+            mLabelView.setText(getMarqueeText(text));
             mLabelView.setVisibility(VISIBLE);
         }
     }
@@ -975,7 +978,7 @@
             }
         } else {
             getLabelView();
-            mLabelView.setText(text, 0, size);
+            mLabelView.setText(getMarqueeText(text, size));
             mLabelView.setVisibility(VISIBLE);
         }
     }
@@ -992,6 +995,7 @@
             if (mPhotoPosition == PhotoPosition.LEFT) {
                 mLabelView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mCountViewTextSize);
                 mLabelView.setAllCaps(true);
+                mLabelView.setGravity(Gravity.RIGHT);
             } else {
                 mLabelView.setTypeface(mLabelView.getTypeface(), Typeface.BOLD);
             }
@@ -1012,11 +1016,28 @@
             return;
         } else {
             getDataView();
-            mDataView.setText(text, 0, size);
+            mDataView.setText(getMarqueeText(text, size));
             mDataView.setVisibility(VISIBLE);
         }
     }
 
+    private CharSequence getMarqueeText(char[] text, int size) {
+        return getMarqueeText(new String(text, 0, size));
+    }
+
+    private CharSequence getMarqueeText(CharSequence text) {
+        if (getTextEllipsis() == TruncateAt.MARQUEE) {
+            // To show MARQUEE correctly (with END effect during non-active state), we need
+            // to build Spanned with MARQUEE in addition to TextView's ellipsize setting.
+            final SpannableStringBuilder builder = new SpannableStringBuilder(text);
+            builder.setSpan(TruncateAt.MARQUEE, 0, builder.length(),
+                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            return builder;
+        } else {
+            return text;
+        }
+    }
+
     /**
      * Returns the text view for the data text, creating it if necessary.
      */
@@ -1103,7 +1124,7 @@
             }
         } else {
             getCountView();
-            mCountView.setText(text);
+            mCountView.setText(getMarqueeText(text));
             mCountView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mCountViewTextSize);
             mCountView.setGravity(Gravity.CENTER_VERTICAL);
             mCountView.setTextColor(mContactsCountTextColor);
@@ -1121,7 +1142,7 @@
             }
         } else {
             getStatusView();
-            mStatusView.setText(text);
+            mStatusView.setText(getMarqueeText(text));
             mStatusView.setVisibility(VISIBLE);
         }
     }
@@ -1146,9 +1167,7 @@
     }
 
     private TruncateAt getTextEllipsis() {
-        // Note: If we want to choose MARQUEE here, we may need to manually trigger TextView's
-        // startStopMarquee(), which is unfortunately *private*. See also issue 5465510.
-        return TruncateAt.MIDDLE;
+        return TruncateAt.MARQUEE;
     }
 
     public void showDisplayName(Cursor cursor, int nameColumnIndex, int alternativeNameColumnIndex,
@@ -1158,8 +1177,10 @@
         cursor.copyStringToBuffer(alternativeNameColumnIndex,
                 mDisplayNameFormatter.getAlternateNameBuffer());
 
-        mDisplayNameFormatter.setDisplayName(
-                getNameTextView(), displayOrder, highlightingEnabled, mHighlightedPrefix);
+        CharSequence displayName = mDisplayNameFormatter.getDisplayName(
+                displayOrder, highlightingEnabled, mHighlightedPrefix);
+        getNameTextView().setText(getMarqueeText(displayName));
+
         // Since the quick contact content description is derived from the display name and there is
         // no guarantee that when the quick contact is initialized the display name is already set,
         // do it here too.
diff --git a/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java b/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java
index 2dfd95a..c1c3e08 100644
--- a/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java
+++ b/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java
@@ -18,6 +18,7 @@
 
 import com.android.contacts.calllog.CallTypeHelper;
 import com.android.contacts.calllog.PhoneNumberHelper;
+import com.android.contacts.calllog.TestPhoneNumberHelper;
 import com.android.contacts.util.LocaleTestUtils;
 import com.android.internal.telephony.CallerInfo;
 
@@ -67,7 +68,7 @@
         Context context = getContext();
         Resources resources = context.getResources();
         CallTypeHelper callTypeHelper = new CallTypeHelper(resources);
-        mPhoneNumberHelper = new PhoneNumberHelper(resources, TEST_VOICEMAIL_NUMBER);
+        mPhoneNumberHelper = new TestPhoneNumberHelper(resources, TEST_VOICEMAIL_NUMBER);
         mHelper = new PhoneCallDetailsHelper(resources, callTypeHelper, mPhoneNumberHelper);
         mHelper.setCurrentTimeForTest(
                 new GregorianCalendar(2011, 5, 4, 13, 0, 0).getTimeInMillis());
diff --git a/tests/src/com/android/contacts/activities/CallLogActivityTests.java b/tests/src/com/android/contacts/activities/CallLogActivityTests.java
index ac314b6..b670f05 100644
--- a/tests/src/com/android/contacts/activities/CallLogActivityTests.java
+++ b/tests/src/com/android/contacts/activities/CallLogActivityTests.java
@@ -39,6 +39,7 @@
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.VoicemailContract;
 import android.telephony.PhoneNumberUtils;
+import android.telephony.TelephonyManager;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.MediumTest;
@@ -112,7 +113,7 @@
     public void setUp() {
         mActivity = getActivity();
         mFragment = mActivity.getFragment();
-        mVoicemail = mFragment.getVoiceMailNumber();
+        mVoicemail = TelephonyManager.getDefault().getVoiceMailNumber();
         mAdapter = mFragment.getAdapter();
         // Do not process requests for details during tests. This would start a background thread,
         // which makes the tests flaky.
diff --git a/tests/src/com/android/contacts/calllog/CallLogAdapterTest.java b/tests/src/com/android/contacts/calllog/CallLogAdapterTest.java
index 909002a..600a589 100644
--- a/tests/src/com/android/contacts/calllog/CallLogAdapterTest.java
+++ b/tests/src/com/android/contacts/calllog/CallLogAdapterTest.java
@@ -36,7 +36,6 @@
     private static final String TEST_NUMBER_LABEL = "label";
     private static final int TEST_NUMBER_TYPE = 1;
     private static final String TEST_COUNTRY_ISO = "US";
-    private static final String TEST_VOICEMAIL_NUMBER = "111";
 
     /** The object under test. */
     private TestCallLogAdapter mAdapter;
@@ -64,8 +63,7 @@
                     }
                 };
 
-        mAdapter = new TestCallLogAdapter(getContext(), fakeCallFetcher, fakeContactInfoHelper,
-                TEST_VOICEMAIL_NUMBER);
+        mAdapter = new TestCallLogAdapter(getContext(), fakeCallFetcher, fakeContactInfoHelper);
         // The cursor used in the tests to store the entries to display.
         mCursor = new MatrixCursor(CallLogQuery.EXTENDED_PROJECTION);
         mCursor.moveToFirst();
@@ -213,8 +211,8 @@
         public final List<Request> requests = Lists.newArrayList();
 
         public TestCallLogAdapter(Context context, CallFetcher callFetcher,
-                ContactInfoHelper contactInfoHelper, String voicemailNumber) {
-            super(context, callFetcher, contactInfoHelper, voicemailNumber);
+                ContactInfoHelper contactInfoHelper) {
+            super(context, callFetcher, contactInfoHelper);
         }
 
         @Override
diff --git a/tests/src/com/android/contacts/calllog/CallLogListItemHelperTest.java b/tests/src/com/android/contacts/calllog/CallLogListItemHelperTest.java
index ce3c14f..0488044 100644
--- a/tests/src/com/android/contacts/calllog/CallLogListItemHelperTest.java
+++ b/tests/src/com/android/contacts/calllog/CallLogListItemHelperTest.java
@@ -58,7 +58,7 @@
         Context context = getContext();
         Resources resources = context.getResources();
         CallTypeHelper callTypeHelper = new CallTypeHelper(resources);
-        mPhoneNumberHelper = new PhoneNumberHelper(resources, TEST_VOICEMAIL_NUMBER);
+        mPhoneNumberHelper = new TestPhoneNumberHelper(resources, TEST_VOICEMAIL_NUMBER);
         PhoneCallDetailsHelper phoneCallDetailsHelper = new PhoneCallDetailsHelper(
                 resources, callTypeHelper, mPhoneNumberHelper);
         mHelper = new CallLogListItemHelper(phoneCallDetailsHelper, mPhoneNumberHelper, resources);
diff --git a/tests/src/com/android/contacts/calllog/TestPhoneNumberHelper.java b/tests/src/com/android/contacts/calllog/TestPhoneNumberHelper.java
new file mode 100644
index 0000000..2bbd978
--- /dev/null
+++ b/tests/src/com/android/contacts/calllog/TestPhoneNumberHelper.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2011 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.calllog;
+
+import android.content.res.Resources;
+
+/**
+ * Modified version of {@link PhoneNumberHelper} to be used in tests that allows injecting the
+ * voicemail number.
+ */
+public final class TestPhoneNumberHelper extends PhoneNumberHelper {
+    private CharSequence mVoicemailNumber;
+
+    public TestPhoneNumberHelper(Resources resources, CharSequence voicemailNumber) {
+        super(resources);
+        mVoicemailNumber = voicemailNumber;
+    }
+
+    @Override
+    public boolean isVoicemailNumber(CharSequence number) {
+        return mVoicemailNumber.equals(number);
+    }
+}
\ No newline at end of file