GridLayoutManager: fire selected event when selected item type changed

Not only compare focused position but also compare the focused View that might
changed in fastLayout pass.

Bug 25619502

Change-Id: Ib59c8d753224daf23667d2f6ebd9a1babad61eb4
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java b/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java
index e7fa99f..20d54e2 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java
@@ -1773,6 +1773,11 @@
         mFocusPositionOffset = 0;
         saveContext(recycler, state);
 
+        View savedFocusView = findViewByPosition(mFocusPosition);
+        int savedFocusPos = mFocusPosition;
+        int savedSubFocusPos = mSubFocusPosition;
+        boolean hadFocus = mBaseGridView.hasFocus();
+
         // Track the old focus view so we can adjust our system scroll position
         // so that any scroll animations happening now will remain valid.
         // We must use same delta in Pre Layout (if prelayout exists) and second layout.
@@ -1781,17 +1786,14 @@
         if (mFocusPosition != NO_POSITION && scrollToFocus
                 && mBaseGridView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE) {
             // FIXME: we should get the remaining scroll animation offset from RecyclerView
-            View focusView = findViewByPosition(mFocusPosition);
-            if (focusView != null) {
-                if (getScrollPosition(focusView, focusView.findFocus(), sTwoInts)) {
+            if (savedFocusView != null) {
+                if (getScrollPosition(savedFocusView, savedFocusView.findFocus(), sTwoInts)) {
                     delta = sTwoInts[0];
                     deltaSecondary = sTwoInts[1];
                 }
             }
         }
 
-        boolean hadFocus = mBaseGridView.hasFocus();
-        int savedFocusPos = mFocusPosition;
         if (mInFastRelayout = layoutInit()) {
             fastRelayout();
             // appends items till focus position.
@@ -1859,7 +1861,8 @@
         }
 
         // For fastRelayout, only dispatch event when focus position changes.
-        if (mInFastRelayout && mFocusPosition != savedFocusPos) {
+        if (mInFastRelayout && (mFocusPosition != savedFocusPos || mSubFocusPosition !=
+                savedFocusPos || findViewByPosition(mFocusPosition) != savedFocusView)) {
             dispatchChildSelected();
         } else if (!mInFastRelayout && mInLayoutSearchFocus) {
             // For full layout we dispatchChildSelected() in createItem() unless searched all
diff --git a/v17/tests/src/android/support/v17/leanback/widget/GridActivity.java b/v17/tests/src/android/support/v17/leanback/widget/GridActivity.java
index 145ae48..902a665 100644
--- a/v17/tests/src/android/support/v17/leanback/widget/GridActivity.java
+++ b/v17/tests/src/android/support/v17/leanback/widget/GridActivity.java
@@ -360,7 +360,8 @@
                 holder.mItemAlignment = null;
             }
             if (mChildLayout == -1) {
-                ((TextView) holder.itemView).setText("Item "+mItemLengths[position]);
+                ((TextView) holder.itemView).setText("Item "+mItemLengths[position]
+                        + " type=" + getItemViewType(position));
                 boolean focusable = true;
                 if (mItemFocusables != null) {
                     focusable = mItemFocusables[position];
@@ -370,7 +371,8 @@
                 holder.itemView.setBackgroundColor(Color.LTGRAY);
             } else {
                 if (holder.itemView instanceof TextView) {
-                    ((TextView) holder.itemView).setText("Item "+mItemLengths[position]);
+                    ((TextView) holder.itemView).setText("Item "+mItemLengths[position]
+                            + " type=" + getItemViewType(position));
                 }
             }
             updateSize(holder.itemView, position);
@@ -380,6 +382,7 @@
         public int getItemCount() {
             return mNumItems;
         }
+
     }
 
     void updateSize(View view, int position) {
diff --git a/v17/tests/src/android/support/v17/leanback/widget/GridWidgetTest.java b/v17/tests/src/android/support/v17/leanback/widget/GridWidgetTest.java
index a24e1f6..335f449 100644
--- a/v17/tests/src/android/support/v17/leanback/widget/GridWidgetTest.java
+++ b/v17/tests/src/android/support/v17/leanback/widget/GridWidgetTest.java
@@ -21,6 +21,7 @@
 import android.text.Spannable;
 import android.util.Log;
 import android.util.SparseArray;
+import android.util.SparseIntArray;
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewGroup;
@@ -1886,6 +1887,20 @@
         }
     }
 
+    static class ChangeableViewTypesProvider implements ViewTypeProvider {
+        static SparseIntArray sViewTypes = new SparseIntArray();
+        @Override
+        public int getViewType(int position) {
+            return sViewTypes.get(position);
+        }
+        public static void clear() {
+            sViewTypes.clear();
+        }
+        public static void setViewType(int position, int type) {
+            sViewTypes.put(position, type);
+        }
+    }
+
     static class PositionItemAlignmentFacetProviderForRelativeLayout1
             implements ItemAlignmentFacetProvider {
         ItemAlignmentFacet mMultipleFacet;
@@ -2101,6 +2116,38 @@
         assertEquals(0, mGridView.getSelectedPosition());
     }
 
+    public void testNotifyItemTypeChangedSelectionEvent() throws Throwable {
+        mInstrumentation = getInstrumentation();
+        Intent intent = new Intent(mInstrumentation.getContext(), GridActivity.class);
+        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
+                R.layout.vertical_linear);
+        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 10);
+        intent.putExtra(GridActivity.EXTRA_VIEWTYPEPROVIDER_CLASS,
+                ChangeableViewTypesProvider.class.getName());
+        ChangeableViewTypesProvider.clear();
+        initActivity(intent);
+        mOrientation = BaseGridView.HORIZONTAL;
+        mNumRows = 1;
+
+        final ArrayList<Integer> selectedLog = new ArrayList<Integer>();
+        mGridView.setOnChildSelectedListener(new OnChildSelectedListener() {
+            public void onChildSelected(ViewGroup parent, View view, int position, long id) {
+                selectedLog.add(position);
+            }
+        });
+
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                ChangeableViewTypesProvider.setViewType(0, 1);
+                mGridView.getAdapter().notifyItemChanged(0, 1);
+            }
+        });
+        waitForTransientStateGone(null);
+        assertEquals(0, mGridView.getSelectedPosition());
+        assertEquals(selectedLog.size(), 1);
+        assertEquals((int) selectedLog.get(0), 0);
+    }
+
     public void testSelectionSmoothAndAddItemInOneCycle() throws Throwable {
         mInstrumentation = getInstrumentation();
         Intent intent = new Intent(mInstrumentation.getContext(), GridActivity.class);