Merge "Merge commit 'd3ffa4914baebe668d540fc966efddd0c89a92a2' into merge_work"
diff --git a/Android.mk b/Android.mk
index b029189..baf71ad 100644
--- a/Android.mk
+++ b/Android.mk
@@ -18,10 +18,12 @@
     $(phone_common_dir)/res
 
 LOCAL_SRC_FILES := $(call all-java-files-under, $(src_dirs))
-LOCAL_RESOURCE_DIR := $(addprefix $(LOCAL_PATH)/, $(res_dirs))
+LOCAL_RESOURCE_DIR := $(addprefix $(LOCAL_PATH)/, $(res_dirs)) \
+    frameworks/support/v7/cardview/res
 
 LOCAL_AAPT_FLAGS := \
     --auto-add-overlay \
+    --extra-packages android.support.v7.cardview \
     --extra-packages android.support.v7.recyclerview \
     --extra-packages com.android.incallui \
     --extra-packages com.android.contacts.common \
@@ -33,6 +35,7 @@
     android-ex-variablespeed \
     android-support-v13 \
     android-support-v4 \
+    android-support-v7-cardview \
     android-support-v7-recyclerview \
     com.android.services.telephony.common \
     com.android.vcard \
diff --git a/res/layout/call_log_fragment.xml b/res/layout/call_log_fragment.xml
index 74c6309..ff0d58e 100644
--- a/res/layout/call_log_fragment.xml
+++ b/res/layout/call_log_fragment.xml
@@ -28,51 +28,20 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:visibility="gone">
-        <include layout="@layout/call_log_voicemail_status"
-    />
+
+        <include layout="@layout/call_log_voicemail_status" />
+
     </FrameLayout>
 
     <FrameLayout
         android:layout_width="match_parent"
-        android:layout_height="wrap_content">
-        <TextView
-            android:id="@+id/filter_status"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            style="@style/ContactListSeparatorTextViewStyle"
-            android:layout_marginStart="@dimen/call_log_outer_margin"
-            android:layout_marginEnd="@dimen/call_log_outer_margin"
-            android:paddingTop="@dimen/call_log_inner_margin"
-            android:paddingBottom="@dimen/call_log_inner_margin"
-            android:layout_alignParentStart="true"
-            android:layout_alignParentBottom="true"
-            android:visibility="gone"
-            />
-        <View
-            android:id="@+id/call_log_divider"
-            android:layout_width="match_parent"
-            android:layout_height="1px"
-            android:layout_marginStart="@dimen/call_log_outer_margin"
-            android:layout_marginEnd="@dimen/call_log_outer_margin"
-            android:layout_gravity="bottom"
-            android:background="#55ffffff"
-            />
-    </FrameLayout>
-    <FrameLayout
-        android:layout_width="match_parent"
         android:layout_height="match_parent">
-        <!-- clipChildren=false is required to ensure shadows drawn
-            within list items aren't clipped by the list item bounds. -->
-        <ListView android:id="@android:id/list"
+
+        <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:fadingEdge="none"
-            android:scrollbarStyle="outsideOverlay"
             android:background="@color/background_dialer_list_items"
-            android:divider="@null"
-            android:nestedScrollingEnabled="true"
-            android:clipChildren="false"
-        />
+            android:padding="8dp" />
 
         <include
             android:id="@+id/empty_list_view"
diff --git a/res/layout/call_log_list_item.xml b/res/layout/call_log_list_item.xml
index 910e78f..1fbc579 100644
--- a/res/layout/call_log_list_item.xml
+++ b/res/layout/call_log_list_item.xml
@@ -37,13 +37,17 @@
 
     <!-- Linear layout to separate the primary area containing the contact badge and caller
          information and the secondary action (call details / play voicemail). -->
-    <LinearLayout
+    <android.support.v7.widget.CardView
+        xmlns:card_view="http://schemas.android.com/apk/res-auto"
         android:id="@+id/call_log_row"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:layout_margin="4dp"
         android:baselineAligned="false"
         android:orientation="vertical"
-        android:gravity="center_vertical" >
+        android:gravity="center_vertical"
+        card_view:cardCornerRadius="4dp"
+        card_view:cardBackgroundColor="@color/background_dialer_list_items">
 
         <!-- Primary area containing the contact badge and caller information -->
         <LinearLayout
@@ -60,6 +64,7 @@
             android:focusable="true"
             android:nextFocusRight="@+id/call_back_action"
             android:nextFocusLeft="@+id/quick_contact_photo" >
+
             <QuickContactBadge
                 android:id="@+id/quick_contact_photo"
                 android:layout_width="@dimen/contact_photo_size"
@@ -67,16 +72,16 @@
                 android:paddingTop="2dp"
                 android:nextFocusRight="@id/primary_action_view"
                 android:layout_gravity="top"
-                android:focusable="true"
-                />
+                android:focusable="true" />
+
             <LinearLayout
                 android:layout_width="0dp"
                 android:layout_height="wrap_content"
                 android:layout_weight="1"
                 android:orientation="vertical"
                 android:gravity="center_vertical"
-                android:layout_marginStart="@dimen/call_log_start_margin"
-                >
+                android:layout_marginStart="@dimen/call_log_start_margin">
+
                 <TextView
                     android:id="@+id/name"
                     android:layout_width="wrap_content"
@@ -85,8 +90,8 @@
                     android:layout_marginEnd="@dimen/call_log_icon_margin"
                     android:textColor="?attr/call_log_primary_text_color"
                     android:textSize="@dimen/call_log_primary_text_size"
-                    android:singleLine="true"
-                    />
+                    android:singleLine="true" />
+
                 <TextView
                     android:id="@+id/voicemail_transcription"
                     android:layout_width="wrap_content"
@@ -96,22 +101,22 @@
                     android:textSize="@dimen/call_log_secondary_text_size"
                     android:singleLine="true"
                     android:ellipsize="marquee"
-                    android:visibility="gone"
-                    />
+                    android:visibility="gone" />
+
                 <LinearLayout
                     android:id="@+id/call_type"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:orientation="horizontal"
-                    >
+                    android:orientation="horizontal">
+
                     <view
                         class="com.android.dialer.calllog.CallTypeIconsView"
                         android:id="@+id/call_type_icons"
                         android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
                         android:layout_marginEnd="@dimen/call_log_icon_margin"
-                        android:layout_gravity="center_vertical"
-                        />
+                        android:layout_gravity="center_vertical" />
+
                     <TextView
                         android:id="@+id/call_location_and_date"
                         android:layout_width="wrap_content"
@@ -120,9 +125,10 @@
                         android:layout_gravity="center_vertical"
                         android:textColor="?attr/call_log_secondary_text_color"
                         android:textSize="@dimen/call_log_secondary_text_size"
-                        android:singleLine="true"
-                        />
+                        android:singleLine="true" />
+
                 </LinearLayout>
+
                 <TextView
                     android:id="@+id/call_account_label"
                     android:layout_width="wrap_content"
@@ -131,9 +137,10 @@
                     android:textColor="?attr/call_log_secondary_text_color"
                     android:textSize="@dimen/call_log_secondary_text_size"
                     android:visibility="gone"
-                    android:singleLine="true"
-                    />
+                    android:singleLine="true" />
+
             </LinearLayout>
+
             <ImageView
                 android:id="@+id/call_indicator_icon"
                 android:layout_width="wrap_content"
@@ -144,16 +151,17 @@
                 android:tint="@color/recent_call_log_item_phone_icon_tint"
                 android:alpha="0.3"
                 android:importantForAccessibility="no"
-                android:visibility="gone"
-                />
+                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"/>
-    </LinearLayout>
+    </android.support.v7.widget.CardView>
 
 </LinearLayout>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index f697cc8..2954d75 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -58,7 +58,7 @@
     <!-- Background color for search results and call details -->
     <color name="background_dialer_results">#f9f9f9</color>
     <!-- Background color of dialer list items (contacts, call log entries) -->
-    <color name="background_dialer_list_items">@color/background_dialer_light</color>
+    <color name="background_dialer_list_items">@color/background_dialer_white</color>
     <color name="background_dialer_details_list_items">@color/background_dialer_results</color>
 
     <!-- Color of the 1dp divider that separates favorites -->
@@ -84,7 +84,6 @@
     <!-- Color of the bottom border below the contacts grid on the main dialer screen. -->
     <color name="contacts_grid_bottom_border_color">#16000000</color>
 
-    <color name="call_log_expanded_background_color">#ffffff</color>
     <!-- Color of actions in expanded call log entries.  This text color represents actions such
          as call back, play voicemail, etc. -->
     <color name="call_log_action_text">@color/dialer_theme_color</color>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 9de20f3..0902cb7 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -111,8 +111,6 @@
     <dimen name="call_log_list_item_actions_text_size">12sp</dimen>
     <!-- Height of the call log actions section for each call log entry -->
     <dimen name="call_log_action_height">44dp</dimen>
-    <!-- Z Translation of expanded call log items. -->
-    <dimen name="call_log_expanded_translation_z">2dp</dimen>
     <dimen name="call_log_day_group_padding_top">15dp</dimen>
     <dimen name="call_log_day_group_padding_bottom">9dp</dimen>
 
diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java
index 3e8efa0..07cd215 100644
--- a/src/com/android/dialer/calllog/CallLogAdapter.java
+++ b/src/com/android/dialer/calllog/CallLogAdapter.java
@@ -23,6 +23,7 @@
 import android.net.Uri;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.ContactsContract.PhoneLookup;
+import android.support.v7.widget.RecyclerView.ViewHolder;
 import android.telecom.PhoneAccountHandle;
 import android.telephony.PhoneNumberUtils;
 import android.text.TextUtils;
@@ -225,13 +226,12 @@
         mLoading = loading;
     }
 
-    @Override
     public boolean isEmpty() {
         if (mLoading) {
             // We don't want the empty state to show when loading.
             return false;
         } else {
-            return super.isEmpty();
+            return getItemCount() == 0;
         }
     }
 
@@ -262,48 +262,19 @@
     }
 
     @Override
-    protected View newStandAloneView(Context context, ViewGroup parent) {
-        return newChildView(context, parent);
-    }
-
-    @Override
-    protected View newGroupView(Context context, ViewGroup parent) {
-        return newChildView(context, parent);
-    }
-
-    @Override
-    protected View newChildView(Context context, ViewGroup parent) {
-        LayoutInflater inflater = LayoutInflater.from(context);
+    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+        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(context, view);
+        CallLogListItemViews views = CallLogListItemViews.fromView(mContext, view);
         view.setTag(views);
 
         // 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 view;
-    }
-
-    @Override
-    protected void bindStandAloneView(View view, Context context, Cursor cursor) {
-        bindView(view, cursor, 1);
-    }
-
-    @Override
-    protected void bindChildView(View view, Context context, Cursor cursor) {
-        bindView(view, cursor, 1);
-    }
-
-    @Override
-    protected void bindGroupView(View view, Context context, Cursor cursor, int groupSize,
-            boolean expanded) {
-        bindView(view, cursor, groupSize);
-    }
-
-    private void findAndCacheViews(View view) {
+        return (CallLogListItemViews) view.getTag();
     }
 
     /**
@@ -312,12 +283,17 @@
      * should not. It invokes cross-process methods and the repeat execution can get costly.
      *
      * @param callLogItemView the view corresponding to this entry
-     * @param c the cursor pointing to the entry in the call log
      * @param count the number of entries in the current item, greater than 1 if it is a group
      */
-    public void bindView(View callLogItemView, Cursor c, int count) {
-        callLogItemView.setAccessibilityDelegate(mAccessibilityDelegate);
-        final CallLogListItemViews views = (CallLogListItemViews) callLogItemView.getTag();
+    public void onBindViewHolder(ViewHolder viewHolder, int position) {
+        Cursor c = (Cursor) getItem(position);
+        if (c == null) {
+            return;
+        }
+        int count = getGroupSize(position);
+
+        CallLogListItemViews views = (CallLogListItemViews) viewHolder;
+        views.rootView.setAccessibilityDelegate(mAccessibilityDelegate);
 
         // Default case: an item in the call log.
         views.primaryActionView.setVisibility(View.VISIBLE);
@@ -435,7 +411,7 @@
 
         // Listen for the first draw
         if (mViewTreeObserver == null) {
-            mViewTreeObserver = callLogItemView.getViewTreeObserver();
+            mViewTreeObserver = views.rootView.getViewTreeObserver();
             mViewTreeObserver.addOnPreDrawListener(this);
         }
     }
diff --git a/src/com/android/dialer/calllog/CallLogFragment.java b/src/com/android/dialer/calllog/CallLogFragment.java
index d69c2ed..4f4fc1b 100644
--- a/src/com/android/dialer/calllog/CallLogFragment.java
+++ b/src/com/android/dialer/calllog/CallLogFragment.java
@@ -21,8 +21,8 @@
 import android.animation.ValueAnimator;
 import android.app.Activity;
 import android.app.DialogFragment;
+import android.app.Fragment;
 import android.app.KeyguardManager;
-import android.app.ListFragment;
 import android.content.Context;
 import android.content.Intent;
 import android.database.ContentObserver;
@@ -34,10 +34,11 @@
 import android.provider.CallLog.Calls;
 import android.provider.ContactsContract;
 import android.provider.VoicemailContract.Status;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.LinearLayoutManager;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup.LayoutParams;
 import android.widget.ListView;
@@ -60,7 +61,7 @@
  * Displays a list of call log entries. To filter for a particular kind of call
  * (all, missed or voicemails), specify it in the constructor.
  */
-public class CallLogFragment extends ListFragment
+public class CallLogFragment extends Fragment
         implements CallLogQueryHandler.Listener, CallLogAdapter.OnReportButtonClickListener,
         CallLogAdapter.CallFetcher {
     private static final String TAG = "CallLogFragment";
@@ -76,6 +77,8 @@
     private static final String KEY_LOG_LIMIT = "log_limit";
     private static final String KEY_DATE_LIMIT = "date_limit";
 
+    private RecyclerView mRecyclerView;
+    private LinearLayoutManager mLayoutManager;
     private CallLogAdapter mAdapter;
     private CallLogQueryHandler mCallLogQueryHandler;
     private boolean mScrollToTop;
@@ -172,9 +175,6 @@
         }
 
         String currentCountryIso = GeoUtil.getCurrentCountryIso(getActivity());
-        mAdapter = ObjectFactory.newCallLogAdapter(getActivity(), this,
-                new ContactInfoHelper(getActivity(), currentCountryIso), this);
-        setListAdapter(mAdapter);
         mCallLogQueryHandler = new CallLogQueryHandler(getActivity().getContentResolver(),
                 this, mLogLimit);
         mKeyguardManager =
@@ -201,9 +201,8 @@
         // This will update the state of the "Clear call log" menu item.
         getActivity().invalidateOptionsMenu();
 
-        final ListView listView = getListView();
         boolean showListView = cursor.getCount() > 0;
-        listView.setVisibility(showListView ? View.VISIBLE : View.GONE);
+        mRecyclerView.setVisibility(showListView ? View.VISIBLE : View.GONE);
         mEmptyListView.setVisibility(!showListView ? View.VISIBLE : View.GONE);
 
         if (mScrollToTop) {
@@ -213,8 +212,9 @@
             // will not experience the illusion of downward motion.  Instead,
             // if we're not already near the top of the list, we instantly jump
             // near the top, and animate from there.
-            if (listView.getFirstVisiblePosition() > 5) {
-                listView.setSelection(5);
+            if (mLayoutManager.findFirstVisibleItemPosition() > 5) {
+                // TODO: Jump to near the top, then begin smooth scroll.
+                mRecyclerView.smoothScrollToPosition(0);
             }
             // Workaround for framework issue: the smooth-scroll doesn't
             // occur if setSelection() is called immediately before.
@@ -224,7 +224,7 @@
                    if (getActivity() == null || getActivity().isFinishing()) {
                        return;
                    }
-                   listView.smoothScrollToPosition(0);
+                   mRecyclerView.smoothScrollToPosition(0);
                }
             });
 
@@ -269,6 +269,17 @@
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
         View view = inflater.inflate(R.layout.call_log_fragment, container, false);
+
+        mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
+        mRecyclerView.setHasFixedSize(true);
+        mLayoutManager = new LinearLayoutManager(getActivity());
+        mRecyclerView.setLayoutManager(mLayoutManager);
+
+        String currentCountryIso = GeoUtil.getCurrentCountryIso(getActivity());
+        mAdapter = ObjectFactory.newCallLogAdapter(getActivity(), this,
+                new ContactInfoHelper(getActivity(), currentCountryIso), this);
+        mRecyclerView.setAdapter(mAdapter);
+
         mVoicemailStatusHelper = new VoicemailStatusHelperImpl();
         mStatusMessageView = view.findViewById(R.id.voicemail_status);
         mStatusMessageText = (TextView) view.findViewById(R.id.voicemail_status_message);
@@ -280,7 +291,6 @@
     public void onViewCreated(View view, Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
         mEmptyListView = view.findViewById(R.id.empty_list_view);
-        getListView().setItemsCanFocus(true);
 
         updateEmptyMessage(mCallTypeFilter);
     }
diff --git a/src/com/android/dialer/calllog/CallLogListItemViews.java b/src/com/android/dialer/calllog/CallLogListItemViews.java
index 9d11a3a..4d43436 100644
--- a/src/com/android/dialer/calllog/CallLogListItemViews.java
+++ b/src/com/android/dialer/calllog/CallLogListItemViews.java
@@ -20,6 +20,8 @@
 import android.content.res.Resources;
 import android.net.Uri;
 import android.provider.CallLog.Calls;
+import android.support.v7.widget.CardView;
+import android.support.v7.widget.RecyclerView;
 import android.telecom.PhoneAccountHandle;
 import android.text.TextUtils;
 import android.view.View;
@@ -44,7 +46,7 @@
  * 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.
  */
-public final class CallLogListItemViews {
+public final class CallLogListItemViews extends RecyclerView.ViewHolder {
     /** The root view of the call log list item */
     public final View rootView;
     /** The quick contact badge for the contact. */
@@ -56,7 +58,7 @@
     /** The text of the header for a day grouping. */
     public final TextView dayGroupHeader;
     /** The view containing the details for the call log row, including the action buttons. */
-    public final View callLogEntryView;
+    public final CardView callLogEntryView;
     /** 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. */
@@ -135,9 +137,6 @@
     private Context mContext;
     private int mPhotoSize;
 
-    private int mCallLogBackgroundColor;
-    private int mExpandedBackgroundColor;
-    private float mExpandedTranslationZ;
 
     private CallLogListItemViews(
             Context context,
@@ -145,8 +144,9 @@
             QuickContactBadge quickContactView,
             View primaryActionView,
             PhoneCallDetailsViews phoneCallDetailsViews,
-            View callLogEntryView,
+            CardView callLogEntryView,
             TextView dayGroupHeader) {
+        super(rootView);
         mContext = context;
 
         this.rootView = rootView;
@@ -157,9 +157,6 @@
         this.dayGroupHeader = dayGroupHeader;
 
         Resources resources = mContext.getResources();
-        mCallLogBackgroundColor = resources.getColor(R.color.background_dialer_list_items);
-        mExpandedBackgroundColor = resources.getColor(R.color.call_log_expanded_background_color);
-        mExpandedTranslationZ = resources.getDimension(R.dimen.call_log_expanded_translation_z);
         mPhotoSize = mContext.getResources().getDimensionPixelSize(R.dimen.contact_photo_size);
     }
 
@@ -170,7 +167,7 @@
                 (QuickContactBadge) view.findViewById(R.id.quick_contact_photo),
                 view.findViewById(R.id.primary_action_view),
                 PhoneCallDetailsViews.fromView(view),
-                view.findViewById(R.id.call_log_row),
+                (CardView) view.findViewById(R.id.call_log_row),
                 (TextView) view.findViewById(R.id.call_log_day_group_label));
     }
 
@@ -322,19 +319,12 @@
 
             actionsView.setVisibility(View.VISIBLE);
             actionsView.setAlpha(1.0f);
-            callLogEntryView.setBackgroundColor(mExpandedBackgroundColor);
-            callLogEntryView.setTranslationZ(mExpandedTranslationZ);
-            rootView.setTranslationZ(mExpandedTranslationZ); // WAR
         } else {
             // When recycling a view, it is possible the actionsView ViewStub was previously
             // inflated so we should hide it in this case.
             if (actionsView != null) {
                 actionsView.setVisibility(View.GONE);
             }
-
-            callLogEntryView.setBackgroundColor(mCallLogBackgroundColor);
-            callLogEntryView.setTranslationZ(0);
-            rootView.setTranslationZ(0); // WAR
         }
     }
 
@@ -388,7 +378,7 @@
                 new QuickContactBadge(context),
                 new View(context),
                 PhoneCallDetailsViews.createForTest(context),
-                new View(context),
+                new CardView(context),
                 new TextView(context));
         views.callBackButtonView = new TextView(context);
         views.voicemailButtonView = new TextView(context);
diff --git a/src/com/android/dialer/calllog/GroupingListAdapter.java b/src/com/android/dialer/calllog/GroupingListAdapter.java
index 7895549..501e88d 100644
--- a/src/com/android/dialer/calllog/GroupingListAdapter.java
+++ b/src/com/android/dialer/calllog/GroupingListAdapter.java
@@ -21,6 +21,8 @@
 import android.database.Cursor;
 import android.database.DataSetObserver;
 import android.os.Handler;
+import android.support.v7.widget.RecyclerView;
+import android.util.Log;
 import android.util.SparseIntArray;
 import android.view.View;
 import android.view.ViewGroup;
@@ -34,7 +36,7 @@
  * The list has three types of elements: stand-alone, group header and group child. Groups are
  * collapsible and collapsed by default. This is used by the call log to group related entries.
  */
-abstract class GroupingListAdapter extends BaseAdapter {
+abstract class GroupingListAdapter extends RecyclerView.Adapter {
 
     private static final int GROUP_METADATA_ARRAY_INITIAL_SIZE = 16;
     private static final int GROUP_METADATA_ARRAY_INCREMENT = 128;
@@ -109,11 +111,6 @@
         public void onChanged() {
             notifyDataSetChanged();
         }
-
-        @Override
-        public void onInvalidated() {
-            notifyDataSetInvalidated();
-        }
     };
 
     public GroupingListAdapter(Context context) {
@@ -127,15 +124,7 @@
      */
     protected abstract void addGroups(Cursor cursor);
 
-    protected abstract View newStandAloneView(Context context, ViewGroup parent);
-    protected abstract void bindStandAloneView(View view, Context context, Cursor cursor);
-
-    protected abstract View newGroupView(Context context, ViewGroup parent);
-    protected abstract void bindGroupView(View view, Context context, Cursor cursor, int groupSize,
-            boolean expanded);
-
-    protected abstract View newChildView(Context context, ViewGroup parent);
-    protected abstract void bindChildView(View view, Context context, Cursor cursor);
+    protected abstract void onContentChanged();
 
     /**
      * Cache should be reset whenever the cursor changes or groups are expanded or collapsed.
@@ -149,9 +138,6 @@
         mPositionCache.clear();
     }
 
-    protected void onContentChanged() {
-    }
-
     public void changeCursor(Cursor cursor) {
         if (cursor == mCursor) {
             return;
@@ -171,13 +157,10 @@
             cursor.registerDataSetObserver(mDataSetObserver);
             mRowIdColumnIndex = cursor.getColumnIndexOrThrow("_id");
             notifyDataSetChanged();
-        } else {
-            // notify the observers about the lack of a data set
-            notifyDataSetInvalidated();
         }
-
     }
 
+    @NeededForTesting
     public Cursor getCursor() {
         return mCursor;
     }
@@ -231,7 +214,8 @@
         return need;
     }
 
-    public int getCount() {
+    @Override
+    public int getItemCount() {
         if (mCursor == null) {
             return 0;
         }
@@ -343,6 +327,7 @@
             if (position < listPosition) {
                 metadata.itemType = ITEM_TYPE_STANDALONE;
                 metadata.cursorPosition = cursorPosition - (listPosition - position);
+                metadata.childCount = 1;
                 return;
             }
 
@@ -382,6 +367,7 @@
         // The required item is past the last group
         metadata.itemType = ITEM_TYPE_STANDALONE;
         metadata.cursorPosition = cursorPosition + (position - listPosition);
+        metadata.childCount = 1;
     }
 
     /**
@@ -421,12 +407,6 @@
         notifyDataSetChanged();
     }
 
-    @Override
-    public int getViewTypeCount() {
-        return 3;
-    }
-
-    @Override
     public int getItemViewType(int position) {
         obtainPositionMetadata(mPositionMetadata, position);
         return mPositionMetadata.itemType;
@@ -454,37 +434,16 @@
         }
     }
 
-    public View getView(int position, View convertView, ViewGroup parent) {
-        obtainPositionMetadata(mPositionMetadata, position);
-        View view = convertView;
-        if (view == null) {
-            switch (mPositionMetadata.itemType) {
-                case ITEM_TYPE_STANDALONE:
-                    view = newStandAloneView(mContext, parent);
-                    break;
-                case ITEM_TYPE_GROUP_HEADER:
-                    view = newGroupView(mContext, parent);
-                    break;
-                case ITEM_TYPE_IN_GROUP:
-                    view = newChildView(mContext, parent);
-                    break;
-            }
+    /**
+     * Used for setting the cursor without triggering a UI thread update.
+     */
+    @NeededForTesting
+    public void setCursorForTesting(Cursor cursor) {
+        if (cursor != null) {
+            mCursor = cursor;
+            cursor.registerContentObserver(mChangeObserver);
+            cursor.registerDataSetObserver(mDataSetObserver);
+            mRowIdColumnIndex = cursor.getColumnIndexOrThrow("_id");
         }
-
-        mCursor.moveToPosition(mPositionMetadata.cursorPosition);
-        switch (mPositionMetadata.itemType) {
-            case ITEM_TYPE_STANDALONE:
-                bindStandAloneView(view, mContext, mCursor);
-                break;
-            case ITEM_TYPE_GROUP_HEADER:
-                bindGroupView(view, mContext, mCursor, mPositionMetadata.childCount,
-                        mPositionMetadata.isExpanded);
-                break;
-            case ITEM_TYPE_IN_GROUP:
-                bindChildView(view, mContext, mCursor);
-                break;
-
-        }
-        return view;
     }
 }
diff --git a/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java b/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java
index 845e279..bffbe5c 100644
--- a/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java
+++ b/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java
@@ -87,7 +87,8 @@
         mCursor.addRow(createCallLogEntry());
 
         // Bind the views of a single row.
-        mAdapter.bindStandAloneView(mView, getContext(), mCursor);
+        mAdapter.changeCursor(mCursor);
+        mAdapter.onBindViewHolder(CallLogListItemViews.fromView(getContext(), mView), 0);
 
         // There is one request for contact details.
         assertEquals(1, mAdapter.getContactInfoCache().requests.size());
@@ -105,7 +106,8 @@
         mCursor.addRow(createCallLogEntryWithCachedValues());
 
         // Bind the views of a single row.
-        mAdapter.bindStandAloneView(mView, getContext(), mCursor);
+        mAdapter.changeCursor(mCursor);
+        mAdapter.onBindViewHolder(CallLogListItemViews.fromView(getContext(), mView), 0);
 
         // There is one request for contact details.
         assertEquals(1, mAdapter.getContactInfoCache().requests.size());
@@ -123,7 +125,9 @@
         mAdapter.injectContactInfoForTest(TEST_NUMBER, TEST_COUNTRY_ISO, createContactInfo());
 
         // Bind the views of a single row.
-        mAdapter.bindStandAloneView(mView, getContext(), mCursor);
+        mAdapter.changeCursor(mCursor);
+        mAdapter.onBindViewHolder(
+                CallLogListItemViews.fromView(getContext(), mView), 0);
 
         // There is one request for contact details.
         assertEquals(1, mAdapter.getContactInfoCache().requests.size());
@@ -138,7 +142,8 @@
         mAdapter.injectContactInfoForTest(TEST_NUMBER, TEST_COUNTRY_ISO, createContactInfo());
 
         // Bind the views of a single row.
-        mAdapter.bindStandAloneView(mView, getContext(), mCursor);
+        mAdapter.changeCursor(mCursor);
+        mAdapter.onBindViewHolder(CallLogListItemViews.fromView(getContext(), mView), 0);
 
         // Cache and call log are up-to-date: no need to request update.
         assertEquals(0, mAdapter.getContactInfoCache().requests.size());
@@ -153,7 +158,8 @@
         mAdapter.injectContactInfoForTest(TEST_NUMBER, TEST_COUNTRY_ISO, info);
 
         // Bind the views of a single row.
-        mAdapter.bindStandAloneView(mView, getContext(), mCursor);
+        mAdapter.changeCursor(mCursor);
+        mAdapter.onBindViewHolder(CallLogListItemViews.fromView(getContext(), mView), 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 b57489d..fe14f87 100644
--- a/tests/src/com/android/dialer/calllog/CallLogFragmentTest.java
+++ b/tests/src/com/android/dialer/calllog/CallLogFragmentTest.java
@@ -30,6 +30,7 @@
 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,9 +95,9 @@
 
     // An item in the call list. All the methods performing checks use it.
     private CallLogListItemViews mItem;
-    // The list of views representing the data in the DB. View are in
-    // reverse order compare to the DB.
-    private View[] mList;
+
+    // The list of view holderss representing the data in the DB, in reverse order from the DB.
+    private ViewHolder[] mList;
 
     public CallLogFragmentTest() {
         super(FragmentTestActivity.class);
@@ -129,6 +130,7 @@
         mAdapter.pauseCache();
         mParentView = new FrameLayout(mActivity);
         mCursor = new MatrixCursor(CallLogQuery._PROJECTION);
+        mAdapter.setCursorForTesting(mCursor);
     }
 
     /**
@@ -140,7 +142,7 @@
     @MediumTest
     public void testCallViewIsNotVisibleForPrivateAndUnknownNumbers() {
         final int SIZE = 100;
-        mList = new View[SIZE];
+        mList = new ViewHolder[SIZE];
 
         // Insert the first batch of entries.
         mCursor.moveToFirst();
@@ -168,34 +170,34 @@
         insertPrivate(NOW, 0);
         insertPrivate(NOW, 0);
         insertPrivate(NOW, 0);
-        View view = mAdapter.newGroupView(getActivity(), mParentView);
-        mAdapter.bindGroupView(view, getActivity(), mCursor, 3, false);
+        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
+        mAdapter.onBindViewHolder(viewHolder, /* position */ 0);
     }
 
     @MediumTest
     public void testCallAndGroupViews_StandAloneView() {
         mCursor.moveToFirst();
         insertPrivate(NOW, 0);
-        View view = mAdapter.newStandAloneView(getActivity(), mParentView);
-        bindViewForTest(view, mCursor);
+        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, 0);
+        bindViewForTest(viewHolder);
     }
 
     @MediumTest
     public void testCallAndGroupViews_ChildView() {
         mCursor.moveToFirst();
         insertPrivate(NOW, 0);
-        View view = mAdapter.newChildView(getActivity(), mParentView);
-        mAdapter.bindChildView(view, getActivity(), mCursor);
+        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
+        mAdapter.onBindViewHolder(viewHolder, /* position */ 0);
     }
 
     @MediumTest
     public void testBindView_NumberOnlyNoCache() {
         mCursor.moveToFirst();
         insert(TEST_NUMBER, Calls.PRESENTATION_ALLOWED, NOW, 0, Calls.INCOMING_TYPE);
-        View view = mAdapter.newStandAloneView(getActivity(), mParentView);
-        bindViewForTest(view, mCursor);
+        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
+        bindViewForTest(viewHolder);
 
-        CallLogListItemViews views = (CallLogListItemViews) view.getTag();
+        CallLogListItemViews views = (CallLogListItemViews) viewHolder;
         assertNameIs(views, TEST_NUMBER);
     }
 
@@ -206,10 +208,10 @@
                 Calls.PRESENTATION_ALLOWED, NOW, 0, Calls.INCOMING_TYPE);
         values[CallLogQuery.CACHED_FORMATTED_NUMBER] = TEST_FORMATTED_NUMBER;
         insertValues(values);
-        View view = mAdapter.newStandAloneView(getActivity(), mParentView);
-        bindViewForTest(view, mCursor);
+        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
+        bindViewForTest(viewHolder);
 
-        CallLogListItemViews views = (CallLogListItemViews) view.getTag();
+        CallLogListItemViews views = (CallLogListItemViews) viewHolder;
         assertNameIs(views, TEST_FORMATTED_NUMBER);
     }
 
@@ -220,10 +222,10 @@
         // {@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);
-        View view = mAdapter.newStandAloneView(getActivity(), mParentView);
-        bindViewForTest(view, mCursor);
+        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
+        bindViewForTest(viewHolder);
 
-        CallLogListItemViews views = (CallLogListItemViews) view.getTag();
+        CallLogListItemViews views = (CallLogListItemViews) viewHolder;
         assertNameIs(views, "John Doe");
         assertLabel(views, TEST_FORMATTED_NUMBER, getTypeLabel(Phone.TYPE_HOME));
     }
@@ -233,10 +235,10 @@
         mCursor.moveToFirst();
         insertWithCachedValues("sip:johndoe@gmail.com", NOW, 0, Calls.INCOMING_TYPE,
                 "John Doe", Phone.TYPE_HOME, TEST_DEFAULT_CUSTOM_LABEL);
-        View view = mAdapter.newStandAloneView(getActivity(), mParentView);
-        bindViewForTest(view, mCursor);
+        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
+        bindViewForTest(viewHolder);
 
-        CallLogListItemViews views = (CallLogListItemViews) view.getTag();
+        CallLogListItemViews views = (CallLogListItemViews) viewHolder;
         assertNameIs(views, "John Doe");
         assertLabel(views, "sip:johndoe@gmail.com", "sip:johndoe@gmail.com");
     }
@@ -248,10 +250,10 @@
         // {@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);
-        View view = mAdapter.newStandAloneView(getActivity(), mParentView);
-        bindViewForTest(view, mCursor);
+        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
+        bindViewForTest(viewHolder);
 
-        CallLogListItemViews views = (CallLogListItemViews) view.getTag();
+        CallLogListItemViews views = (CallLogListItemViews) viewHolder;
         assertNameIs(views, "John Doe");
         assertLabel(views, TEST_FORMATTED_NUMBER, getTypeLabel(Phone.TYPE_HOME));
     }
@@ -263,10 +265,10 @@
         // {@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);
-        View view = mAdapter.newStandAloneView(getActivity(), mParentView);
-        bindViewForTest(view, mCursor);
+        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
+        bindViewForTest(viewHolder);
 
-        CallLogListItemViews views = (CallLogListItemViews) view.getTag();
+        CallLogListItemViews views = (CallLogListItemViews) viewHolder;
         assertNameIs(views, "John Doe");
         assertLabel(views, TEST_FORMATTED_NUMBER, getTypeLabel(Phone.TYPE_WORK));
     }
@@ -277,10 +279,10 @@
         String numberLabel = "My label";
         insertWithCachedValues(TEST_NUMBER, NOW, 0, Calls.INCOMING_TYPE,
                 "John Doe", Phone.TYPE_CUSTOM, numberLabel);
-        View view = mAdapter.newStandAloneView(getActivity(), mParentView);
-        bindViewForTest(view, mCursor);
+        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
+        bindViewForTest(viewHolder);
 
-        CallLogListItemViews views = (CallLogListItemViews) view.getTag();
+        CallLogListItemViews views = (CallLogListItemViews) viewHolder;
         assertNameIs(views, "John Doe");
         assertLabel(views, TEST_FORMATTED_NUMBER, numberLabel);
     }
@@ -290,10 +292,10 @@
         mCursor.moveToFirst();
         insertWithCachedValues(TEST_NUMBER, NOW, 0, Calls.INCOMING_TYPE,
                 "John Doe", Phone.TYPE_HOME, "");
-        View view = mAdapter.newStandAloneView(getActivity(), mParentView);
-        bindViewForTest(view, mCursor);
+        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
+        bindViewForTest(viewHolder);
 
-        CallLogListItemViews views = (CallLogListItemViews) view.getTag();
+        CallLogListItemViews views = (CallLogListItemViews) viewHolder;
         assertTrue(views.quickContactView.isEnabled());
     }
 
@@ -301,10 +303,10 @@
     public void testBindView_WithoutQuickContactBadge() {
         mCursor.moveToFirst();
         insert(TEST_NUMBER, Calls.PRESENTATION_ALLOWED, NOW, 0, Calls.INCOMING_TYPE);
-        View view = mAdapter.newStandAloneView(getActivity(), mParentView);
-        bindViewForTest(view, mCursor);
+        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
+        bindViewForTest(viewHolder);
 
-        CallLogListItemViews views = (CallLogListItemViews) view.getTag();
+        CallLogListItemViews views = (CallLogListItemViews) viewHolder;
         assertFalse(views.quickContactView.isEnabled());
     }
 
@@ -312,10 +314,11 @@
     public void testBindView_CallButton() {
         mCursor.moveToFirst();
         insert(TEST_NUMBER, Calls.PRESENTATION_ALLOWED, NOW, 0, Calls.INCOMING_TYPE);
-        View view = mAdapter.newStandAloneView(getActivity(), mParentView);
-        bindViewForTest(view, mCursor);
+        mAdapter.changeCursor(mCursor);
+        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
+        bindViewForTest(viewHolder);
 
-        CallLogListItemViews views = (CallLogListItemViews) view.getTag();
+        CallLogListItemViews views = (CallLogListItemViews) viewHolder;
 
         // The primaryActionView tag is set in the
         // {@link com.android.dialer.calllog.CallLogAdapter#bindView} method.  If it is possible
@@ -333,10 +336,10 @@
     public void testBindView_PlayButton() {
         mCursor.moveToFirst();
         insertVoicemail(TEST_NUMBER, Calls.PRESENTATION_ALLOWED, NOW, 0);
-        View view = mAdapter.newStandAloneView(getActivity(), mParentView);
-        bindViewForTest(view, mCursor);
+        ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
+        bindViewForTest(viewHolder);
 
-        CallLogListItemViews views = (CallLogListItemViews) view.getTag();
+        CallLogListItemViews views = (CallLogListItemViews) viewHolder;
         IntentProvider intentProvider = (IntentProvider) views.voicemailButtonView.getTag();
         Intent intent = intentProvider.getIntent(mActivity);
         // Starts the call detail activity.
@@ -372,7 +375,7 @@
             if (null == mList[i]) {
                 break;
             }
-            mItem = (CallLogListItemViews) mList[i].getTag();
+            mItem = (CallLogListItemViews) mList[i];
             int presentation = getPhoneNumberPresentationForListEntry(i);
             if (presentation == Calls.PRESENTATION_RESTRICTED ||
                     presentation == Calls.PRESENTATION_UNKNOWN) {
@@ -420,11 +423,12 @@
     private void buildViewListFromDb() {
         int i = 0;
         mCursor.moveToLast();
-        while(!mCursor.isBeforeFirst()) {
+        while (!mCursor.isBeforeFirst()) {
             if (null == mList[i]) {
-                mList[i] = mAdapter.newStandAloneView(mActivity, mParentView);
+                mList[i] = mAdapter.onCreateViewHolder(mParentView, /* itemType */ 0);
             }
-            bindViewForTest(mList[i], mCursor);
+            // Bind to the proper position, despite iterating in reverse.
+            bindViewForTest(mList[i], mCursor.getCount() - i - 1);
             mCursor.moveToPrevious();
             i++;
         }
@@ -446,12 +450,15 @@
      * unit tests can access the buttons contained within.
      *
      * @param view The current call log row.
-     * @param cursor The cursor to bind from.
+     * @param position The position of hte item.
      */
-    private void bindViewForTest(View view, MatrixCursor cursor) {
-        mAdapter.bindView(view, cursor, /* count */ 1);
-        CallLogListItemViews views = (CallLogListItemViews) view.getTag();
-        mAdapter.expandItem(views, /* expand */ true);
+    private void bindViewForTest(ViewHolder viewHolder, int position) {
+        mAdapter.onBindViewHolder(viewHolder, position);
+        mAdapter.expandItem((CallLogListItemViews) viewHolder, /* expand */ true);
+    }
+
+    private void bindViewForTest(ViewHolder viewHolder) {
+        bindViewForTest(viewHolder, /* position */ 0);
     }
 
     /**
diff --git a/tests/src/com/android/dialer/calllog/GroupingListAdapterTests.java b/tests/src/com/android/dialer/calllog/GroupingListAdapterTests.java
index 3eb5f06..53583e0 100644
--- a/tests/src/com/android/dialer/calllog/GroupingListAdapterTests.java
+++ b/tests/src/com/android/dialer/calllog/GroupingListAdapterTests.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.database.Cursor;
 import android.database.MatrixCursor;
+import android.support.v7.widget.RecyclerView;
 import android.test.AndroidTestCase;
 import android.text.TextUtils;
 import android.view.View;
@@ -34,7 +35,7 @@
  * Running all tests:
  *
  *   adb shell am instrument -e class com.android.dialer.calllog.GroupingListAdapterTests \
- *     -w com.google.android.dialer.tests/android.test.InstrumentationTestRunner
+ *     -w com.android.dialer.tests/android.test.InstrumentationTestRunner
  */
 public class GroupingListAdapterTests extends AndroidTestCase {
 
@@ -76,34 +77,22 @@
         }
 
         @Override
-        protected void bindChildView(View view, Context context, Cursor cursor) {
+        public void onContentChanged() {
+            // Do nothing.
         }
 
         @Override
-        protected void bindGroupView(View view, Context context, Cursor cursor, int groupSize,
-                boolean expanded) {
-        }
-
-        @Override
-        protected void bindStandAloneView(View view, Context context, Cursor cursor) {
-        }
-
-        @Override
-        protected View newChildView(Context context, ViewGroup parent) {
+        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int position) {
             return null;
         }
 
         @Override
-        protected View newGroupView(Context context, ViewGroup parent) {
-            return null;
-        }
-
-        @Override
-        protected View newStandAloneView(Context context, ViewGroup parent) {
-            return null;
+        public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
+            // Do nothing.
         }
     };
 
+
     private void buildCursor(String... numbers) {
         mCursor = new MatrixCursor(PROJECTION);
         mNextId = 1;
@@ -117,7 +106,7 @@
         buildCursor("1", "2", "3");
         mAdapter.changeCursor(mCursor);
 
-        assertEquals(3, mAdapter.getCount());
+        assertEquals(3, mAdapter.getItemCount());
         assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0);
         assertPositionMetadata(1, ITEM_TYPE_STANDALONE, false, 1);
         assertPositionMetadata(2, ITEM_TYPE_STANDALONE, false, 2);
@@ -127,7 +116,7 @@
         buildCursor("1", "1", "2");
         mAdapter.changeCursor(mCursor);
 
-        assertEquals(2, mAdapter.getCount());
+        assertEquals(2, mAdapter.getItemCount());
         assertPositionMetadata(0, ITEM_TYPE_GROUP_HEADER, false, 0);
         assertPositionMetadata(1, ITEM_TYPE_STANDALONE, false, 2);
     }
@@ -137,7 +126,7 @@
         mAdapter.changeCursor(mCursor);
         mAdapter.toggleGroup(0);
 
-        assertEquals(4, mAdapter.getCount());
+        assertEquals(4, mAdapter.getItemCount());
         assertPositionMetadata(0, ITEM_TYPE_GROUP_HEADER, true, 0);
         assertPositionMetadata(1, ITEM_TYPE_IN_GROUP, false, 0);
         assertPositionMetadata(2, ITEM_TYPE_IN_GROUP, false, 1);
@@ -150,7 +139,7 @@
         mAdapter.toggleGroup(0);
         mAdapter.toggleGroup(0);
 
-        assertEquals(2, mAdapter.getCount());
+        assertEquals(2, mAdapter.getItemCount());
         assertPositionMetadata(0, ITEM_TYPE_GROUP_HEADER, false, 0);
         assertPositionMetadata(1, ITEM_TYPE_STANDALONE, false, 2);
     }
@@ -159,7 +148,7 @@
         buildCursor("1", "2", "2", "2", "3");
         mAdapter.changeCursor(mCursor);
 
-        assertEquals(3, mAdapter.getCount());
+        assertEquals(3, mAdapter.getItemCount());
         assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0);
         assertPositionMetadata(1, ITEM_TYPE_GROUP_HEADER, false, 1);
         assertPositionMetadata(2, ITEM_TYPE_STANDALONE, false, 4);
@@ -170,7 +159,7 @@
         mAdapter.changeCursor(mCursor);
         mAdapter.toggleGroup(1);
 
-        assertEquals(6, mAdapter.getCount());
+        assertEquals(6, mAdapter.getItemCount());
         assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0);
         assertPositionMetadata(1, ITEM_TYPE_GROUP_HEADER, true, 1);
         assertPositionMetadata(2, ITEM_TYPE_IN_GROUP, false, 1);
@@ -183,7 +172,7 @@
         buildCursor("1", "2", "3", "3", "3");
         mAdapter.changeCursor(mCursor);
 
-        assertEquals(3, mAdapter.getCount());
+        assertEquals(3, mAdapter.getItemCount());
         assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0);
         assertPositionMetadata(1, ITEM_TYPE_STANDALONE, false, 1);
         assertPositionMetadata(2, ITEM_TYPE_GROUP_HEADER, false, 2);
@@ -194,7 +183,7 @@
         mAdapter.changeCursor(mCursor);
         mAdapter.toggleGroup(2);
 
-        assertEquals(6, mAdapter.getCount());
+        assertEquals(6, mAdapter.getItemCount());
         assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0);
         assertPositionMetadata(1, ITEM_TYPE_STANDALONE, false, 1);
         assertPositionMetadata(2, ITEM_TYPE_GROUP_HEADER, true, 2);
@@ -207,7 +196,7 @@
         buildCursor("1", "2", "2", "3", "4", "4", "5", "5", "6");
         mAdapter.changeCursor(mCursor);
 
-        assertEquals(6, mAdapter.getCount());
+        assertEquals(6, mAdapter.getItemCount());
         assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0);
         assertPositionMetadata(1, ITEM_TYPE_GROUP_HEADER, false, 1);
         assertPositionMetadata(2, ITEM_TYPE_STANDALONE, false, 3);
@@ -225,7 +214,7 @@
         // 4th to the 6th position
         mAdapter.toggleGroup(6);
 
-        assertEquals(10, mAdapter.getCount());
+        assertEquals(10, mAdapter.getItemCount());
         assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0);
         assertPositionMetadata(1, ITEM_TYPE_GROUP_HEADER, true, 1);
         assertPositionMetadata(2, ITEM_TYPE_IN_GROUP, false, 1);
@@ -243,7 +232,7 @@
         mAdapter.changeCursor(mCursor);
 
         // First pass - building up cache
-        assertEquals(6, mAdapter.getCount());
+        assertEquals(6, mAdapter.getItemCount());
         assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0);
         assertPositionMetadata(1, ITEM_TYPE_GROUP_HEADER, false, 1);
         assertPositionMetadata(2, ITEM_TYPE_STANDALONE, false, 3);
@@ -252,7 +241,7 @@
         assertPositionMetadata(5, ITEM_TYPE_STANDALONE, false, 8);
 
         // Second pass - using cache
-        assertEquals(6, mAdapter.getCount());
+        assertEquals(6, mAdapter.getItemCount());
         assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0);
         assertPositionMetadata(1, ITEM_TYPE_GROUP_HEADER, false, 1);
         assertPositionMetadata(2, ITEM_TYPE_STANDALONE, false, 3);
@@ -295,7 +284,7 @@
         buildCursor(numbers);
         mAdapter.changeCursor(mCursor);
 
-        assertEquals(250, mAdapter.getCount());
+        assertEquals(250, mAdapter.getItemCount());
     }
 
     private void assertPositionMetadata(int position, int itemType, boolean isExpanded,