Merge "Change hasVoicemailNumber to getVoicemailNumber"
diff --git a/res/drawable/call_log_background.xml b/res/drawable/call_log_background.xml
deleted file mode 100644
index 1b3dbc9..0000000
--- a/res/drawable/call_log_background.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 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.
--->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="?android:attr/colorControlHighlight" />
\ No newline at end of file
diff --git a/res/layout/call_log_list_item.xml b/res/layout/call_log_list_item.xml
index 9ea3db8..7a826d9 100644
--- a/res/layout/call_log_list_item.xml
+++ b/res/layout/call_log_list_item.xml
@@ -44,15 +44,13 @@
         android:layout_height="wrap_content"
         android:layout_margin="4dp"
         android:baselineAligned="false"
-        android:orientation="vertical"
-        android:gravity="center_vertical"
         card_view:cardCornerRadius="4dp"
         card_view:cardBackgroundColor="@color/background_dialer_call_log_list_item">
 
         <!-- Primary area containing the contact badge and caller information -->
         <LinearLayout
             android:id="@+id/primary_action_view"
-            android:background="@drawable/call_log_background"
+            android:background="?android:attr/selectableItemBackground"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:paddingStart="@dimen/call_log_start_margin"
@@ -142,26 +140,28 @@
             </LinearLayout>
 
             <ImageView
-                android:id="@+id/call_indicator_icon"
+                android:id="@+id/call_icon"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center_vertical"
                 android:layout_marginEnd="@dimen/call_log_icon_margin"
+                android:background="?android:attr/selectableItemBackgroundBorderless"
                 android:src="@drawable/ic_card_phone"
                 android:tint="@color/recent_call_log_item_phone_icon_tint"
                 android:alpha="0.3"
-                android:importantForAccessibility="no"
+                android:contentDescription="@string/description_call_log_call_action"
                 android:visibility="gone" />
 
-            <!-- Viewstub with additional expandable actions for a call log entry -->
-            <ViewStub android:id="@+id/call_log_entry_actions_stub"
-                      android:inflatedId="@+id/call_log_entry_actions"
-                      android:layout="@layout/call_log_list_item_actions"
-                      android:layout_width="match_parent"
-                      android:layout_height="wrap_content"/>
-
         </LinearLayout>
 
+        <!-- Viewstub with additional expandable actions for a call log entry -->
+        <ViewStub android:id="@+id/call_log_entry_actions_stub"
+            android:inflatedId="@+id/call_log_entry_actions"
+            android:layout="@layout/call_log_list_item_actions"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_gravity="bottom" />
+
     </android.support.v7.widget.CardView>
 
 </LinearLayout>
diff --git a/res/layout/call_log_list_item_actions.xml b/res/layout/call_log_list_item_actions.xml
index 1280089..8ef92bf 100644
--- a/res/layout/call_log_list_item_actions.xml
+++ b/res/layout/call_log_list_item_actions.xml
@@ -14,100 +14,53 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License
   -->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-             android:layout_width="match_parent"
-             android:layout_height="wrap_content"
-             android:id="@+id/call_log_action_container">
-    <LinearLayout
-        android:id="@+id/call_log_entry_actions_ll"
-        android:gravity="center_vertical"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/call_log_action_container"
+    android:gravity="center_vertical"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:visibility="visible"
+    android:importantForAccessibility="1">
+
+    <!-- Temporary border spacer. -->
+    <View
         android:layout_width="match_parent"
-        android:layout_height="@dimen/call_log_action_height"
-        android:orientation="horizontal"
-        android:paddingStart="@dimen/call_log_actions_left_padding"
-        android:visibility="visible"
-        android:importantForAccessibility="1"
-        >
-        <TextView
-            android:id="@+id/call_back_action"
-            android:background="?android:attr/selectableItemBackground"
-            android:gravity="center"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:paddingStart="@dimen/call_log_action_horizontal_padding"
-            android:paddingEnd="@dimen/call_log_action_horizontal_padding"
-            android:text="@string/call_log_action_call_back"
-            android:textColor="@color/call_log_action_text"
-            android:textSize="@dimen/call_log_list_item_actions_text_size"
-            android:textStyle="bold"
-            android:nextFocusLeft="@+id/primary_action_view"
-            android:nextFocusRight="@+id/video_call_action"
-            android:focusable="true"
-            android:singleLine="true"/>
-        <TextView
-            android:id="@+id/video_call_action"
-            android:background="?android:attr/selectableItemBackground"
-            android:gravity="center"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:paddingStart="@dimen/call_log_action_horizontal_padding"
-            android:paddingEnd="@dimen/call_log_action_horizontal_padding"
-            android:text="@string/call_log_action_video_call"
-            android:textColor="?attr/call_log_secondary_text_color"
-            android:textSize="@dimen/call_log_list_item_actions_text_size"
-            android:textStyle="bold"
-            android:nextFocusLeft="@+id/call_back_action"
-            android:nextFocusRight="@+id/voicemail_action"
-            android:focusable="true"
-            android:singleLine="true"/>
-        <TextView
-            android:id="@+id/voicemail_action"
-            android:background="?android:attr/selectableItemBackground"
-            android:gravity="center"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:paddingStart="@dimen/call_log_action_horizontal_padding"
-            android:paddingEnd="@dimen/call_log_action_horizontal_padding"
-            android:text="@string/call_log_action_voicemail"
-            android:textColor="@color/call_log_action_text"
-            android:textSize="@dimen/call_log_list_item_actions_text_size"
-            android:textStyle="bold"
-            android:nextFocusLeft="@+id/video_call_action"
-            android:nextFocusRight="@+id/details_action"
-            android:focusable="true"
-            android:singleLine="true"/>
-        <TextView
-            android:id="@+id/details_action"
-            android:background="?android:attr/selectableItemBackground"
-            android:gravity="center"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:paddingStart="@dimen/call_log_action_horizontal_padding"
-            android:paddingEnd="@dimen/call_log_action_horizontal_padding"
-            android:text="@string/call_log_action_details"
-            android:textColor="?attr/call_log_secondary_text_color"
-            android:textSize="@dimen/call_log_list_item_actions_text_size"
-            android:textStyle="bold"
-            android:nextFocusLeft="@+id/voicemail_action"
-            android:nextFocusRight="@+id/report_action"
-            android:focusable="true"
-            android:singleLine="true"/>
-        <TextView
-            android:id="@+id/report_action"
-            android:background="?android:attr/selectableItemBackground"
-            android:gravity="center"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:paddingStart="@dimen/call_log_action_horizontal_padding"
-            android:paddingEnd="@dimen/call_log_action_horizontal_padding"
-            android:text="@string/call_log_action_report"
-            android:textColor="?attr/call_log_secondary_text_color"
-            android:textSize="@dimen/call_log_list_item_actions_text_size"
-            android:textStyle="bold"
-            android:nextFocusLeft="@+id/details_action"
-            android:nextFocusRight="@+id/primary_action_view"
-            android:focusable="true"
-            android:singleLine="true"
-            android:visibility="gone"/>
-    </LinearLayout>
-</FrameLayout>
+        android:layout_height="1dp"
+        android:layout_weight="1"
+        android:background="#eeeeee" />
+
+    <TextView
+        android:id="@+id/video_call_action"
+        style="@style/CallLogActionsStyle"
+        android:background="?android:attr/selectableItemBackground"
+        android:text="@string/call_log_action_video_call"
+        android:nextFocusLeft="@+id/primary_action_view"
+        android:nextFocusRight="@+id/voicemail_action" />
+
+    <TextView
+        android:id="@+id/voicemail_action"
+        style="@style/CallLogActionsStyle"
+        android:background="?android:attr/selectableItemBackground"
+        android:text="@string/call_log_action_voicemail"
+        android:nextFocusLeft="@+id/video_call_action"
+        android:nextFocusRight="@+id/details_action" />
+
+    <TextView
+        android:id="@+id/details_action"
+        style="@style/CallLogActionsStyle"
+        android:background="?android:attr/selectableItemBackground"
+        android:text="@string/call_log_action_details"
+        android:nextFocusLeft="@+id/voicemail_action"
+        android:nextFocusRight="@+id/report_action" />
+
+    <TextView
+        android:id="@+id/report_action"
+        style="@style/CallLogActionsStyle"
+        android:background="?android:attr/selectableItemBackground"
+        android:text="@string/call_log_action_report"
+        android:nextFocusLeft="@+id/details_action"
+        android:nextFocusRight="@+id/primary_action_view"
+        android:visibility="gone" />
+
+</LinearLayout>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 0902cb7..502b21a 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -99,14 +99,14 @@
     <dimen name="search_list_padding_top">16dp</dimen>
     <dimen name="search_box_elevation">3dp</dimen>
 
-    <!-- Padding to the left and right of call log action buttons. -->
-    <dimen name="call_log_action_horizontal_padding">8dp</dimen>
+    <dimen name="call_log_action_height">48dp</dimen>
+    <dimen name="call_log_action_horizontal_padding">24dp</dimen>
     <!-- Left-padding for the call log action buttons - ensures the buttons align with the text
          to the right of the contact badge.  Adjust when any of the following change:
          call_log_action_horizontal_padding
          call_log_list_contact_photo_size  -->
     <dimen name="call_log_actions_left_padding">64dp</dimen>
-    <dimen name="call_log_primary_text_size">16sp</dimen>
+    <dimen name="call_log_primary_text_size">14sp</dimen>
     <dimen name="call_log_secondary_text_size">14sp</dimen>
     <dimen name="call_log_list_item_actions_text_size">12sp</dimen>
     <!-- Height of the call log actions section for each call log entry -->
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4c4921d..4ee5b45 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -539,30 +539,10 @@
          [CHAR LIMIT=21] -->
     <string name="favorites_menu_all_contacts">ALL CONTACTS</string>
 
-    <!-- Button text for the "call back" button displayed underneath an entry in the call log. This
-         is used to describe the action of calling a phone number that the user previously received
-         an incoming call from. Tapping causes a call to be placed to the number represented by the
-         call log entry.
-         [CHAR LIMIT=30] -->
-    <string name="call_log_action_call_back">CALL BACK</string>
-
-    <!-- BUTTON text for the "call" button displayed underneath an entry in the call log. This
-         is used to describe the action of calling a phone number. Tapping causes a call to be
-         placed to the number represented by the call log entry.
-         [CHAR LIMIT=30] -->
-    <string name="call_log_action_call">CALL</string>
-
-    <!-- BUTTON text for the "redial" button displayed underneath an entry in the call log. This
-         is used to describe the action of calling a phone number that the user previously made an
-         outgoing call to. Tapping causes a call to be placed to the number represented by the call
-         log entry.
-         [CHAR LIMIT=30] -->
-    <string name="call_log_action_redial">REDIAL</string>
-
-    <!-- Button text for the "video call" button displayed underneath an entry in the call log.
+    <!-- Button text for the "video call" displayed underneath an entry in the call log.
          Tapping causes a video call to be placed to the caller represented by the call log entry.
-         [CHAR LIMIT=30] -->
-    <string name="call_log_action_video_call">VIDEO CALL</string>
+         [CHAR LIMIT=50] -->
+    <string name="call_log_action_video_call">Video call</string>
 
     <!-- Button text for the "LISTEN" button displayed underneath an entry in the call log.
          Tapping navigates the user to the call details screen where the user can listen to the
@@ -570,11 +550,10 @@
          [CHAR LIMIT=30] -->
     <string name="call_log_action_voicemail">LISTEN</string>
 
-    <!-- Button text for the "DETAILS" button displayed underneath an entry in the call log.
+    <!-- Button text for the button displayed underneath an entry in the call log.
          Tapping navigates the user to the call details screen where the user can view details for
-         the call log entry.
-         [CHAR LIMIT=30] -->
-    <string name="call_log_action_details">DETAILS</string>
+         the call log entry. [CHAR LIMIT=50] -->
+    <string name="call_log_action_details">View details</string>
 
     <!-- String describing an incoming missed call entry in the call log.
          Note: AccessibilityServices uses this attribute to announce what the view represents.
@@ -598,11 +577,15 @@
          [CHAR LIMIT=NONE] -->
     <string name="description_phone_account">on <xliff:g id="phoneAccount" example="SIM 1">^1</xliff:g></string>
 
-    <!-- String describing the "call back" action for an entry in the call log.  The call back
+    <!-- String describing the phone icon on a call log list item. When tapped, it will place a
+         call to the number represented by that call log entry. [CHAR LIMIT=NONE]-->
+    <string name="description_call_log_call_action">Call</string>
+
+    <!-- String describing the "call" action for an entry in the call log.  The call back
          action triggers a return call to the named user.
          Note: AccessibilityServices uses this attribute to announce the purpose of the button.
          [CHAR LIMIT=NONE] -->
-    <string name="description_call_back_action">Call back <xliff:g id="nameOrNumber" example="John Smith">^1</xliff:g></string>
+    <string name="description_call_action">Call <xliff:g id="nameOrNumber" example="John Smith">^1</xliff:g></string>
 
     <!-- String describing the "video call" action for an entry in the call log.  The video call
          action triggers a return video call to the named person/number.
@@ -630,7 +613,7 @@
     <!-- Button text for the "report" button displayed underneath an entry in the call log.
          Tapping causes the call log entry to be reported to Google as a bad id.
          [CHAR LIMIT=30] -->
-    <string name="call_log_action_report">REPORT</string>
+    <string name="call_log_action_report">Report</string>
 
     <!-- String used as a header in the call log above calls which occurred today.
          [CHAR LIMIT=65] -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 8bd5f9d..cfb2480 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -158,6 +158,19 @@
         <item name="android:overScrollMode">always</item>
     </style>
 
+    <style name="CallLogActionsStyle">
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">@dimen/call_log_action_height</item>
+        <item name="android:gravity">start|center_vertical</item>
+        <item name="android:paddingStart">@dimen/call_log_action_horizontal_padding</item>
+        <item name="android:paddingEnd">@dimen/call_log_action_horizontal_padding</item>
+        <item name="android:textColor">?attr/call_log_secondary_text_color</item>
+        <item name="android:textSize">@dimen/call_log_list_item_actions_text_size</item>
+        <item name="android:fontFamily">"sans-serif-medium"</item>
+        <item name="android:focusable">true</item>
+        <item name="android:singleLine">true</item>
+    </style>
+
     <style name="DismissButtonStyle">
         <item name="android:paddingLeft">@dimen/dismiss_button_padding_start</item>
         <item name="android:paddingRight">@dimen/dismiss_button_padding_end</item>
diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java
index 07cd215..cc1a4a6 100644
--- a/src/com/android/dialer/calllog/CallLogAdapter.java
+++ b/src/com/android/dialer/calllog/CallLogAdapter.java
@@ -153,8 +153,7 @@
     private final View.OnClickListener mExpandCollapseListener = new View.OnClickListener() {
         @Override
         public void onClick(View v) {
-            final View callLogItem = (View) v.getParent().getParent();
-            handleRowExpanded(callLogItem, false /* forceExpand */);
+            handleRowExpanded(v, false /* forceExpand */);
         }
     };
 
@@ -266,15 +265,15 @@
         LayoutInflater inflater = LayoutInflater.from(mContext);
         View view = inflater.inflate(R.layout.call_log_list_item, parent, false);
 
-        // Get the views to bind to and cache them.
-        CallLogListItemViews views = CallLogListItemViews.fromView(mContext, view);
-        view.setTag(views);
+        CallLogListItemViewHolder viewHolder = CallLogListItemViewHolder.create(
+                view,
+                mContext,
+                mActionListener,
+                mPhoneNumberUtilsWrapper,
+                mCallLogViewsHelper);
+        viewHolder.primaryActionView.setTag(viewHolder);
 
-        // Set text height to false on the TextViews so they don't have extra padding.
-        views.phoneCallDetailsViews.nameView.setElegantTextHeight(false);
-        views.phoneCallDetailsViews.callLocationAndDate.setElegantTextHeight(false);
-
-        return (CallLogListItemViews) view.getTag();
+        return viewHolder;
     }
 
     /**
@@ -292,7 +291,7 @@
         }
         int count = getGroupSize(position);
 
-        CallLogListItemViews views = (CallLogListItemViews) viewHolder;
+        CallLogListItemViewHolder views = (CallLogListItemViewHolder) viewHolder;
         views.rootView.setAccessibilityDelegate(mAccessibilityDelegate);
 
         // Default case: an item in the call log.
@@ -378,12 +377,7 @@
 
         // Restore expansion state of the row on rebind.  Inflate the actions ViewStub if required,
         // and set its visibility state accordingly.
-        views.expandOrCollapseActions(
-                isExpanded(rowId),
-                mOnReportButtonClickListener,
-                mActionListener,
-                mPhoneNumberUtilsWrapper,
-                mCallLogViewsHelper);
+        views.showActions(isExpanded(rowId), mOnReportButtonClickListener);
 
         if (TextUtils.isEmpty(name)) {
             details = new PhoneCallDetails(number, numberPresentation, formattedNumber, countryIso,
@@ -409,6 +403,8 @@
                 mContactInfoHelper.isBusiness(info.sourceType));
         views.quickContactView.setPrioritizedMimeType(Phone.CONTENT_ITEM_TYPE);
 
+        views.updateCallButton();
+
         // Listen for the first draw
         if (mViewTreeObserver == null) {
             mViewTreeObserver = views.rootView.getViewTreeObserver();
@@ -603,28 +599,13 @@
      *        of its previous state
      */
     private void handleRowExpanded(View view, boolean forceExpand) {
-        final CallLogListItemViews views = (CallLogListItemViews) view.getTag();
+        final CallLogListItemViewHolder views = (CallLogListItemViewHolder) view.getTag();
 
         if (forceExpand && isExpanded(views.rowId)) {
             return;
         }
 
-        // Hide or show the actions view.
         boolean expanded = toggleExpansion(views.rowId);
-        expandItem(views, expanded);
-    }
-
-    /**
-     * @param views The view holder for the item to expand or collapse.
-     * @param expand {@code true} to expand the item, {@code false} otherwise.
-     */
-    public void expandItem(CallLogListItemViews views, boolean expand) {
-        // Trigger loading of the viewstub and visual expand or collapse.
-        views.expandOrCollapseActions(
-                expand,
-                mOnReportButtonClickListener,
-                mActionListener,
-                mPhoneNumberUtilsWrapper,
-                mCallLogViewsHelper);
+        views.showActions(expanded, mOnReportButtonClickListener);
     }
 }
diff --git a/src/com/android/dialer/calllog/CallLogListItemHelper.java b/src/com/android/dialer/calllog/CallLogListItemHelper.java
index 77ad333..0e94ef4 100644
--- a/src/com/android/dialer/calllog/CallLogListItemHelper.java
+++ b/src/com/android/dialer/calllog/CallLogListItemHelper.java
@@ -62,7 +62,7 @@
      * @param details the details of a phone call needed to fill in the data
      */
     public void setPhoneCallDetails(
-            Context context, CallLogListItemViews views, PhoneCallDetails details) {
+            Context context, CallLogListItemViewHolder views, PhoneCallDetails details) {
         mPhoneCallDetailsHelper.setPhoneCallDetails(views.phoneCallDetailsViews, details);
 
         // Set the accessibility text for the contact badge
@@ -81,7 +81,7 @@
      *
      * @param views The views associated with the current call log entry.
      */
-    public void setActionContentDescriptions(CallLogListItemViews views) {
+    public void setActionContentDescriptions(CallLogListItemViewHolder views) {
         if (views.nameOrNumber == null) {
             Log.e(TAG, "setActionContentDescriptions; name or number is null.");
         }
@@ -90,10 +90,6 @@
         // Although we don't expect a null name or number, it is best to protect against it.
         CharSequence nameOrNumber = views.nameOrNumber == null ? "" : views.nameOrNumber;
 
-        views.callBackButtonView.setContentDescription(
-                TextUtils.expandTemplate(
-                        mResources.getString(R.string.description_call_back_action), nameOrNumber));
-
         views.videoCallButtonView.setContentDescription(
                 TextUtils.expandTemplate(
                         mResources.getString(R.string.description_video_call_action),
diff --git a/src/com/android/dialer/calllog/CallLogListItemViews.java b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java
similarity index 67%
rename from src/com/android/dialer/calllog/CallLogListItemViews.java
rename to src/com/android/dialer/calllog/CallLogListItemViewHolder.java
index 4d43436..4b208f1 100644
--- a/src/com/android/dialer/calllog/CallLogListItemViews.java
+++ b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.content.res.Resources;
+import android.content.Intent;
 import android.net.Uri;
 import android.provider.CallLog.Calls;
 import android.support.v7.widget.CardView;
@@ -27,6 +28,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewStub;
+import android.view.ViewTreeObserver;
 import android.widget.QuickContactBadge;
 import android.widget.TextView;
 
@@ -34,19 +36,18 @@
 import com.android.contacts.common.ContactPhotoManager;
 import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest;
 import com.android.contacts.common.testing.NeededForTesting;
+import com.android.dialer.PhoneCallDetailsHelper;
 import com.android.dialer.PhoneCallDetailsViews;
 import com.android.dialer.R;
 
 /**
- * This is an object containing the various views within a call log entry. It contains values
- * pointing to views contained by a call log list item view, so that we can improve performance
- * by reducing the frequency with which we need to find views by IDs.
+ * This is an object containing references to views contained by the call log list item. This
+ * improves performance by reducing the frequency with which we need to find views by IDs.
  *
- * This object also contains methods for inflating action views and binding action behaviors. This
- * is a way of isolating view logic from the CallLogAdapter. We should consider moving that logic
- * if the call log list item is eventually represented as a UI component.
+ * This object also contains UI logic pertaining to the view, to isolate it from the CallLogAdapter.
  */
-public final class CallLogListItemViews extends RecyclerView.ViewHolder {
+public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder {
+
     /** The root view of the call log list item */
     public final View rootView;
     /** The quick contact badge for the contact. */
@@ -59,10 +60,10 @@
     public final TextView dayGroupHeader;
     /** The view containing the details for the call log row, including the action buttons. */
     public final CardView callLogEntryView;
+    /** The actionable view which places a call to the number corresponding to the call log row. */
+    public final View callActionView;
     /** The view containing call log item actions.  Null until the ViewStub is inflated. */
     public View actionsView;
-    /** The "call back" action button - assigned only when the action section is expanded. */
-    public TextView callBackButtonView;
     /** The "video call" action button - assigned only when the action section is expanded. */
     public TextView videoCallButtonView;
     /** The "voicemail" action button - assigned only when the action section is expanded. */
@@ -134,20 +135,31 @@
 
     private static final int VOICEMAIL_TRANSCRIPTION_MAX_LINES = 10;
 
-    private Context mContext;
-    private int mPhotoSize;
+    private final Context mContext;
+    private final View.OnClickListener mActionListener;
+    private final PhoneNumberUtilsWrapper mPhoneNumberUtilsWrapper;
+    private final CallLogListItemHelper mCallLogListItemHelper;
 
+    private final int mPhotoSize;
 
-    private CallLogListItemViews(
+    private CallLogListItemViewHolder(
             Context context,
+            View.OnClickListener actionListener,
+            PhoneNumberUtilsWrapper phoneNumberUtilsWrapper,
+            CallLogListItemHelper callLogListItemHelper,
             View rootView,
             QuickContactBadge quickContactView,
             View primaryActionView,
             PhoneCallDetailsViews phoneCallDetailsViews,
             CardView callLogEntryView,
-            TextView dayGroupHeader) {
+            TextView dayGroupHeader,
+            View callActionView) {
         super(rootView);
+
         mContext = context;
+        mActionListener = actionListener;
+        mPhoneNumberUtilsWrapper = phoneNumberUtilsWrapper;
+        mCallLogListItemHelper = callLogListItemHelper;
 
         this.rootView = rootView;
         this.quickContactView = quickContactView;
@@ -155,20 +167,39 @@
         this.phoneCallDetailsViews = phoneCallDetailsViews;
         this.callLogEntryView = callLogEntryView;
         this.dayGroupHeader = dayGroupHeader;
+        this.callActionView = callActionView;
 
         Resources resources = mContext.getResources();
         mPhotoSize = mContext.getResources().getDimensionPixelSize(R.dimen.contact_photo_size);
+
+        // Set text height to false on the TextViews so they don't have extra padding.
+        phoneCallDetailsViews.nameView.setElegantTextHeight(false);
+        phoneCallDetailsViews.callLocationAndDate.setElegantTextHeight(false);
+
+        if (callActionView != null) {
+            callActionView.setOnClickListener(mActionListener);
+        }
     }
 
-    public static CallLogListItemViews fromView(Context context, View view) {
-        return new CallLogListItemViews(
+    public static CallLogListItemViewHolder create(
+            View view,
+            Context context,
+            View.OnClickListener actionListener,
+            PhoneNumberUtilsWrapper phoneNumberUtilsWrapper,
+            CallLogListItemHelper callLogListItemHelper) {
+
+        return new CallLogListItemViewHolder(
                 context,
+                actionListener,
+                phoneNumberUtilsWrapper,
+                callLogListItemHelper,
                 view,
                 (QuickContactBadge) view.findViewById(R.id.quick_contact_photo),
                 view.findViewById(R.id.primary_action_view),
                 PhoneCallDetailsViews.fromView(view),
                 (CardView) view.findViewById(R.id.call_log_row),
-                (TextView) view.findViewById(R.id.call_log_day_group_label));
+                (TextView) view.findViewById(R.id.call_log_day_group_label),
+                view.findViewById(R.id.call_icon));
     }
 
     /**
@@ -179,19 +210,12 @@
      * @param callLogItem The call log list item view.
      */
     public void inflateActionViewStub(
-            final CallLogAdapter.OnReportButtonClickListener onReportButtonClickListener,
-            View.OnClickListener actionListener,
-            PhoneNumberUtilsWrapper phoneNumberUtilsWrapper,
-            CallLogListItemHelper callLogViewsHelper) {
+            final CallLogAdapter.OnReportButtonClickListener onReportButtonClickListener) {
         ViewStub stub = (ViewStub) rootView.findViewById(R.id.call_log_entry_actions_stub);
         if (stub != null) {
             actionsView = (ViewGroup) stub.inflate();
         }
 
-        if (callBackButtonView == null) {
-            callBackButtonView = (TextView) actionsView.findViewById(R.id.call_back_action);
-        }
-
         if (videoCallButtonView == null) {
             videoCallButtonView = (TextView) actionsView.findViewById(R.id.video_call_action);
         }
@@ -216,54 +240,54 @@
             });
         }
 
-        bindActionButtons(actionListener, phoneNumberUtilsWrapper, callLogViewsHelper);
+        bindActionButtons();
+    }
+
+    public void updateCallButton() {
+        boolean canPlaceCallToNumber =
+                PhoneNumberUtilsWrapper.canPlaceCallsTo(number, numberPresentation);
+
+        if (canPlaceCallToNumber) {
+            boolean isVoicemailNumber =
+                    mPhoneNumberUtilsWrapper.isVoicemailNumber(accountHandle, number);
+            if (isVoicemailNumber) {
+                // Make a general call to voicemail to ensure that if there are multiple accounts
+                // it does not call the voicemail number of a specific phone account.
+                callActionView.setTag(IntentProvider.getReturnVoicemailCallIntentProvider());
+            } else {
+                callActionView.setTag(IntentProvider.getReturnCallIntentProvider(number));
+            }
+
+            if (nameOrNumber != null) {
+                callActionView.setContentDescription(TextUtils.expandTemplate(
+                        mContext.getString(R.string.description_call_action),
+                        nameOrNumber));
+            } else {
+                callActionView.setContentDescription(
+                        mContext.getString(R.string.description_call_log_call_action));
+            }
+
+            callActionView.setVisibility(View.VISIBLE);
+        } else {
+            callActionView.setTag(null);
+            callActionView.setVisibility(View.GONE);
+        }
     }
 
     /**
      * Binds text titles, click handlers and intents to the voicemail, details and callback action
      * buttons.
      */
-    private void bindActionButtons(
-            View.OnClickListener actionListener,
-            PhoneNumberUtilsWrapper phoneNumberUtilsWrapper,
-            CallLogListItemHelper callLogViewsHelper) {
+    private void bindActionButtons() {
         boolean canPlaceCallToNumber =
                 PhoneNumberUtilsWrapper.canPlaceCallsTo(number, numberPresentation);
 
-        // Set return call intent, otherwise null.
-        if (canPlaceCallToNumber) {
-            boolean isVoicemailNumber =
-                    phoneNumberUtilsWrapper.isVoicemailNumber(accountHandle, number);
-            if (isVoicemailNumber) {
-                // Make a general call to voicemail to ensure that if there are multiple accounts
-                // it does not call the voicemail number of a specific phone account.
-                callBackButtonView.setTag(IntentProvider.getReturnVoicemailCallIntentProvider());
-            } else {
-                // Sets the primary action to call the number.
-                callBackButtonView.setTag(IntentProvider.getReturnCallIntentProvider(number));
-            }
-            callBackButtonView.setVisibility(View.VISIBLE);
-            callBackButtonView.setOnClickListener(actionListener);
-
-            final int titleId;
-            if (callType == Calls.VOICEMAIL_TYPE || callType == Calls.OUTGOING_TYPE) {
-                titleId = R.string.call_log_action_redial;
-            } else {
-                titleId = R.string.call_log_action_call_back;
-            }
-            callBackButtonView.setText(mContext.getString(titleId));
-        } else {
-            // Number is not callable, so hide button.
-            callBackButtonView.setTag(null);
-            callBackButtonView.setVisibility(View.GONE);
-        }
-
         // If one of the calls had video capabilities, show the video call button.
         if (CallUtil.isVideoEnabled(mContext) && canPlaceCallToNumber &&
                 phoneCallDetailsViews.callTypeIcons.isVideoShown()) {
             videoCallButtonView.setTag(IntentProvider.getReturnVideoCallIntentProvider(number));
             videoCallButtonView.setVisibility(View.VISIBLE);
-            videoCallButtonView.setOnClickListener(actionListener);
+            videoCallButtonView.setOnClickListener(mActionListener);
         } else {
             videoCallButtonView.setTag(null);
             videoCallButtonView.setVisibility(View.GONE);
@@ -271,7 +295,7 @@
 
         // For voicemail calls, show the "VOICEMAIL" action button; hide otherwise.
         if (callType == Calls.VOICEMAIL_TYPE) {
-            voicemailButtonView.setOnClickListener(actionListener);
+            voicemailButtonView.setOnClickListener(mActionListener);
             voicemailButtonView.setTag(
                     IntentProvider.getPlayVoicemailIntentProvider(rowId, voicemailUri));
             voicemailButtonView.setVisibility(View.VISIBLE);
@@ -281,7 +305,7 @@
             voicemailButtonView.setTag(null);
             voicemailButtonView.setVisibility(View.GONE);
 
-            detailsButtonView.setOnClickListener(actionListener);
+            detailsButtonView.setOnClickListener(mActionListener);
             detailsButtonView.setTag(
                     IntentProvider.getCallDetailIntentProvider(rowId, callIds, null));
 
@@ -292,30 +316,21 @@
             }
         }
 
-        callLogViewsHelper.setActionContentDescriptions(this);
+        mCallLogListItemHelper.setActionContentDescriptions(this);
     }
 
     /**
-     * Expands or collapses the view containing the CALLBACK/REDIAL, VOICEMAIL and DETAILS action
-     * buttons.
+     * Show or hide the action views, such as voicemail, details, and add contact.
      *
-     * TODO: Reduce number of classes which need to be passed in to inflate the action view stub.
-     *     1) Instantiate them in this class, and store local references.
-     *     2) Set them on the CallLogListItemHelper and use it for inflation.
-     *     3) Implement a parent view for a call log list item, and store references in that class.
+     * If the action views have never been shown yet for this view, inflate the view stub.
      */
-    public void expandOrCollapseActions(
-            boolean isExpanded,
-            final CallLogAdapter.OnReportButtonClickListener onReportButtonClickListener,
-            View.OnClickListener actionListener,
-            PhoneNumberUtilsWrapper phoneNumberUtilsWrapper,
-            CallLogListItemHelper callLogViewsHelper) {
-        expandVoicemailTranscriptionView(isExpanded);
+    public void showActions(boolean show,
+            final CallLogAdapter.OnReportButtonClickListener onReportButtonClickListener) {
+        expandVoicemailTranscriptionView(show);
 
-        if (isExpanded) {
+        if (show) {
             // Inflate the view stub if necessary, and wire up the event handlers.
-            inflateActionViewStub(onReportButtonClickListener, actionListener,
-                    phoneNumberUtilsWrapper, callLogViewsHelper);
+            inflateActionViewStub(onReportButtonClickListener);
 
             actionsView.setVisibility(View.VISIBLE);
             actionsView.setAlpha(1.0f);
@@ -326,6 +341,27 @@
                 actionsView.setVisibility(View.GONE);
             }
         }
+
+        if (actionsView != null) {
+            final ViewTreeObserver observer = callLogEntryView.getViewTreeObserver();
+            observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+                @Override
+                public boolean onPreDraw() {
+                    if (observer.isAlive()) {
+                        observer.removeOnPreDrawListener(this);
+                    }
+
+                    // TODO: Animate, instead of immediately resizing.
+                    int currentHeight = primaryActionView.getHeight();
+                    int actionsHeight = actionsView.getVisibility() == View.VISIBLE
+                            ? actionsView.getHeight() : 0;
+                    callLogEntryView.getLayoutParams().height = currentHeight + actionsHeight;
+                    callLogEntryView.requestLayout();
+
+                    return false;
+                }
+            });
+        }
     }
 
     public void expandVoicemailTranscriptionView(boolean isExpanded) {
@@ -371,20 +407,32 @@
     }
 
     @NeededForTesting
-    public static CallLogListItemViews createForTest(Context context) {
-        CallLogListItemViews views = new CallLogListItemViews(
+    public static CallLogListItemViewHolder createForTest(Context context) {
+        Resources resources = context.getResources();
+        PhoneNumberDisplayHelper phoneNumberHelper =
+                new PhoneNumberDisplayHelper(context, resources);
+        PhoneNumberUtilsWrapper phoneNumberUtilsWrapper = new PhoneNumberUtilsWrapper(context);
+        PhoneCallDetailsHelper phoneCallDetailsHelper = new PhoneCallDetailsHelper(
+                context, resources, phoneNumberUtilsWrapper);
+
+        CallLogListItemViewHolder viewHolder = new CallLogListItemViewHolder(
                 context,
+                null /* actionListener */,
+                phoneNumberUtilsWrapper,
+                new CallLogListItemHelper(
+                        phoneCallDetailsHelper, phoneNumberHelper, resources),
                 new View(context),
                 new QuickContactBadge(context),
                 new View(context),
                 PhoneCallDetailsViews.createForTest(context),
                 new CardView(context),
-                new TextView(context));
-        views.callBackButtonView = new TextView(context);
-        views.voicemailButtonView = new TextView(context);
-        views.detailsButtonView = new TextView(context);
-        views.reportButtonView = new TextView(context);
-        views.actionsView = new View(context);
-        return views;
+                new TextView(context),
+                new View(context));
+        viewHolder.voicemailButtonView = new TextView(context);
+        viewHolder.detailsButtonView = new TextView(context);
+        viewHolder.reportButtonView = new TextView(context);
+        viewHolder.actionsView = new View(context);
+
+        return viewHolder;
     }
 }
diff --git a/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java b/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java
index bffbe5c..70d63c9 100644
--- a/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java
+++ b/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.database.MatrixCursor;
+import android.support.v7.widget.RecyclerView.ViewHolder;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.view.View;
@@ -45,6 +46,7 @@
 
     private MatrixCursor mCursor;
     private View mView;
+    private ViewHolder mViewHolder;
 
     @Override
     protected void setUp() throws Exception {
@@ -72,7 +74,8 @@
         mCursor.moveToFirst();
         // The views into which to store the data.
         mView = new LinearLayout(getContext());
-        mView.setTag(CallLogListItemViews.createForTest(getContext()));
+        mViewHolder = CallLogListItemViewHolder.createForTest(getContext());
+        mView.setTag(mViewHolder);
     }
 
     @Override
@@ -88,7 +91,7 @@
 
         // Bind the views of a single row.
         mAdapter.changeCursor(mCursor);
-        mAdapter.onBindViewHolder(CallLogListItemViews.fromView(getContext(), mView), 0);
+        mAdapter.onBindViewHolder(mViewHolder, 0);
 
         // There is one request for contact details.
         assertEquals(1, mAdapter.getContactInfoCache().requests.size());
@@ -107,7 +110,7 @@
 
         // Bind the views of a single row.
         mAdapter.changeCursor(mCursor);
-        mAdapter.onBindViewHolder(CallLogListItemViews.fromView(getContext(), mView), 0);
+        mAdapter.onBindViewHolder(mViewHolder, 0);
 
         // There is one request for contact details.
         assertEquals(1, mAdapter.getContactInfoCache().requests.size());
@@ -126,8 +129,7 @@
 
         // Bind the views of a single row.
         mAdapter.changeCursor(mCursor);
-        mAdapter.onBindViewHolder(
-                CallLogListItemViews.fromView(getContext(), mView), 0);
+        mAdapter.onBindViewHolder(mViewHolder, 0);
 
         // There is one request for contact details.
         assertEquals(1, mAdapter.getContactInfoCache().requests.size());
@@ -143,7 +145,7 @@
 
         // Bind the views of a single row.
         mAdapter.changeCursor(mCursor);
-        mAdapter.onBindViewHolder(CallLogListItemViews.fromView(getContext(), mView), 0);
+        mAdapter.onBindViewHolder(mViewHolder, 0);
 
         // Cache and call log are up-to-date: no need to request update.
         assertEquals(0, mAdapter.getContactInfoCache().requests.size());
@@ -159,7 +161,7 @@
 
         // Bind the views of a single row.
         mAdapter.changeCursor(mCursor);
-        mAdapter.onBindViewHolder(CallLogListItemViews.fromView(getContext(), mView), 0);
+        mAdapter.onBindViewHolder(mViewHolder, 0);
 
         // There is one request for contact details.
         assertEquals(1, mAdapter.getContactInfoCache().requests.size());
diff --git a/tests/src/com/android/dialer/calllog/CallLogFragmentTest.java b/tests/src/com/android/dialer/calllog/CallLogFragmentTest.java
index fe14f87..0c19799 100644
--- a/tests/src/com/android/dialer/calllog/CallLogFragmentTest.java
+++ b/tests/src/com/android/dialer/calllog/CallLogFragmentTest.java
@@ -30,7 +30,6 @@
 import android.provider.CallLog.Calls;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.VoicemailContract;
-import android.support.v7.widget.RecyclerView.ViewHolder;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.TelephonyManager;
 import android.test.ActivityInstrumentationTestCase2;
@@ -94,10 +93,10 @@
     private Random mRnd;
 
     // An item in the call list. All the methods performing checks use it.
-    private CallLogListItemViews mItem;
+    private CallLogListItemViewHolder mItem;
 
     // The list of view holderss representing the data in the DB, in reverse order from the DB.
-    private ViewHolder[] mList;
+    private CallLogListItemViewHolder[] mList;
 
     public CallLogFragmentTest() {
         super(FragmentTestActivity.class);
@@ -136,13 +135,13 @@
     /**
      * Checks that the call icon is not visible for private and
      * unknown numbers.
-     * Use 2 passes, one where new views are created and one where
-     * half of the total views are updated and the other half created.
+     * Use 2 passes, one where new viewHolder are created and one where
+     * half of the total viewHolder are updated and the other half created.
      */
     @MediumTest
     public void testCallViewIsNotVisibleForPrivateAndUnknownNumbers() {
         final int SIZE = 100;
-        mList = new ViewHolder[SIZE];
+        mList = new CallLogListItemViewHolder[SIZE];
 
         // Insert the first batch of entries.
         mCursor.moveToFirst();
@@ -153,7 +152,7 @@
         checkCallStatus();
 
         // Append the rest of the entries. We keep the first set of
-        // views around so they get updated and not built from
+        // viewHolder around so they get updated and not built from
         // scratch, this exposes some bugs that are not there when the
         // call log is launched for the 1st time but show up when the
         // call log gets updated afterwards.
@@ -165,28 +164,31 @@
     }
 
     @MediumTest
-    public void testCallAndGroupViews_GroupView() {
+    public void testCallAndGroupviewHolder_GroupView() {
         mCursor.moveToFirst();
         insertPrivate(NOW, 0);
         insertPrivate(NOW, 0);
         insertPrivate(NOW, 0);
-        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
+        CallLogListItemViewHolder viewHolder = (CallLogListItemViewHolder)
+                mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
         mAdapter.onBindViewHolder(viewHolder, /* position */ 0);
     }
 
     @MediumTest
-    public void testCallAndGroupViews_StandAloneView() {
+    public void testCallAndGroupviewHolder_StandAloneView() {
         mCursor.moveToFirst();
         insertPrivate(NOW, 0);
-        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, 0);
+        CallLogListItemViewHolder viewHolder = (CallLogListItemViewHolder)
+                mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
         bindViewForTest(viewHolder);
     }
 
     @MediumTest
-    public void testCallAndGroupViews_ChildView() {
+    public void testCallAndGroupviewHolder_ChildView() {
         mCursor.moveToFirst();
         insertPrivate(NOW, 0);
-        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
+        CallLogListItemViewHolder viewHolder = (CallLogListItemViewHolder)
+                mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
         mAdapter.onBindViewHolder(viewHolder, /* position */ 0);
     }
 
@@ -194,11 +196,11 @@
     public void testBindView_NumberOnlyNoCache() {
         mCursor.moveToFirst();
         insert(TEST_NUMBER, Calls.PRESENTATION_ALLOWED, NOW, 0, Calls.INCOMING_TYPE);
-        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
+        CallLogListItemViewHolder viewHolder = (CallLogListItemViewHolder)
+                mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
         bindViewForTest(viewHolder);
 
-        CallLogListItemViews views = (CallLogListItemViews) viewHolder;
-        assertNameIs(views, TEST_NUMBER);
+        assertNameIs(viewHolder, TEST_NUMBER);
     }
 
     @MediumTest
@@ -208,11 +210,11 @@
                 Calls.PRESENTATION_ALLOWED, NOW, 0, Calls.INCOMING_TYPE);
         values[CallLogQuery.CACHED_FORMATTED_NUMBER] = TEST_FORMATTED_NUMBER;
         insertValues(values);
-        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
+        CallLogListItemViewHolder viewHolder = (CallLogListItemViewHolder)
+                mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
         bindViewForTest(viewHolder);
 
-        CallLogListItemViews views = (CallLogListItemViews) viewHolder;
-        assertNameIs(views, TEST_FORMATTED_NUMBER);
+        assertNameIs(viewHolder, TEST_FORMATTED_NUMBER);
     }
 
     @MediumTest
@@ -222,12 +224,12 @@
         // {@value com.android.dialer.calllog.ContactInfo#GEOCODE_AS_LABEL}
         insertWithCachedValues(TEST_NUMBER, NOW, 0, Calls.INCOMING_TYPE,
                 "John Doe", Phone.TYPE_HOME, TEST_DEFAULT_CUSTOM_LABEL);
-        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
+        CallLogListItemViewHolder viewHolder = (CallLogListItemViewHolder)
+                mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
         bindViewForTest(viewHolder);
 
-        CallLogListItemViews views = (CallLogListItemViews) viewHolder;
-        assertNameIs(views, "John Doe");
-        assertLabel(views, TEST_FORMATTED_NUMBER, getTypeLabel(Phone.TYPE_HOME));
+        assertNameIs(viewHolder, "John Doe");
+        assertLabel(viewHolder, TEST_FORMATTED_NUMBER, getTypeLabel(Phone.TYPE_HOME));
     }
 
     @MediumTest
@@ -235,12 +237,12 @@
         mCursor.moveToFirst();
         insertWithCachedValues("sip:johndoe@gmail.com", NOW, 0, Calls.INCOMING_TYPE,
                 "John Doe", Phone.TYPE_HOME, TEST_DEFAULT_CUSTOM_LABEL);
-        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
+        CallLogListItemViewHolder viewHolder = (CallLogListItemViewHolder)
+                mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
         bindViewForTest(viewHolder);
 
-        CallLogListItemViews views = (CallLogListItemViews) viewHolder;
-        assertNameIs(views, "John Doe");
-        assertLabel(views, "sip:johndoe@gmail.com", "sip:johndoe@gmail.com");
+        assertNameIs(viewHolder, "John Doe");
+        assertLabel(viewHolder, "sip:johndoe@gmail.com", "sip:johndoe@gmail.com");
     }
 
     @MediumTest
@@ -250,12 +252,12 @@
         // {@value com.android.dialer.calllog.ContactInfo#GEOCODE_AS_LABEL}
         insertWithCachedValues(TEST_NUMBER, NOW, 0, Calls.INCOMING_TYPE,
                 "John Doe", Phone.TYPE_HOME, TEST_DEFAULT_CUSTOM_LABEL);
-        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
+        CallLogListItemViewHolder viewHolder = (CallLogListItemViewHolder)
+                mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
         bindViewForTest(viewHolder);
 
-        CallLogListItemViews views = (CallLogListItemViews) viewHolder;
-        assertNameIs(views, "John Doe");
-        assertLabel(views, TEST_FORMATTED_NUMBER, getTypeLabel(Phone.TYPE_HOME));
+        assertNameIs(viewHolder, "John Doe");
+        assertLabel(viewHolder, TEST_FORMATTED_NUMBER, getTypeLabel(Phone.TYPE_HOME));
     }
 
     @MediumTest
@@ -265,12 +267,12 @@
         // {@link com.android.dialer.calllog.ContactInfo#GEOCODE_AS_LABEL}
         insertWithCachedValues(TEST_NUMBER, NOW, 0, Calls.INCOMING_TYPE,
                 "John Doe", Phone.TYPE_WORK, TEST_DEFAULT_CUSTOM_LABEL);
-        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
+        CallLogListItemViewHolder viewHolder = (CallLogListItemViewHolder)
+                mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
         bindViewForTest(viewHolder);
 
-        CallLogListItemViews views = (CallLogListItemViews) viewHolder;
-        assertNameIs(views, "John Doe");
-        assertLabel(views, TEST_FORMATTED_NUMBER, getTypeLabel(Phone.TYPE_WORK));
+        assertNameIs(viewHolder, "John Doe");
+        assertLabel(viewHolder, TEST_FORMATTED_NUMBER, getTypeLabel(Phone.TYPE_WORK));
     }
 
     @MediumTest
@@ -279,12 +281,12 @@
         String numberLabel = "My label";
         insertWithCachedValues(TEST_NUMBER, NOW, 0, Calls.INCOMING_TYPE,
                 "John Doe", Phone.TYPE_CUSTOM, numberLabel);
-        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
+        CallLogListItemViewHolder viewHolder = (CallLogListItemViewHolder)
+                mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
         bindViewForTest(viewHolder);
 
-        CallLogListItemViews views = (CallLogListItemViews) viewHolder;
-        assertNameIs(views, "John Doe");
-        assertLabel(views, TEST_FORMATTED_NUMBER, numberLabel);
+        assertNameIs(viewHolder, "John Doe");
+        assertLabel(viewHolder, TEST_FORMATTED_NUMBER, numberLabel);
     }
 
     @MediumTest
@@ -292,22 +294,22 @@
         mCursor.moveToFirst();
         insertWithCachedValues(TEST_NUMBER, NOW, 0, Calls.INCOMING_TYPE,
                 "John Doe", Phone.TYPE_HOME, "");
-        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
+        CallLogListItemViewHolder viewHolder = (CallLogListItemViewHolder)
+                mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
         bindViewForTest(viewHolder);
 
-        CallLogListItemViews views = (CallLogListItemViews) viewHolder;
-        assertTrue(views.quickContactView.isEnabled());
+        assertTrue(viewHolder.quickContactView.isEnabled());
     }
 
     @MediumTest
     public void testBindView_WithoutQuickContactBadge() {
         mCursor.moveToFirst();
         insert(TEST_NUMBER, Calls.PRESENTATION_ALLOWED, NOW, 0, Calls.INCOMING_TYPE);
-        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
+        CallLogListItemViewHolder viewHolder = (CallLogListItemViewHolder)
+                mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
         bindViewForTest(viewHolder);
 
-        CallLogListItemViews views = (CallLogListItemViews) viewHolder;
-        assertFalse(views.quickContactView.isEnabled());
+        assertFalse(viewHolder.quickContactView.isEnabled());
     }
 
     @MediumTest
@@ -315,16 +317,16 @@
         mCursor.moveToFirst();
         insert(TEST_NUMBER, Calls.PRESENTATION_ALLOWED, NOW, 0, Calls.INCOMING_TYPE);
         mAdapter.changeCursor(mCursor);
-        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
+        CallLogListItemViewHolder viewHolder = (CallLogListItemViewHolder)
+                mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
         bindViewForTest(viewHolder);
-
-        CallLogListItemViews views = (CallLogListItemViews) viewHolder;
+        viewHolder.updateCallButton();
 
         // The primaryActionView tag is set in the
         // {@link com.android.dialer.calllog.CallLogAdapter#bindView} method.  If it is possible
         // to place a call to the phone number, a call intent will have been created for the
         // primaryActionView.
-        IntentProvider intentProvider = (IntentProvider) views.callBackButtonView.getTag();
+        IntentProvider intentProvider = (IntentProvider) viewHolder.callActionView.getTag();
         Intent intent = intentProvider.getIntent(mActivity);
         // Starts a call.
         assertEquals(TestConstants.CALL_INTENT_ACTION, intent.getAction());
@@ -336,11 +338,11 @@
     public void testBindView_PlayButton() {
         mCursor.moveToFirst();
         insertVoicemail(TEST_NUMBER, Calls.PRESENTATION_ALLOWED, NOW, 0);
-        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
+        CallLogListItemViewHolder viewHolder = (CallLogListItemViewHolder)
+                mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
         bindViewForTest(viewHolder);
 
-        CallLogListItemViews views = (CallLogListItemViews) viewHolder;
-        IntentProvider intentProvider = (IntentProvider) views.voicemailButtonView.getTag();
+        IntentProvider intentProvider = (IntentProvider) viewHolder.voicemailButtonView.getTag();
         Intent intent = intentProvider.getIntent(mActivity);
         // Starts the call detail activity.
         assertEquals(new ComponentName(mActivity, CallDetailActivity.class),
@@ -363,10 +365,10 @@
     }
 
     //
-    // HELPERS to check conditions on the DB/views
+    // HELPERS to check conditions on the DB/viewHolder
     //
     /**
-     * Go over the views in the list and check to ensure that
+     * Go over the viewHolder in the list and check to ensure that
      * callable numbers have an associated call intent, where numbers
      * which are not callable have a null intent.
      */
@@ -375,17 +377,17 @@
             if (null == mList[i]) {
                 break;
             }
-            mItem = (CallLogListItemViews) mList[i];
+            mItem = (CallLogListItemViewHolder) mList[i];
             int presentation = getPhoneNumberPresentationForListEntry(i);
             if (presentation == Calls.PRESENTATION_RESTRICTED ||
                     presentation == Calls.PRESENTATION_UNKNOWN) {
                 //If number is not callable, the primary action view should have a null tag.
-                assertNull(mItem.callBackButtonView.getTag());
+                assertNull(mItem.callActionView.getTag());
             } else {
                 //If the number is callable, the primary action view should have a non-null tag.
-                assertNotNull(mItem.callBackButtonView.getTag());
+                assertNotNull(mItem.callActionView.getTag());
 
-                IntentProvider intentProvider = (IntentProvider)mItem.callBackButtonView.getTag();
+                IntentProvider intentProvider = (IntentProvider)mItem.callActionView.getTag();
                 Intent callIntent = intentProvider.getIntent(mActivity);
 
                 //The intent should be to make the call
@@ -412,7 +414,7 @@
     }
 
     //
-    // HELPERS to build/update the call entries (views) from the DB.
+    // HELPERS to build/update the call entries (viewHolder) from the DB.
     //
 
     /**
@@ -425,7 +427,8 @@
         mCursor.moveToLast();
         while (!mCursor.isBeforeFirst()) {
             if (null == mList[i]) {
-                mList[i] = mAdapter.onCreateViewHolder(mParentView, /* itemType */ 0);
+                mList[i] = (CallLogListItemViewHolder)
+                        mAdapter.onCreateViewHolder(mParentView, /* itemType */ 0);
             }
             // Bind to the proper position, despite iterating in reverse.
             bindViewForTest(mList[i], mCursor.getCount() - i - 1);
@@ -452,12 +455,13 @@
      * @param view The current call log row.
      * @param position The position of hte item.
      */
-    private void bindViewForTest(ViewHolder viewHolder, int position) {
+    private void bindViewForTest(CallLogListItemViewHolder viewHolder, int position) {
         mAdapter.onBindViewHolder(viewHolder, position);
-        mAdapter.expandItem((CallLogListItemViews) viewHolder, /* expand */ true);
+        viewHolder.inflateActionViewStub(null);
+        viewHolder.updateCallButton();
     }
 
-    private void bindViewForTest(ViewHolder viewHolder) {
+    private void bindViewForTest(CallLogListItemViewHolder viewHolder) {
         bindViewForTest(viewHolder, /* position */ 0);
     }
 
@@ -645,17 +649,17 @@
     }
 
     /** Asserts that the name text view is shown and contains the given text. */
-    private void assertNameIs(CallLogListItemViews views, String name) {
-        assertEquals(View.VISIBLE, views.phoneCallDetailsViews.nameView.getVisibility());
-        assertEquals(name, views.phoneCallDetailsViews.nameView.getText().toString());
+    private void assertNameIs(CallLogListItemViewHolder viewHolder, String name) {
+        assertEquals(View.VISIBLE, viewHolder.phoneCallDetailsViews.nameView.getVisibility());
+        assertEquals(name, viewHolder.phoneCallDetailsViews.nameView.getText().toString());
     }
 
     /** Asserts that the label text view contains the given text. */
-    private void assertLabel(CallLogListItemViews views, CharSequence number,
+    private void assertLabel(CallLogListItemViewHolder viewHolder, CharSequence number,
             CharSequence label) {
         if (label != null) {
-            assertTrue(views.phoneCallDetailsViews.callLocationAndDate.getText().toString()
-                    .contains(label));
+            assertTrue(viewHolder.phoneCallDetailsViews.callLocationAndDate.getText()
+                    .toString().contains(label));
         }
     }
 }
diff --git a/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java b/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java
index 30a84c2..0f4974b 100644
--- a/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java
+++ b/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java
@@ -50,7 +50,7 @@
     private CallLogListItemHelper mHelper;
 
     /** The views used in the tests. */
-    private CallLogListItemViews mViews;
+    private CallLogListItemViewHolder mViewHolder;
     private PhoneNumberDisplayHelper mPhoneNumberHelper;
     private PhoneNumberDisplayHelper mPhoneNumberDisplayHelper;
 
@@ -68,20 +68,20 @@
         mPhoneNumberDisplayHelper = new PhoneNumberDisplayHelper(context, mResources, phoneUtils);
         mHelper = new CallLogListItemHelper(phoneCallDetailsHelper, mPhoneNumberDisplayHelper,
                 mResources);
-        mViews = CallLogListItemViews.createForTest(context);
+        mViewHolder = CallLogListItemViewHolder.createForTest(getContext());
     }
 
     @Override
     protected void tearDown() throws Exception {
         mHelper = null;
-        mViews = null;
+        mViewHolder = null;
         super.tearDown();
     }
 
     public void testSetPhoneCallDetails() {
         setPhoneCallDetailsWithNumber("12125551234", Calls.PRESENTATION_ALLOWED,
                 "1-212-555-1234");
-        assertEquals(View.VISIBLE, mViews.callBackButtonView.getVisibility());
+        assertEquals(View.VISIBLE, mViewHolder.callActionView.getVisibility());
     }
 
     public void testSetPhoneCallDetails_Unknown() {
@@ -102,23 +102,23 @@
     public void testSetPhoneCallDetails_VoicemailNumber() {
         setPhoneCallDetailsWithNumber(TEST_VOICEMAIL_NUMBER,
                 Calls.PRESENTATION_ALLOWED, TEST_VOICEMAIL_NUMBER);
-        assertEquals(View.VISIBLE, mViews.voicemailButtonView.getVisibility());
+        assertEquals(View.VISIBLE, mViewHolder.voicemailButtonView.getVisibility());
     }
 
     public void testSetPhoneCallDetails_ReadVoicemail() {
         setPhoneCallDetailsWithTypes(Calls.VOICEMAIL_TYPE);
-        assertEquals(View.VISIBLE, mViews.voicemailButtonView.getVisibility());
+        assertEquals(View.VISIBLE, mViewHolder.voicemailButtonView.getVisibility());
     }
 
     public void testSetPhoneCallDetails_UnreadVoicemail() {
         setUnreadPhoneCallDetailsWithTypes(Calls.VOICEMAIL_TYPE);
-        assertEquals(View.VISIBLE, mViews.voicemailButtonView.getVisibility());
+        assertEquals(View.VISIBLE, mViewHolder.voicemailButtonView.getVisibility());
     }
 
     public void testSetPhoneCallDetails_VoicemailFromUnknown() {
         setPhoneCallDetailsWithNumberAndType("", Calls.PRESENTATION_UNKNOWN,
                 "", Calls.VOICEMAIL_TYPE);
-        assertEquals(View.VISIBLE, mViews.voicemailButtonView.getVisibility());
+        assertEquals(View.VISIBLE, mViewHolder.voicemailButtonView.getVisibility());
     }
 
     /**
@@ -335,7 +335,7 @@
 
     /** Asserts that the primary action view does not have a call intent. */
     private void assertNoCallIntent() {
-        Object intentProvider = (IntentProvider)mViews.primaryActionView.getTag();
+        Object intentProvider = (IntentProvider)mViewHolder.primaryActionView.getTag();
         // The intent provider should be null as there is no ability to make a call.
         assertNull(intentProvider);
     }
@@ -350,7 +350,7 @@
     /** Sets the details of a phone call using the specified phone number. */
     private void setPhoneCallDetailsWithNumberAndType(String number,
             int presentation, String formattedNumber, int callType) {
-        mHelper.setPhoneCallDetails(getContext(), mViews,
+        mHelper.setPhoneCallDetails(getContext(), mViewHolder,
                 new PhoneCallDetails(number, presentation, formattedNumber,
                         TEST_COUNTRY_ISO, TEST_GEOCODE,
                         new int[]{ callType }, TEST_DATE, TEST_DURATION)
@@ -359,7 +359,7 @@
 
     /** Sets the details of a phone call using the specified call type. */
     private void setPhoneCallDetailsWithTypes(int... types) {
-        mHelper.setPhoneCallDetails(getContext() ,mViews,
+        mHelper.setPhoneCallDetails(getContext() ,mViewHolder,
                 new PhoneCallDetails(TEST_NUMBER, Calls.PRESENTATION_ALLOWED,
                         TEST_FORMATTED_NUMBER, TEST_COUNTRY_ISO, TEST_GEOCODE,
                         types, TEST_DATE, TEST_DURATION)
@@ -368,7 +368,7 @@
 
     /** Sets the details of an unread phone call using the specified call type. */
     private void setUnreadPhoneCallDetailsWithTypes(int... types) {
-        mHelper.setPhoneCallDetails(getContext(), mViews,
+        mHelper.setPhoneCallDetails(getContext(), mViewHolder,
                 new PhoneCallDetails(TEST_NUMBER, Calls.PRESENTATION_ALLOWED,
                         TEST_FORMATTED_NUMBER, TEST_COUNTRY_ISO, TEST_GEOCODE,
                         types, TEST_DATE, TEST_DURATION)