am 90ea1491: am 7e4e56f0: am 3ce60186: Switch favorites screen to grid layout

* commit '90ea149179f4208711012b4e768d01307f4e0666':
  Switch favorites screen to grid layout
diff --git a/res/drawable-hdpi/ic_contact_info.png b/res/drawable-hdpi/ic_contact_info.png
deleted file mode 100644
index 9c23000..0000000
--- a/res/drawable-hdpi/ic_contact_info.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_star_marked_as_fav.png b/res/drawable-hdpi/ic_star_marked_as_fav.png
deleted file mode 100644
index 8a138c4..0000000
--- a/res/drawable-hdpi/ic_star_marked_as_fav.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/overflow_thumbnail.png b/res/drawable-hdpi/overflow_thumbnail.png
new file mode 100644
index 0000000..57db353
--- /dev/null
+++ b/res/drawable-hdpi/overflow_thumbnail.png
Binary files differ
diff --git a/res/drawable-hdpi/star_thumbnail.png b/res/drawable-hdpi/star_thumbnail.png
new file mode 100644
index 0000000..1d4d5e1
--- /dev/null
+++ b/res/drawable-hdpi/star_thumbnail.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_contact_info.png b/res/drawable-mdpi/ic_contact_info.png
deleted file mode 100644
index 5d35ec5..0000000
--- a/res/drawable-mdpi/ic_contact_info.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_star_marked_as_fav.png b/res/drawable-mdpi/ic_star_marked_as_fav.png
deleted file mode 100644
index ee1b5ec..0000000
--- a/res/drawable-mdpi/ic_star_marked_as_fav.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/overflow_thumbnail.png b/res/drawable-mdpi/overflow_thumbnail.png
new file mode 100644
index 0000000..c699374
--- /dev/null
+++ b/res/drawable-mdpi/overflow_thumbnail.png
Binary files differ
diff --git a/res/drawable-mdpi/star_thumbnail.png b/res/drawable-mdpi/star_thumbnail.png
new file mode 100644
index 0000000..7b96272
--- /dev/null
+++ b/res/drawable-mdpi/star_thumbnail.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_contact_info.png b/res/drawable-xhdpi/ic_contact_info.png
deleted file mode 100644
index 88d367b..0000000
--- a/res/drawable-xhdpi/ic_contact_info.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_star_marked_as_fav.png b/res/drawable-xhdpi/ic_star_marked_as_fav.png
deleted file mode 100644
index 372747a..0000000
--- a/res/drawable-xhdpi/ic_star_marked_as_fav.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/overflow_thumbnail.png b/res/drawable-xhdpi/overflow_thumbnail.png
new file mode 100644
index 0000000..e538b98
--- /dev/null
+++ b/res/drawable-xhdpi/overflow_thumbnail.png
Binary files differ
diff --git a/res/drawable-xhdpi/star_thumbnail.png b/res/drawable-xhdpi/star_thumbnail.png
new file mode 100644
index 0000000..a71262f
--- /dev/null
+++ b/res/drawable-xhdpi/star_thumbnail.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_contact_info.png b/res/drawable-xxhdpi/ic_contact_info.png
deleted file mode 100644
index e5d2939..0000000
--- a/res/drawable-xxhdpi/ic_contact_info.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_star_marked_as_fav.png b/res/drawable-xxhdpi/ic_star_marked_as_fav.png
deleted file mode 100644
index 3eeff4c..0000000
--- a/res/drawable-xxhdpi/ic_star_marked_as_fav.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/overflow_thumbnail.png b/res/drawable-xxhdpi/overflow_thumbnail.png
new file mode 100644
index 0000000..7f3f733
--- /dev/null
+++ b/res/drawable-xxhdpi/overflow_thumbnail.png
Binary files differ
diff --git a/res/drawable-xxhdpi/star_thumbnail.png b/res/drawable-xxhdpi/star_thumbnail.png
new file mode 100644
index 0000000..5f13fec
--- /dev/null
+++ b/res/drawable-xxhdpi/star_thumbnail.png
Binary files differ
diff --git a/res/layout/phone_favorite_regular_row_view.xml b/res/layout/phone_favorite_regular_row_view.xml
index 012c9be..0d131f6 100644
--- a/res/layout/phone_favorite_regular_row_view.xml
+++ b/res/layout/phone_favorite_regular_row_view.xml
@@ -75,7 +75,7 @@
             android:layout_marginRight="7dip"
             android:layout_marginEnd="7dip"
             android:layout_marginBottom="7dip"
-            android:src="@drawable/ic_star_marked_as_fav"
+            android:src="@drawable/star_thumbnail"
             android:visibility="gone" />
 
     </RelativeLayout>
diff --git a/res/layout/phone_favorite_tile_view.xml b/res/layout/phone_favorite_tile_view.xml
index 8806d39..c4ad780 100644
--- a/res/layout/phone_favorite_tile_view.xml
+++ b/res/layout/phone_favorite_tile_view.xml
@@ -46,7 +46,7 @@
             android:paddingRight="@dimen/contact_tile_info_button_height_and_width"
             android:paddingStart="8dp"
             android:paddingEnd="@dimen/contact_tile_info_button_height_and_width"
-            android:paddingBottom="4dp"
+            android:paddingBottom="12dp"
             android:layout_alignParentBottom="true"
             android:orientation="vertical" >
             <TextView
@@ -57,7 +57,7 @@
                 android:textColor="@color/contact_tile_name_color"
                 android:fontFamily="sans-serif"
                 android:singleLine="true"
-                android:textSize="16sp"
+                android:textSize="15sp"
                 android:fadingEdge="horizontal"
                 android:fadingEdgeLength="3dip"
                 android:ellipsize="marquee"
@@ -70,7 +70,7 @@
                 android:textColor="@color/contact_tile_name_color"
                 android:fontFamily="sans-serif"
                 android:singleLine="true"
-                android:textSize="12sp"
+                android:textSize="11sp"
                 android:paddingBottom="2dp"
                 android:fadingEdge="horizontal"
                 android:fadingEdgeLength="3dip"
@@ -90,35 +90,37 @@
             android:background="?android:attr/selectableItemBackground"
             android:layout_height="@dimen/contact_tile_info_button_height_and_width"
             android:layout_width="@dimen/contact_tile_info_button_height_and_width"
-            android:paddingLeft="8dp"
-            android:paddingRight="8dp"
-            android:paddingStart="8dp"
-            android:paddingEnd="8dp"
-            android:paddingTop="8dp"
-            android:paddingBottom="8dp"
-            android:layout_alignParentBottom="true"
+            android:paddingLeft="2dp"
+            android:paddingRight="2dp"
+            android:paddingStart="2dp"
+            android:paddingEnd="2dp"
+            android:paddingTop="2dp"
+            android:paddingBottom="2dp"
+            android:layout_alignParentTop="true"
             android:layout_alignParentRight="true"
             android:layout_alignParentEnd="true"
-            android:src="@drawable/ic_star_marked_as_fav"
+            android:src="@drawable/star_thumbnail"
             android:scaleType="center"
+            android:contentDescription="@string/description_view_contact_detail"
             android:visibility="gone" />
 
 
         <ImageButton
             android:id="@id/contact_tile_secondary_button"
-            android:src="@drawable/ic_contact_info"
+            android:src="@drawable/overflow_thumbnail"
             android:background="?android:attr/selectableItemBackground"
             android:layout_height="@dimen/contact_tile_info_button_height_and_width"
             android:layout_width="@dimen/contact_tile_info_button_height_and_width"
-            android:paddingLeft="8dp"
-            android:paddingRight="8dp"
-            android:paddingStart="8dp"
-            android:paddingEnd="8dp"
-            android:paddingTop="8dp"
-            android:paddingBottom="8dp"
-            android:layout_alignParentBottom="true"
+            android:paddingLeft="4dp"
+            android:paddingRight="4dp"
+            android:paddingStart="4dp"
+            android:paddingEnd="4dp"
+            android:paddingTop="4dp"
+            android:paddingBottom="4dp"
+            android:layout_alignParentTop="true"
             android:layout_alignParentRight="true"
             android:layout_alignParentEnd="true"
+            android:scaleType="center"
             android:contentDescription="@string/description_view_contact_detail" />
 
     </RelativeLayout>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index a8ddf2b..b2d4bc5 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -63,7 +63,7 @@
     <color name="searchbox_text_color">#d3d3d3</color>
 
     <!-- Color of the contact name in favorite tiles -->
-    <color name="contact_tile_name_color">#f0f0f0</color>
+    <color name="contact_tile_name_color">#ffffff</color>
 
     <!-- Undo dialogue color -->
     <color name="undo_dialogue_text_color">#4d4d4d</color>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 1743952..53d9c47 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -63,10 +63,11 @@
     <dimen name="fake_menu_button_min_width">56dp</dimen>
 
     <!--  Favorites tile and recent call log padding -->
-    <dimen name="contact_tile_divider_padding">3dp</dimen>
+    <dimen name="contact_tile_divider_width">12dp</dimen>
     <dimen name="contact_tile_info_button_height_and_width">36dp</dimen>
-    <dimen name="favorites_row_top_padding">8dp</dimen>
-    <dimen name="favorites_row_bottom_padding">8dp</dimen>
+    <item name="contact_tile_height_to_width_ratio" type="dimen">67%</item>
+    <dimen name="favorites_row_top_padding">6dp</dimen>
+    <dimen name="favorites_row_bottom_padding">6dp</dimen>
     <dimen name="favorites_row_start_padding">8dp</dimen>
     <dimen name="favorites_row_end_padding">8dp</dimen>
     <dimen name="favorites_row_undo_text_side_padding">32dp</dimen>
diff --git a/src/com/android/dialer/list/PhoneFavoriteFragment.java b/src/com/android/dialer/list/PhoneFavoriteFragment.java
index 81d9bfd..efc659f 100644
--- a/src/com/android/dialer/list/PhoneFavoriteFragment.java
+++ b/src/com/android/dialer/list/PhoneFavoriteFragment.java
@@ -17,9 +17,7 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorSet;
-import android.animation.ArgbEvaluator;
 import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
 import android.app.Activity;
 import android.app.Fragment;
 import android.app.LoaderManager;
@@ -36,9 +34,9 @@
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.view.ViewTreeObserver;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
 import android.widget.AbsListView;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
@@ -55,10 +53,10 @@
 import com.android.contacts.common.list.ContactTileView;
 import com.android.dialer.DialtactsActivity;
 import com.android.dialer.R;
-import com.android.dialer.calllog.CallLogQuery;
-import com.android.dialer.calllog.ContactInfoHelper;
 import com.android.dialer.calllog.CallLogAdapter;
+import com.android.dialer.calllog.CallLogQuery;
 import com.android.dialer.calllog.CallLogQueryHandler;
+import com.android.dialer.calllog.ContactInfoHelper;
 import com.android.dialer.list.PhoneFavoritesTileAdapter.ContactTileRow;
 import com.android.dialerbind.ObjectFactory;
 
@@ -238,8 +236,8 @@
         // that will be available on onCreateView().
         mContactTileAdapter = new PhoneFavoritesTileAdapter(activity, mContactTileAdapterListener,
                 this,
-                getResources().getInteger(R.integer.contact_tile_column_count_in_favorites_new),
-                1);
+                getResources().getInteger(R.integer.contact_tile_column_count_in_favorites),
+                PhoneFavoritesTileAdapter.NO_ROW_LIMIT);
         mContactTileAdapter.setPhotoLoader(ContactPhotoManager.getInstance(activity));
     }
 
@@ -424,7 +422,10 @@
     }
 
     /**
-     * Saves the current view offsets into memory
+     * Cache the current view offsets into memory. Once a relayout of views in the ListView
+     * has happened due to a dataset change, the cached offsets are used to create animations
+     * that slide views from their previous positions to their new ones, to give the appearance
+     * that the views are sliding into their new positions.
      */
     @SuppressWarnings("unchecked")
     private void saveOffsets(int removedItemHeight) {
@@ -440,7 +441,7 @@
             if (itemViewType == PhoneFavoritesTileAdapter.ViewTypes.TOP) {
                 // This is a tiled row, so save horizontal offsets instead
                 saveHorizontalOffsets((ContactTileRow) child, (ArrayList<ContactEntry>)
-                        mAdapter.getItem(position));
+                        mAdapter.getItem(position), position);
             }
             if (DEBUG) {
                 Log.d(TAG, "Saving itemId: " + itemId + " for listview child " + i + " Top: "
@@ -452,7 +453,13 @@
         mItemIdTopMap.put(KEY_REMOVED_ITEM_HEIGHT, removedItemHeight);
     }
 
-    private void saveHorizontalOffsets(ContactTileRow row, ArrayList<ContactEntry> list) {
+    /**
+     * Saves the horizontal offsets for contacts that are displayed as tiles in a row. Saving
+     * these offsets allow us to animate tiles sliding left and right within the same row.
+     * See {@link #saveOffsets(int removedItemHeight)}
+     */
+    private void saveHorizontalOffsets(ContactTileRow row, ArrayList<ContactEntry> list,
+            int currentRowIndex) {
         for (int i = 0; i < list.size() && i < row.getChildCount(); i++) {
             final View child = row.getChildAt(i);
             if (child == null) {
@@ -464,6 +471,7 @@
                 Log.d(TAG, "Saving itemId: " + itemId + " for tileview child " + i + " Left: "
                         + child.getTop());
             }
+            mItemIdTopMap.put(itemId, currentRowIndex);
             mItemIdLeftMap.put(itemId, child.getLeft());
         }
     }
@@ -472,7 +480,7 @@
      * Performs a animations for a row of tiles
      */
     private void performHorizontalAnimations(ContactTileRow row, ArrayList<ContactEntry> list,
-            long[] idsInPlace) {
+            long[] idsInPlace, int currentRow) {
         if (mItemIdLeftMap.isEmpty()) {
             return;
         }
@@ -490,6 +498,26 @@
             } else {
                 Integer startLeft = mItemIdLeftMap.get(itemId);
                 int left = child.getLeft();
+
+                Integer startRow = mItemIdTopMap.get(itemId);
+
+                if (startRow != null) {
+                    if (startRow > currentRow) {
+                        // Item has shifted upwards to the previous row.
+                        // It should now animate in from right to left.
+                        startLeft = left + child.getWidth();
+                    } else if (startRow < currentRow) {
+                        // Item has shifted downwards to the next row.
+                        // It should now animate in from left to right.
+                        startLeft = left - child.getWidth();
+                    }
+
+                    // If the item hasn't shifted rows (startRow == currentRow), it either remains
+                    // in the same position or has shifted left or right within its current row.
+                    // Either way, startLeft has already been correctly saved and retrieved from
+                    // mItemIdTopMap.
+                }
+
                 if (startLeft != null) {
                     if (startLeft != left) {
                         int delta = startLeft - left;
@@ -545,7 +573,8 @@
                             child instanceof ContactTileRow) {
                         // This is a tiled row, so perform horizontal animations instead
                         performHorizontalAnimations((ContactTileRow) child, (
-                                ArrayList<ContactEntry>) mAdapter.getItem(position), idsInPlace);
+                                ArrayList<ContactEntry>) mAdapter.getItem(position), idsInPlace,
+                                position);
                     }
 
                     final long itemId = mAdapter.getItemId(position);
diff --git a/src/com/android/dialer/list/PhoneFavoriteSquareTileView.java b/src/com/android/dialer/list/PhoneFavoriteSquareTileView.java
index 85e7216..e855c88 100644
--- a/src/com/android/dialer/list/PhoneFavoriteSquareTileView.java
+++ b/src/com/android/dialer/list/PhoneFavoriteSquareTileView.java
@@ -36,10 +36,6 @@
     private static final String TAG = PhoneFavoriteSquareTileView.class.getSimpleName();
     private ImageButton mSecondaryButton;
 
-    // TODO: Use a more expansive name token separator if needed. For now it should be fine to
-    // not split by dashes, underscore etc.
-    private static final Pattern NAME_TOKEN_SEPARATOR_PATTERN = Pattern.compile("\\s+");
-
     public PhoneFavoriteSquareTileView(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
@@ -63,14 +59,6 @@
     }
 
     @Override
-    protected String getNameForView(String name) {
-        if (TextUtils.isEmpty(name)) return name;
-        final String[] tokens = NAME_TOKEN_SEPARATOR_PATTERN.split(name, 2);
-        if (tokens.length < 1) return name;
-        return tokens[0];
-    }
-
-    @Override
     public void loadFromContact(ContactEntry entry) {
         super.loadFromContact(entry);
         if (entry != null) {
diff --git a/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java b/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java
index a85fc6a..dff68b2 100644
--- a/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java
+++ b/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java
@@ -15,7 +15,9 @@
  */
 package com.android.dialer.list;
 
-import android.animation.ObjectAnimator;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ComparisonChain;
+
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
@@ -44,9 +46,6 @@
 import com.android.dialer.list.SwipeHelper.OnItemGestureListener;
 import com.android.dialer.list.SwipeHelper.SwipeHelperCallback;
 
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ComparisonChain;
-
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.LinkedList;
@@ -64,7 +63,9 @@
     private static final String TAG = PhoneFavoritesTileAdapter.class.getSimpleName();
     private static final boolean DEBUG = false;
 
-    public static final int ROW_LIMIT_DEFAULT = 1;
+    public static final int NO_ROW_LIMIT = -1;
+
+    public static final int ROW_LIMIT_DEFAULT = NO_ROW_LIMIT;
 
     private ContactTileView.Listener mListener;
     private OnDataSetChangedForAnimationListener mDataSetChangedListener;
@@ -155,7 +156,7 @@
         mContactEntries = new ArrayList<ContactEntry>();
         // Converting padding in dips to padding in pixels
         mPaddingInPixels = mContext.getResources()
-                .getDimensionPixelSize(R.dimen.contact_tile_divider_padding);
+                .getDimensionPixelSize(R.dimen.contact_tile_divider_width);
 
         bindColumnIndices();
     }
@@ -386,18 +387,24 @@
     protected int getRowCount(int entryCount) {
         if (entryCount == 0) return 0;
         final int nonLimitedRows = ((entryCount - 1) / mColumnCount) + 1;
+        if (mMaxTiledRows == NO_ROW_LIMIT) {
+            return nonLimitedRows;
+        }
         return Math.min(mMaxTiledRows, nonLimitedRows);
     }
 
     private int getMaxContactsInTiles() {
+        if (mMaxTiledRows == NO_ROW_LIMIT) {
+            return Integer.MAX_VALUE;
+        }
         return mColumnCount * mMaxTiledRows;
     }
 
     public int getRowIndex(int entryIndex) {
-        if (entryIndex < mMaxTiledRows * mColumnCount) {
+        if (entryIndex < getMaxContactsInTiles()) {
             return entryIndex / mColumnCount;
         } else {
-            return entryIndex - mMaxTiledRows * mColumnCount + mMaxTiledRows;
+            return entryIndex - mMaxTiledRows * (mColumnCount + 1);
         }
     }
 
@@ -467,9 +474,13 @@
     }
 
     /**
-     * Calculates the stable itemId for a particular entry based on its contactID
+     * Calculates the stable itemId for a particular entry based on the entry's contact ID. This
+     * stable itemId is used for animation purposes.
      */
     public long getAdjustedItemId(long id) {
+        if (mMaxTiledRows == NO_ROW_LIMIT) {
+            return id;
+        }
         return mMaxTiledRows + id;
     }
 
@@ -479,7 +490,6 @@
     }
 
     @Override
-
     public boolean areAllItemsEnabled() {
         // No dividers, so all items are enabled.
         return true;
@@ -541,7 +551,7 @@
 
     @Override
     public int getItemViewType(int position) {
-        if (position < getRowCount(getMaxContactsInTiles())) {
+        if (position < getMaxContactsInTiles()) {
             return ViewTypes.TOP;
         } else {
             return ViewTypes.FREQUENT;
@@ -700,6 +710,7 @@
         private final int mRowPaddingEnd;
         private final int mRowPaddingTop;
         private final int mRowPaddingBottom;
+        private final float mHeightToWidthRatio;
         private int mPosition;
         private SwipeHelper mSwipeHelper;
         private OnItemGestureListener mOnItemSwipeListener;
@@ -712,6 +723,9 @@
 
             final Resources resources = mContext.getResources();
 
+            mHeightToWidthRatio = getResources().getFraction(
+                    R.dimen.contact_tile_height_to_width_ratio, 1, 1);
+
             if (mItemViewType == ViewTypes.TOP) {
                 // For tiled views, we still want padding to be set on the ContactTileRow.
                 // Otherwise the padding would be set around each of the tiles, which we don't want
@@ -723,8 +737,6 @@
                         R.dimen.favorites_row_start_padding);
                 mRowPaddingEnd = resources.getDimensionPixelSize(
                         R.dimen.favorites_row_end_padding);
-
-                setBackgroundResource(R.drawable.bottom_border_background);
             } else {
                 // For row views, padding is set on the view itself.
                 mRowPaddingTop = 0;
@@ -894,21 +906,22 @@
 
             // Preferred width / height for images (excluding the padding).
             // The actual width may be 1 pixel larger than this if we have a remainder.
-            final int imageSize = (width - totalPaddingsInPixels) / mColumnCount;
-            final int remainder = width - (imageSize * mColumnCount) - totalPaddingsInPixels;
+            final int imageWidth = (width - totalPaddingsInPixels) / mColumnCount;
+            final int remainder = width - (imageWidth * mColumnCount) - totalPaddingsInPixels;
+
+            final int height = (int) (mHeightToWidthRatio * imageWidth);
 
             for (int i = 0; i < childCount; i++) {
                 final View child = getChildAt(i);
-                final int childWidth = imageSize + child.getPaddingRight()
+                final int childWidth = imageWidth + child.getPaddingRight()
                         // Compensate for the remainder
                         + (i < remainder ? 1 : 0);
-                final int childHeight = imageSize;
                 child.measure(
                         MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY),
-                        MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY)
+                        MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
                         );
             }
-            setMeasuredDimension(width, imageSize + getPaddingTop() + getPaddingBottom());
+            setMeasuredDimension(width, height + getPaddingTop() + getPaddingBottom());
         }
 
         /**
@@ -919,7 +932,7 @@
          * @return Index of the selected item in the cached array.
          */
         public int getItemIndex(float itemX, float itemY) {
-            if (mPosition < mMaxTiledRows) {
+            if (mMaxTiledRows == NO_ROW_LIMIT || mPosition < mMaxTiledRows) {
                 if (DEBUG) {
                     Log.v(TAG, String.valueOf(itemX) + " " + String.valueOf(itemY));
                 }
diff --git a/tests/src/com/android/dialer/list/PhoneFavoritesTileAdapterTest.java b/tests/src/com/android/dialer/list/PhoneFavoritesTileAdapterTest.java
index 611b3f1..7a2076d 100644
--- a/tests/src/com/android/dialer/list/PhoneFavoritesTileAdapterTest.java
+++ b/tests/src/com/android/dialer/list/PhoneFavoritesTileAdapterTest.java
@@ -1,15 +1,26 @@
 package com.android.dialer.list;
 
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.provider.ContactsContract.PinnedPositions;
 import android.test.AndroidTestCase;
 
+import com.android.contacts.common.ContactTileLoaderFactory;
+import com.android.contacts.common.list.ContactEntry;
+import com.android.dialer.list.PhoneFavoritesTileAdapter.OnDataSetChangedForAnimationListener;
+
+import java.util.ArrayList;
+
 public class PhoneFavoritesTileAdapterTest extends AndroidTestCase {
     private PhoneFavoritesTileAdapter mAdapter;
+    private static final OnDataSetChangedForAnimationListener
+            sOnDataSetChangedForAnimationListener = new OnDataSetChangedForAnimationListener() {
+                @Override
+                public void onDataSetChangedForAnimation(long... idsInPlace) {}
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mAdapter = new PhoneFavoritesTileAdapter(getContext(), null, null, 3, 1);
-    }
+                @Override
+                public void cacheOffsetsForDatasetChange() {}
+            };
 
     /**
      * TODO: Add tests
@@ -42,5 +53,124 @@
 
     }
 
+    public void testGetRowIndex_NoRowLimit() {
+        mAdapter = getAdapterForTest(2, PhoneFavoritesTileAdapter.NO_ROW_LIMIT);
+        assertEquals(0, mAdapter.getRowCount(0));
+        assertEquals(1, mAdapter.getRowCount(1));
+        assertEquals(1, mAdapter.getRowCount(2));
+        assertEquals(2, mAdapter.getRowCount(4));
+        assertEquals(4, mAdapter.getRowCount(7));
+        assertEquals(100, mAdapter.getRowCount(199));
 
+        mAdapter = getAdapterForTest(5, PhoneFavoritesTileAdapter.NO_ROW_LIMIT);
+        assertEquals(0, mAdapter.getRowCount(0));
+        assertEquals(1, mAdapter.getRowCount(1));
+        assertEquals(1, mAdapter.getRowCount(3));
+        assertEquals(1, mAdapter.getRowCount(5));
+        assertEquals(2, mAdapter.getRowCount(7));
+        assertEquals(2, mAdapter.getRowCount(10));
+        assertEquals(40, mAdapter.getRowCount(199));
+    }
+
+    public void testGetItemId_NoRowLimit() {
+        mAdapter = getAdapterForTest(2, PhoneFavoritesTileAdapter.NO_ROW_LIMIT);
+        assertEquals(0, mAdapter.getItemId(0));
+        assertEquals(1, mAdapter.getItemId(1));
+        assertEquals(5, mAdapter.getItemId(5));
+        assertEquals(10, mAdapter.getItemId(10));
+    }
+
+    public void testGetAdjustedItemId_NoRowLimit() {
+        mAdapter = getAdapterForTest(2, PhoneFavoritesTileAdapter.NO_ROW_LIMIT);
+        assertEquals(0, mAdapter.getAdjustedItemId(0));
+        assertEquals(1, mAdapter.getAdjustedItemId(1));
+        assertEquals(5, mAdapter.getAdjustedItemId(5));
+        assertEquals(10, mAdapter.getAdjustedItemId(10));
+    }
+
+    public void testGetItem_NoRowLimit() {
+        mAdapter = getAdapterForTest(2, PhoneFavoritesTileAdapter.NO_ROW_LIMIT);
+        mAdapter.setContactCursor(getCursorForTest(5, 5));
+
+        final ArrayList<ContactEntry> row1 = new ArrayList<ContactEntry> ();
+        row1.add(getTestContactEntry(0, true));
+        row1.add(getTestContactEntry(1, true));
+        assertContactEntryRowsEqual(row1, mAdapter.getItem(0));
+
+        final ArrayList<ContactEntry> row3 = new ArrayList<ContactEntry> ();
+        row3.add(getTestContactEntry(4, true));
+        row3.add(getTestContactEntry(5, false));
+        assertContactEntryRowsEqual(row3, mAdapter.getItem(2));
+
+        final ArrayList<ContactEntry> row5 = new ArrayList<ContactEntry> ();
+        row5.add(getTestContactEntry(8, false));
+        row5.add(getTestContactEntry(9, false));
+        assertContactEntryRowsEqual(row5, mAdapter.getItem(4));
+    }
+
+    /**
+     * Ensures that PhoneFavoritesTileAdapter returns true for hasStableIds. This is needed for
+     * animation purposes.
+     */
+    public void testHasStableIds() {
+        mAdapter = new PhoneFavoritesTileAdapter(getContext(), null, null, 2, 2);
+        assertTrue(mAdapter.hasStableIds());
+    }
+
+    private PhoneFavoritesTileAdapter getAdapterForTest(int numCols, int numRows) {
+        return new PhoneFavoritesTileAdapter(getContext(), null,
+                sOnDataSetChangedForAnimationListener, numCols, numRows);
+    }
+
+    /**
+     * Returns a cursor containing starred and frequent contacts for test purposes.
+     *
+     * @param numStarred Number of starred contacts in the cursor. Cannot be a negative number.
+     * @param numFrequents Number of frequent contacts in the cursor. Cannot be a negative number.
+     * @return Cursor containing the required number of rows, each representing one ContactEntry
+     */
+    private Cursor getCursorForTest(int numStarred, int numFrequents) {
+        assertTrue(numStarred >= 0);
+        assertTrue(numFrequents >= 0);
+        final MatrixCursor c = new MatrixCursor(ContactTileLoaderFactory.COLUMNS_PHONE_ONLY);
+        int countId = 0;
+
+        // Add starred contact entries. These entries have the starred field set to 1 (true).
+        // The only field that really matters for testing is the contact id.
+        for (int i = 0; i < numStarred; i++) {
+            c.addRow(new Object[] {countId, null, 1, null, null, 0, 0, null, 0,
+                    PinnedPositions.UNPINNED, countId});
+            countId++;
+        }
+
+        // Add frequent contact entries. These entries have the starred field set to 0 (false).
+        for (int i = 0; i < numFrequents; i++) {
+            c.addRow(new Object[] {countId, null, 0, null, null, 0, 0, null, 0,
+                    PinnedPositions.UNPINNED, countId});
+            countId++;
+        }
+        return c;
+    }
+
+    /**
+     * Returns a ContactEntry with test data corresponding to the provided contact Id
+     *
+     * @param id Non-negative id
+     * @return ContactEntry item used for testing
+     */
+    private ContactEntry getTestContactEntry(int id, boolean isFavorite) {
+        ContactEntry contactEntry = new ContactEntry();
+        contactEntry.id = id;
+        contactEntry.isFavorite = isFavorite;
+        return contactEntry;
+    }
+
+    private void assertContactEntryRowsEqual(ArrayList<ContactEntry> expected,
+            ArrayList<ContactEntry> actual) {
+        assertEquals(expected.size(), actual.size());
+        for (int i = 0; i < actual.size(); i++) {
+            assertEquals(expected.get(i).id, actual.get(i).id);
+            assertEquals(expected.get(i).isFavorite, actual.get(i).isFavorite);
+        }
+    }
 }