Merge "CallDetailActivity respect display name order" into ub-contactsdialer-a-dev
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 086145e..dd325bc 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -363,13 +363,6 @@
     -->
     <string name="description_contact_details">Contact details for <xliff:g id="nameOrNumber">%1$s</xliff:g></string>
 
-    <!-- String indicating a call log entry has an associated voicemail.
-
-    Note: AccessibilityServices use this attribute to announce what the view represents.
-          This is especially valuable for views without textual representation like ImageView.
-    -->
-    <string name="description_new_voicemail">New voicemail.</string>
-
     <!-- String indicating the number of calls to/from a caller in the call log.
 
     Note: AccessibilityServices use this attribute to announce what the view represents.
@@ -632,6 +625,16 @@
          [CHAR LIMIT=NONE] -->
     <string name="description_incoming_answered_call">Answered call from <xliff:g id="nameOrNumber" example="John Smith">^1</xliff:g>, <xliff:g id="typeOrLocation" example="Mobile">^2</xliff:g>, <xliff:g id="timeOfCall" example="2 min ago">^3</xliff:g>, <xliff:g id="phoneAccount" example="on SIM 1">^4</xliff:g>.</string>
 
+    <!-- String describing an "unread" voicemail entry in the voicemails tab.
+         Note: AccessibilityServices use this attribute to announce what the view represents.
+         [CHAR LIMIT=NONE] -->
+    <string name="description_unread_voicemail">Unread voicemail from <xliff:g id="nameOrNumber" example="John Smith">^1</xliff:g>, <xliff:g id="typeOrLocation" example="Mobile">^2</xliff:g>, <xliff:g id="timeOfCall" example="2 min ago">^3</xliff:g>, <xliff:g id="phoneAccount" example="on SIM 1">^4</xliff:g>.</string>
+
+    <!-- String describing a "read" voicemail entry in the voicemails tab.
+     Note: AccessibilityServices use this attribute to announce what the view represents.
+     [CHAR LIMIT=NONE] -->
+    <string name="description_read_voicemail">Voicemail from <xliff:g id="nameOrNumber" example="John Smith">^1</xliff:g>, <xliff:g id="typeOrLocation" example="Mobile">^2</xliff:g>, <xliff:g id="timeOfCall" example="2 min ago">^3</xliff:g>, <xliff:g id="phoneAccount" example="on SIM 1">^4</xliff:g>.</string>
+
     <!-- String describing an outgoing call entry in the call log.
          Note: AccessibilityServices uses this attribute to announce what the view represents.
          [CHAR LIMIT=NONE] -->
diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java
index 01af982..b395723 100644
--- a/src/com/android/dialer/calllog/CallLogAdapter.java
+++ b/src/com/android/dialer/calllog/CallLogAdapter.java
@@ -214,7 +214,8 @@
                 // Only expand if actions are not already expanded, because triggering the expand
                 // function on clicks causes the action views to lose the focus indicator.
                 CallLogListItemViewHolder viewHolder = (CallLogListItemViewHolder) host.getTag();
-                if (mCurrentlyExpandedPosition != viewHolder.getAdapterPosition()) {
+                if (mVoicemailPlaybackPresenter == null &&
+                        mCurrentlyExpandedPosition != viewHolder.getAdapterPosition()) {
                     expandViewHolderActions((CallLogListItemViewHolder) host.getTag());
                 }
             }
diff --git a/src/com/android/dialer/calllog/CallLogListItemHelper.java b/src/com/android/dialer/calllog/CallLogListItemHelper.java
index f856bf9..be0e146 100644
--- a/src/com/android/dialer/calllog/CallLogListItemHelper.java
+++ b/src/com/android/dialer/calllog/CallLogListItemHelper.java
@@ -164,7 +164,6 @@
      */
     public CharSequence getCallDescription(PhoneCallDetails details) {
         int lastCallType = getLastCallType(details.callTypes);
-        boolean isVoiceMail = lastCallType == Calls.VOICEMAIL_TYPE;
 
         // Get the name or number of the caller.
         final CharSequence nameOrNumber = getNameOrNumber(details);
@@ -177,11 +176,6 @@
 
         SpannableStringBuilder callDescription = new SpannableStringBuilder();
 
-        // Prepend the voicemail indication.
-        if (isVoiceMail) {
-            callDescription.append(mResources.getString(R.string.description_new_voicemail));
-        }
-
         // Add number of calls if more than one.
         if (details.callTypes.length > 1) {
             callDescription.append(mResources.getString(R.string.description_num_calls,
@@ -193,7 +187,7 @@
             callDescription.append(mResources.getString(R.string.description_video_call));
         }
 
-        int stringID = getCallDescriptionStringID(details.callTypes);
+        int stringID = getCallDescriptionStringID(details.callTypes, details.isRead);
         String accountLabel = mTelecomCallLogCache.getAccountLabel(details.accountHandle);
 
         // Use chosen string resource to build up the message.
@@ -217,15 +211,16 @@
     /**
      * Determine the appropriate string ID to describe a call for accessibility purposes.
      *
-     * @param details Call details.
+     * @param callTypes The type of call corresponding to this entry or multiple if this entry
+     * represents multiple calls grouped together.
+     * @param isRead If the entry is a voicemail, {@code true} if the voicemail is read.
      * @return String resource ID to use.
      */
-    public int getCallDescriptionStringID(int[] callTypes) {
+    public int getCallDescriptionStringID(int[] callTypes, boolean isRead) {
         int lastCallType = getLastCallType(callTypes);
         int stringID;
 
-        if (lastCallType == AppCompatConstants.CALLS_VOICEMAIL_TYPE
-                || lastCallType == AppCompatConstants.CALLS_MISSED_TYPE) {
+        if (lastCallType == AppCompatConstants.CALLS_MISSED_TYPE) {
             //Message: Missed call from <NameOrNumber>, <TypeOrLocation>, <TimeOfCall>,
             //<PhoneAccount>.
             stringID = R.string.description_incoming_missed_call;
@@ -233,6 +228,11 @@
             //Message: Answered call from <NameOrNumber>, <TypeOrLocation>, <TimeOfCall>,
             //<PhoneAccount>.
             stringID = R.string.description_incoming_answered_call;
+        } else if (lastCallType == AppCompatConstants.CALLS_VOICEMAIL_TYPE) {
+            //Message: (Unread) [V/v]oicemail from <NameOrNumber>, <TypeOrLocation>, <TimeOfCall>,
+            //<PhoneAccount>.
+            stringID = isRead ? R.string.description_read_voicemail
+                : R.string.description_unread_voicemail;
         } else {
             //Message: Call to <NameOrNumber>, <TypeOrLocation>, <TimeOfCall>, <PhoneAccount>.
             stringID = R.string.description_outgoing_call;
diff --git a/src/com/android/dialer/calllog/CallLogListItemViewHolder.java b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java
index fd649bc..1bc4410 100644
--- a/src/com/android/dialer/calllog/CallLogListItemViewHolder.java
+++ b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java
@@ -398,6 +398,9 @@
             // Treat as voicemail list item; show play button if not expanded.
             if (!isExpanded) {
                 primaryActionButtonView.setImageResource(R.drawable.ic_play_arrow_24dp);
+                primaryActionButtonView.setContentDescription(TextUtils.expandTemplate(
+                        mContext.getString(R.string.description_voicemail_action),
+                        nameOrNumber));
                 primaryActionButtonView.setVisibility(View.VISIBLE);
             } else {
                 primaryActionButtonView.setVisibility(View.GONE);
diff --git a/src/com/android/dialer/list/BlockedListSearchFragment.java b/src/com/android/dialer/list/BlockedListSearchFragment.java
index 961ce39..8fc6f7a 100644
--- a/src/com/android/dialer/list/BlockedListSearchFragment.java
+++ b/src/com/android/dialer/list/BlockedListSearchFragment.java
@@ -48,7 +48,6 @@
     private FilteredNumberAsyncQueryHandler mFilteredNumberAsyncQueryHandler;
 
     private EditText mSearchView;
-    private String mSearchQuery;
 
     private final TextWatcher mPhoneSearchQueryTextListener = new TextWatcher() {
         @Override
@@ -57,12 +56,7 @@
 
         @Override
         public void onTextChanged(CharSequence s, int start, int before, int count) {
-            final String newText = s.toString();
-            if (newText.equals(mSearchQuery)) {
-                return;
-            }
-            mSearchQuery = newText;
-            setQueryString(mSearchQuery, false);
+            setQueryString(s.toString(), false);
         }
 
         @Override
@@ -86,6 +80,10 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+
+        // Show list of all phone numbers when search query is empty.
+        setShowEmptyListForNullQuery(false);
+
         mFilteredNumberAsyncQueryHandler = new FilteredNumberAsyncQueryHandler(
                 getContext().getContentResolver());
     }
diff --git a/src/com/android/dialer/list/ListsFragment.java b/src/com/android/dialer/list/ListsFragment.java
index c80ab42..934792c 100644
--- a/src/com/android/dialer/list/ListsFragment.java
+++ b/src/com/android/dialer/list/ListsFragment.java
@@ -313,7 +313,7 @@
         if (hasActiveVoicemailProvider != mHasActiveVoicemailProvider) {
             mHasActiveVoicemailProvider = hasActiveVoicemailProvider;
             mViewPagerAdapter.notifyDataSetChanged();
-            mViewPagerTabs.setViewPager(mViewPager);
+            mViewPagerTabs.updateTab(TAB_INDEX_VOICEMAIL);
 
             mPrefs.edit()
                   .putBoolean(PREF_KEY_HAS_ACTIVE_VOICEMAIL_PROVIDER, hasActiveVoicemailProvider)
@@ -344,7 +344,7 @@
         }
 
         mViewPagerTabs.setUnreadCount(count, TAB_INDEX_VOICEMAIL);
-        mViewPagerTabs.setViewPager(mViewPager);
+        mViewPagerTabs.updateTab(TAB_INDEX_VOICEMAIL);
     }
 
     @Override
diff --git a/src/com/android/dialer/list/RegularSearchFragment.java b/src/com/android/dialer/list/RegularSearchFragment.java
index 6b89ef0..ed88d83 100644
--- a/src/com/android/dialer/list/RegularSearchFragment.java
+++ b/src/com/android/dialer/list/RegularSearchFragment.java
@@ -60,11 +60,6 @@
         AnalyticsUtil.sendScreenView(this);
     }
 
-    @Override
-    public void onDetach() {
-        super.onDetach();
-    }
-
     public void configureDirectorySearch() {
         setDirectorySearchEnabled(true);
         setDirectoryResultLimit(SEARCH_DIRECTORY_RESULT_LIMIT);
diff --git a/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java b/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java
index 12f32ce..c9d8264 100644
--- a/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java
+++ b/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java
@@ -129,27 +129,18 @@
      * Test getCallDescriptionID method used to get the accessibility description for calls.
      */
     public void testGetCallDescriptionID_Answered() {
-        int[] callTypes = new int[]{ AppCompatConstants.CALLS_INCOMING_TYPE };
+        int[] callTypes = new int[] {AppCompatConstants.CALLS_INCOMING_TYPE};
         assertEquals(R.string.description_incoming_answered_call,
-                mHelper.getCallDescriptionStringID(callTypes));
+                mHelper.getCallDescriptionStringID(callTypes, true));
     }
 
     /**
      * Test getCallDescriptionID method used to get the accessibility description for calls.
      */
     public void testGetCallDescriptionID_Missed() {
-        int[] callTypes = new int[]{ AppCompatConstants.CALLS_MISSED_TYPE };
+        int[] callTypes = new int[] {AppCompatConstants.CALLS_MISSED_TYPE};
         assertEquals(R.string.description_incoming_missed_call,
-                mHelper.getCallDescriptionStringID(callTypes));
-    }
-
-    /**
-     * Test getCallDescriptionID method used to get the accessibility description for calls.
-     */
-    public void testGetCallDescriptionID_Voicemail() {
-        int[] callTypes = new int[]{ AppCompatConstants.CALLS_VOICEMAIL_TYPE };
-        assertEquals(R.string.description_incoming_missed_call,
-                mHelper.getCallDescriptionStringID(callTypes));
+                mHelper.getCallDescriptionStringID(callTypes, true));
     }
 
     /**
@@ -158,9 +149,9 @@
      * only a single call for this caller.
      */
     public void testGetCallDescriptionID_OutgoingSingle() {
-        int[] callTypes = new int[]{ AppCompatConstants.CALLS_OUTGOING_TYPE };
+        int[] callTypes = new int[] {AppCompatConstants.CALLS_OUTGOING_TYPE};
         assertEquals(R.string.description_outgoing_call,
-                mHelper.getCallDescriptionStringID(callTypes));
+                mHelper.getCallDescriptionStringID(callTypes, true));
     }
 
     /**
@@ -169,60 +160,32 @@
      * many calls for this caller.
      */
     public void testGetCallDescriptionID_OutgoingMultiple() {
-        int[] callTypes = new int[]{
+        int[] callTypes = new int[] {
             AppCompatConstants.CALLS_OUTGOING_TYPE,
             AppCompatConstants.CALLS_OUTGOING_TYPE
         };
         assertEquals(R.string.description_outgoing_call,
-                mHelper.getCallDescriptionStringID(callTypes));
+                mHelper.getCallDescriptionStringID(callTypes, true));
     }
 
     /**
      * Test getCallDescription method used to get the accessibility description for calls.
-     * For outgoing calls, we should NOT have "New Voicemail" in the description.
+     * For read voicemail calls, we should have "Voicemail" in the description.
      */
-    public void testGetCallDescription_NoVoicemailOutgoing() {
-        PhoneCallDetails details = getPhoneCallDetailsWithTypes(
-                AppCompatConstants.CALLS_OUTGOING_TYPE, AppCompatConstants.CALLS_OUTGOING_TYPE);
-        CharSequence description = mHelper.getCallDescription(details);
-        assertFalse(description.toString()
-                .contains(this.mResources.getString(R.string.description_new_voicemail)));
+    public void testGetCallDescriptionID_Voicemail() {
+        int[] callTypes = new int[] {AppCompatConstants.CALLS_VOICEMAIL_TYPE};
+        assertEquals(R.string.description_read_voicemail,
+                mHelper.getCallDescriptionStringID(callTypes, true));
     }
 
     /**
      * Test getCallDescription method used to get the accessibility description for calls.
-     * For regular incoming calls, we should NOT have "New Voicemail" in the description.
+     * For unread voicemail calls, we should have "Unread voicemail" in the description.
      */
-    public void testGetCallDescription_NoVoicemailIncoming() {
-        PhoneCallDetails details = getPhoneCallDetailsWithTypes(
-                AppCompatConstants.CALLS_INCOMING_TYPE, AppCompatConstants.CALLS_OUTGOING_TYPE);
-        CharSequence description = mHelper.getCallDescription(details);
-        assertFalse(description.toString()
-                .contains(this.mResources.getString(R.string.description_new_voicemail)));
-    }
-
-    /**
-     * Test getCallDescription method used to get the accessibility description for calls.
-     * For regular missed calls, we should NOT have "New Voicemail" in the description.
-     */
-    public void testGetCallDescription_NoVoicemailMissed() {
-        PhoneCallDetails details = getPhoneCallDetailsWithTypes(
-                AppCompatConstants.CALLS_MISSED_TYPE, AppCompatConstants.CALLS_OUTGOING_TYPE);
-        CharSequence description = mHelper.getCallDescription(details);
-        assertFalse(description.toString()
-                .contains(this.mResources.getString(R.string.description_new_voicemail)));
-    }
-
-    /**
-     * Test getCallDescription method used to get the accessibility description for calls.
-     * For voicemail calls, we should have "New Voicemail" in the description.
-     */
-    public void testGetCallDescription_Voicemail() {
-        PhoneCallDetails details = getPhoneCallDetailsWithTypes(
-                AppCompatConstants.CALLS_VOICEMAIL_TYPE, AppCompatConstants.CALLS_OUTGOING_TYPE);
-        CharSequence description = mHelper.getCallDescription(details);
-        assertTrue(description.toString()
-                .contains(this.mResources.getString(R.string.description_new_voicemail)));
+    public void testGetCallDescriptionID_UnreadVoicemail() {
+        int[] callTypes = new int[] {AppCompatConstants.CALLS_VOICEMAIL_TYPE};
+        assertEquals(R.string.description_unread_voicemail,
+                mHelper.getCallDescriptionStringID(callTypes, false));
     }
 
     /**
@@ -292,7 +255,7 @@
             int presentation, String formattedNumber, int callType) {
         PhoneCallDetails details = getPhoneCallDetails(
                 number, presentation, formattedNumber);
-        details.callTypes = new int[]{ callType };
+        details.callTypes = new int[] {callType};
         mHelper.setPhoneCallDetails(mViewHolder, details);
     }
 
@@ -322,7 +285,7 @@
     }
 
     private void setDefaultDetails(PhoneCallDetails details) {
-        details.callTypes = new int[]{ Calls.INCOMING_TYPE };
+        details.callTypes = new int[] {Calls.INCOMING_TYPE};
         details.countryIso = TEST_COUNTRY_ISO;
         details.date = TEST_DATE;
         details.duration = TEST_DURATION;