Merge "Fix FocusSearchNavigationTest on API 15."
diff --git a/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java b/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java
index 11e94e5..1463722 100644
--- a/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java
+++ b/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java
@@ -182,6 +182,12 @@
      */
     private static final boolean ALLOW_THREAD_GAP_WORK = Build.VERSION.SDK_INT >= 21;
 
+    /**
+     * FocusFinder#findNextFocus is broken on ICS MR1 and older for View.FOCUS_BACKWARD direction.
+     * We convert it to an absolute direction such as FOCUS_DOWN or FOCUS_LEFT.
+     */
+    private static final boolean FORCE_ABS_FOCUS_SEARCH_DIRECTION = Build.VERSION.SDK_INT <= 15;
+
     static final boolean DISPATCH_TEMP_DETACH = false;
     public static final int HORIZONTAL = 0;
     public static final int VERTICAL = 1;
@@ -2234,6 +2240,10 @@
                         direction == View.FOCUS_FORWARD ? View.FOCUS_DOWN : View.FOCUS_UP;
                 final View found = ff.findNextFocus(this, focused, absDir);
                 needsFocusFailureLayout = found == null;
+                if (FORCE_ABS_FOCUS_SEARCH_DIRECTION) {
+                    // Workaround for broken FOCUS_BACKWARD in API 15 and older devices.
+                    direction = absDir;
+                }
             }
             if (!needsFocusFailureLayout && mLayout.canScrollHorizontally()) {
                 boolean rtl = mLayout.getLayoutDirection() == ViewCompat.LAYOUT_DIRECTION_RTL;
@@ -2241,6 +2251,10 @@
                         ? View.FOCUS_RIGHT : View.FOCUS_LEFT;
                 final View found = ff.findNextFocus(this, focused, absDir);
                 needsFocusFailureLayout = found == null;
+                if (FORCE_ABS_FOCUS_SEARCH_DIRECTION) {
+                    // Workaround for broken FOCUS_BACKWARD in API 15 and older devices.
+                    direction = absDir;
+                }
             }
             if (needsFocusFailureLayout) {
                 consumePendingUpdateOperations();
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/FocusSearchNavigationTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/FocusSearchNavigationTest.java
index 7bed232..55bed7e 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/FocusSearchNavigationTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/FocusSearchNavigationTest.java
@@ -28,6 +28,7 @@
 
 import android.app.Activity;
 import android.content.Context;
+import android.os.Build;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
 import android.support.test.rule.ActivityTestRule;
@@ -60,8 +61,8 @@
 @RunWith(Parameterized.class)
 public class FocusSearchNavigationTest {
     @Rule
-    public ActivityTestRule<RecyclerViewTestActivity> mActivityRule
-            = new ActivityTestRule<>(RecyclerViewTestActivity.class);
+    public ActivityTestRule<RecyclerViewTestActivity> mActivityRule =
+            new ActivityTestRule<>(RecyclerViewTestActivity.class);
 
     private final int mOrientation;
     private final int mLayoutDir;
@@ -73,11 +74,19 @@
 
     @Parameterized.Parameters(name = "orientation:{0},layoutDir:{1}")
     public static List<Object[]> params() {
-        return Arrays.asList(
-                new Object[]{VERTICAL, ViewCompat.LAYOUT_DIRECTION_LTR},
-                new Object[]{HORIZONTAL, ViewCompat.LAYOUT_DIRECTION_LTR},
-                new Object[]{HORIZONTAL, ViewCompat.LAYOUT_DIRECTION_RTL}
-        );
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+            return Arrays.asList(
+                    new Object[]{VERTICAL, ViewCompat.LAYOUT_DIRECTION_LTR},
+                    new Object[]{HORIZONTAL, ViewCompat.LAYOUT_DIRECTION_LTR},
+                    new Object[]{HORIZONTAL, ViewCompat.LAYOUT_DIRECTION_RTL}
+            );
+        } else {
+            // Do not test RTL before API 17
+            return Arrays.asList(
+                    new Object[]{VERTICAL, ViewCompat.LAYOUT_DIRECTION_LTR},
+                    new Object[]{HORIZONTAL, ViewCompat.LAYOUT_DIRECTION_LTR}
+            );
+        }
     }
 
     private Activity mActivity;
@@ -91,11 +100,11 @@
             @Override
             public void run() {
                 mActivity.setContentView(R.layout.focus_search_activity);
-                mActivity.getWindow().getDecorView().setLayoutDirection(mLayoutDir);
+                ViewCompat.setLayoutDirection(mActivity.getWindow().getDecorView(), mLayoutDir);
                 LinearLayout linearLayout = (LinearLayout) mActivity.findViewById(R.id.root);
                 linearLayout.setOrientation(mOrientation);
                 mRecyclerView = (RecyclerView) mActivity.findViewById(R.id.recycler_view);
-                mRecyclerView.setLayoutDirection(mLayoutDir);
+                ViewCompat.setLayoutDirection(mRecyclerView, mLayoutDir);
                 LinearLayoutManager layout = new LinearLayoutManager(mActivity.getBaseContext());
                 layout.setOrientation(mOrientation);
                 mRecyclerView.setLayoutManager(layout);
@@ -115,7 +124,7 @@
         waitForIdleSync();
         assertThat("test sanity", mRecyclerView.getLayoutManager().getLayoutDirection(),
                 is(mLayoutDir));
-        assertThat("test sanity", mRecyclerView.getLayoutDirection(), is(mLayoutDir));
+        assertThat("test sanity", ViewCompat.getLayoutDirection(mRecyclerView), is(mLayoutDir));
     }
 
     @Test