Fix PrefetchRegistry reset, out of bounds exceptions

Bug: 35708283
Test: adb shell am instrument -w -r -e debug false -e size small android.support.v17.leanback.test/android.support.test.runner.AndroidJUnitRunner
Test: adb shell am instrument -w -r -e debug false -e size small android.support.v7.recyclerview.test/android.support.test.runner.AndroidJUnitRunner
Test: ran BrowseFragmentTest / BrowseSupportFragmentTest 5 times in a row, each

Improper reset of the prefetch registry in conjunction with partial
prefetch of invisible views was causing negative item positions to be
attempted to be loaded.

This allows us to un-@Suppress the browse fragment tests in leanback
lib tests.

Change-Id: I931b25d560c9229676cfbec4b217abcbf7e43b4b
(cherry picked from commit 9d8319a04ccdb4785ca86fac3a4ff3fc6a368647)
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/app/BrowseFragmentTest.java b/v17/leanback/tests/java/android/support/v17/leanback/app/BrowseFragmentTest.java
index bb25edc..0008f93 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/app/BrowseFragmentTest.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/app/BrowseFragmentTest.java
@@ -25,7 +25,6 @@
 import android.content.Intent;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
-import android.support.test.filters.Suppress;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
 import android.support.v17.leanback.widget.ItemBridgeAdapter;
@@ -41,7 +40,6 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mockito;
 
-@Suppress
 @MediumTest
 @RunWith(AndroidJUnit4.class)
 public class BrowseFragmentTest {
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/app/BrowseSupportFragmentTest.java b/v17/leanback/tests/java/android/support/v17/leanback/app/BrowseSupportFragmentTest.java
index 699cef1..c7862c9 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/app/BrowseSupportFragmentTest.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/app/BrowseSupportFragmentTest.java
@@ -28,7 +28,6 @@
 import android.content.Intent;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
-import android.support.test.filters.Suppress;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
 import android.support.v17.leanback.widget.ItemBridgeAdapter;
@@ -44,7 +43,6 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mockito;
 
-@Suppress
 @MediumTest
 @RunWith(AndroidJUnit4.class)
 public class BrowseSupportFragmentTest {
diff --git a/v7/recyclerview/src/android/support/v7/widget/GapWorker.java b/v7/recyclerview/src/android/support/v7/widget/GapWorker.java
index 2ed205f..9392ee2 100644
--- a/v7/recyclerview/src/android/support/v7/widget/GapWorker.java
+++ b/v7/recyclerview/src/android/support/v7/widget/GapWorker.java
@@ -107,8 +107,7 @@
         @Override
         public void addPosition(int layoutPosition, int pixelDistance) {
             if (layoutPosition < 0) {
-                // temporary fix for b/35708283
-                return;
+                throw new IllegalArgumentException("Layout positions must be non-negative");
             }
 
             if (pixelDistance < 0) {
@@ -150,6 +149,7 @@
             if (mPrefetchArray != null) {
                 Arrays.fill(mPrefetchArray, -1);
             }
+            mCount = 0;
         }
     }
 
@@ -226,6 +226,11 @@
         int totalTaskIndex = 0;
         for (int i = 0; i < viewCount; i++) {
             RecyclerView view = mRecyclerViews.get(i);
+            if (view.getWindowVisibility() != View.VISIBLE) {
+                // Invisible view, don't bother prefetching
+                continue;
+            }
+
             LayoutPrefetchRegistryImpl prefetchRegistry = view.mPrefetchRegistry;
             final int viewVelocity = Math.abs(prefetchRegistry.mPrefetchDx)
                     + Math.abs(prefetchRegistry.mPrefetchDy);
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/GapWorkerTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/GapWorkerTest.java
index 5d08931..9158161 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/GapWorkerTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/GapWorkerTest.java
@@ -43,6 +43,43 @@
     }
 
     @Test
+    public void registrySimple() {
+        GapWorker.LayoutPrefetchRegistryImpl registry = new GapWorker.LayoutPrefetchRegistryImpl();
+        registry.addPosition(0, 0);
+        registry.addPosition(2, 0);
+        registry.addPosition(3, 0);
+        assertTrue(registry.lastPrefetchIncludedPosition(0));
+        assertFalse(registry.lastPrefetchIncludedPosition(1));
+        assertTrue(registry.lastPrefetchIncludedPosition(2));
+        assertTrue(registry.lastPrefetchIncludedPosition(3));
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void registryNegativeLayout() {
+        GapWorker.LayoutPrefetchRegistryImpl registry = new GapWorker.LayoutPrefetchRegistryImpl();
+        registry.addPosition(-1, 0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void registryNegativeDistance() {
+        GapWorker.LayoutPrefetchRegistryImpl registry = new GapWorker.LayoutPrefetchRegistryImpl();
+        registry.addPosition(0, -1);
+    }
+
+    @Test
+    public void registryResetCorrectly() {
+        GapWorker.LayoutPrefetchRegistryImpl registry = new GapWorker.LayoutPrefetchRegistryImpl();
+        registry.addPosition(0, 0);
+        assertFalse(registry.lastPrefetchIncludedPosition(-1));
+        assertTrue(registry.lastPrefetchIncludedPosition(0));
+
+        registry.clearPrefetchPositions();
+
+        assertFalse(registry.lastPrefetchIncludedPosition(-1));
+        assertFalse(registry.lastPrefetchIncludedPosition(0));
+    }
+
+    @Test
     public void taskOrderViewPresence() {
         ArrayList<GapWorker.Task> list = new ArrayList<>();
         list.add(new GapWorker.Task());