Merge "Copy the drawable's level to the image view"
diff --git a/settings.gradle b/settings.gradle
index 4a3f4a4..866ac21 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -28,6 +28,9 @@
 include ':support-preference-v14'
 project(':support-preference-v14').projectDir = new File(rootDir, 'v14/preference')
 
+include ':support-preference-v17'
+project(':support-preference-v17').projectDir = new File(rootDir, 'v17/preference')
+
 include ':support-v13'
 project(':support-v13').projectDir = new File(rootDir, 'v13')
 
diff --git a/v14/preference/src/android/support/v14/preference/PreferenceFragment.java b/v14/preference/src/android/support/v14/preference/PreferenceFragment.java
index 9fb1840..20bf2aa 100644
--- a/v14/preference/src/android/support/v14/preference/PreferenceFragment.java
+++ b/v14/preference/src/android/support/v14/preference/PreferenceFragment.java
@@ -29,6 +29,7 @@
 import android.support.v7.preference.EditTextPreference;
 import android.support.v7.preference.ListPreference;
 import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceGroupAdapter;
 import android.support.v7.preference.PreferenceManager;
 import android.support.v7.preference.PreferenceScreen;
 import android.support.v7.widget.LinearLayoutManager;
@@ -162,7 +163,7 @@
         /**
          * Called when the user has clicked on a Preference that has
          * a fragment class name associated with it.  The implementation
-         * to should instantiate and switch to an instance of the given
+         * should instantiate and switch to an instance of the given
          * fragment.
          */
         boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref);
@@ -442,7 +443,7 @@
     private void bindPreferences() {
         final PreferenceScreen preferenceScreen = getPreferenceScreen();
         if (preferenceScreen != null) {
-            getListView().setAdapter(preferenceScreen.getAdapter());
+            getListView().setAdapter(onCreateAdapter(preferenceScreen));
         }
         onBindPreferences();
     }
@@ -493,6 +494,16 @@
     }
 
     /**
+     * Creates the root adapter.
+     *
+     * @param preferenceScreen Preference screen object to create the adapter for.
+     * @return An adapter that contains the preferences contained in this {@link PreferenceScreen}.
+     */
+    protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {
+        return new PreferenceGroupAdapter(preferenceScreen);
+    }
+
+    /**
      * Called when a preference in the tree requests to display a dialog. Subclasses should
      * override this method to display custom dialogs or to handle dialogs for custom preference
      * classes.
diff --git a/v17/leanback/kitkat/android/support/v17/leanback/widget/BackgroundHelperKitkat.java b/v17/leanback/kitkat/android/support/v17/leanback/widget/BackgroundHelperKitkat.java
new file mode 100644
index 0000000..2b095fa
--- /dev/null
+++ b/v17/leanback/kitkat/android/support/v17/leanback/widget/BackgroundHelperKitkat.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package android.support.v17.leanback.widget;
+
+import android.graphics.drawable.Drawable;
+import android.view.View;
+
+class BackgroundHelperKitkat {
+
+    public static void setBackgroundPreservingAlpha(View view, Drawable drawable) {
+        if (view.getBackground() != null) {
+            drawable.setAlpha(view.getBackground().getAlpha());
+        }
+        view.setBackground(drawable);
+    }
+}
diff --git a/v17/leanback/res/values-en-rAU/strings.xml b/v17/leanback/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..ed22ccd
--- /dev/null
+++ b/v17/leanback/res/values-en-rAU/strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+Copyright (C) 2014 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="orb_search_action" msgid="5651268540267663887">"Search Action"</string>
+    <string name="lb_search_bar_hint" msgid="8325490927970116252">"Search"</string>
+    <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Speak to search"</string>
+    <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Search <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Speak to search <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Play"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Pause"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Fast-Forward"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Fast Forward %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Rewind"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Rewind %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Skip Next"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Skip Previous"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"More Actions"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Deselect Thumb Up"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Select Thumb Up"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Deselect Thumb Down"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Select Thumb Down"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Repeat None"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Repeat All"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Repeat One"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Enable Shuffle"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Disable Shuffle"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Enable High Quality"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Disable High Quality"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Enable Closed Captioning"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Disable Closed Captioning"</string>
+</resources>
diff --git a/v17/leanback/src/android/support/v17/leanback/app/BackgroundManager.java b/v17/leanback/src/android/support/v17/leanback/app/BackgroundManager.java
index fbc1dcb..59b0f19 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/BackgroundManager.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/BackgroundManager.java
@@ -34,6 +34,7 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.LayerDrawable;
 import android.os.Handler;
+import android.support.v17.leanback.widget.BackgroundHelper;
 import android.support.v4.view.animation.FastOutLinearInInterpolator;
 import android.util.Log;
 import android.view.LayoutInflater;
@@ -250,6 +251,11 @@
             }
         }
 
+        // Queried by system transitions
+        public int getAlpha() {
+            return mPaint.getAlpha();
+        }
+
         @Override
         public Drawable mutate() {
             Drawable drawable = super.mutate();
@@ -316,11 +322,6 @@
     }
 
     private TranslucentLayerDrawable mLayerDrawable;
-    private DrawableWrapper mImageInWrapper;
-    private DrawableWrapper mImageOutWrapper;
-    private DrawableWrapper mColorWrapper;
-    private DrawableWrapper mDimWrapper;
-
     private Drawable mDimDrawable;
     private ChangeBackgroundRunnable mChangeRunnable;
 
@@ -333,10 +334,10 @@
         }
         @Override
         public void onAnimationEnd(Animator animation) {
-            // mImageInWrapper should be full alpha, but mImageOutWrapper may not be 0 alpha
-            if (mImageOutWrapper != null) {
-                mImageOutWrapper.setAlpha(0);
-                mImageOutWrapper = null;
+            // imageInWrapper should be full alpha, but imageOutWrapper may not be 0 alpha
+            DrawableWrapper imageOutWrapper = getImageOutWrapper();
+            if (imageOutWrapper != null) {
+                imageOutWrapper.setAlpha(0);
             }
             if (mChangeRunnable != null) {
                 long delayMs = getRunnableDelay();
@@ -354,10 +355,14 @@
         @Override
         public void onAnimationUpdate(ValueAnimator animation) {
             int fadeInAlpha = (Integer) animation.getAnimatedValue();
-            if (mImageInWrapper != null) {
-                mImageInWrapper.setAlpha(fadeInAlpha);
-            } else if (mImageOutWrapper != null) {
-                mImageOutWrapper.setAlpha(255 - fadeInAlpha);
+            DrawableWrapper imageInWrapper = getImageInWrapper();
+            if (imageInWrapper != null) {
+                imageInWrapper.setAlpha(fadeInAlpha);
+            } else {
+                DrawableWrapper imageOutWrapper = getImageOutWrapper();
+                if (imageOutWrapper != null) {
+                    imageOutWrapper.setAlpha(255 - fadeInAlpha);
+                }
             }
         }
     };
@@ -366,8 +371,9 @@
             new ValueAnimator.AnimatorUpdateListener() {
         @Override
         public void onAnimationUpdate(ValueAnimator animation) {
-            if (mDimWrapper != null) {
-                mDimWrapper.setAlpha((Integer) animation.getAnimatedValue());
+            DrawableWrapper dimWrapper = getDimWrapper();
+            if (dimWrapper != null) {
+                dimWrapper.setAlpha((Integer) animation.getAnimatedValue());
             }
         }
     };
@@ -555,6 +561,26 @@
         fragment.setBackgroundManager(this);
     }
 
+    private DrawableWrapper getImageInWrapper() {
+        return mLayerDrawable == null ? null :
+                mLayerDrawable.findWrapperById(R.id.background_imagein);
+    }
+
+    private DrawableWrapper getImageOutWrapper() {
+        return mLayerDrawable == null ? null :
+                mLayerDrawable.findWrapperById(R.id.background_imageout);
+    }
+
+    private DrawableWrapper getDimWrapper() {
+        return mLayerDrawable == null ? null :
+                mLayerDrawable.findWrapperById(R.id.background_dim);
+    }
+
+    private DrawableWrapper getColorWrapper() {
+        return mLayerDrawable == null ? null :
+                mLayerDrawable.findWrapperById(R.id.background_color);
+    }
+
     /**
      * Synchronizes state when the owning Activity is resumed.
      */
@@ -596,13 +622,11 @@
         LayerDrawable layerDrawable = (LayerDrawable)
                 ContextCompat.getDrawable(mContext, R.drawable.lb_background).mutate();
         mLayerDrawable = TranslucentLayerDrawable.create(layerDrawable);
-        mBgView.setBackground(mLayerDrawable);
+        BackgroundHelper.setBackgroundPreservingAlpha(mBgView, mLayerDrawable);
 
         mLayerDrawable.clearDrawable(R.id.background_imageout, mContext);
         mLayerDrawable.updateDrawable(R.id.background_theme, getThemeDrawable());
 
-        mColorWrapper = mLayerDrawable.findWrapperById(R.id.background_color);
-
         updateDimWrapper();
     }
 
@@ -612,8 +636,9 @@
         }
         Drawable dimDrawable = mDimDrawable.getConstantState().newDrawable(
                 mContext.getResources()).mutate();
-        mDimWrapper = mLayerDrawable == null ? null : mLayerDrawable.updateDrawable(
-                R.id.background_dim, dimDrawable);
+        if (mLayerDrawable != null) {
+            mLayerDrawable.updateDrawable(R.id.background_dim, dimDrawable);
+        }
     }
 
     /**
@@ -704,10 +729,6 @@
             mLayerDrawable.clearDrawable(R.id.background_theme, mContext);
             mLayerDrawable = null;
         }
-        mImageInWrapper = null;
-        mImageOutWrapper = null;
-        mColorWrapper = null;
-        mDimWrapper = null;
         if (mChangeRunnable != null) {
             mHandler.removeCallbacks(mChangeRunnable);
             mChangeRunnable = null;
@@ -744,9 +765,13 @@
     private void updateImmediate() {
         lazyInit();
 
-        mColorWrapper.setColor(mBackgroundColor);
-        if (mDimWrapper != null) {
-            mDimWrapper.setAlpha(mBackgroundColor == Color.TRANSPARENT ? 0 : DIM_ALPHA_ON_SOLID);
+        DrawableWrapper colorWrapper = getColorWrapper();
+        if (colorWrapper != null) {
+            colorWrapper.setColor(mBackgroundColor);
+        }
+        DrawableWrapper dimWrapper = getDimWrapper();
+        if (dimWrapper != null) {
+            dimWrapper.setAlpha(mBackgroundColor == Color.TRANSPARENT ? 0 : DIM_ALPHA_ON_SOLID);
         }
         showWallpaper(mBackgroundColor == Color.TRANSPARENT);
 
@@ -754,10 +779,10 @@
             mLayerDrawable.clearDrawable(R.id.background_imagein, mContext);
         } else {
             if (DEBUG) Log.v(TAG, "Background drawable is available");
-            mImageInWrapper = mLayerDrawable.updateDrawable(
+            mLayerDrawable.updateDrawable(
                     R.id.background_imagein, mBackgroundDrawable);
-            if (mDimWrapper != null) {
-                mDimWrapper.setAlpha(FULL_ALPHA);
+            if (dimWrapper != null) {
+                dimWrapper.setAlpha(FULL_ALPHA);
             }
         }
     }
@@ -772,8 +797,9 @@
         mBackgroundColor = color;
         mService.setColor(mBackgroundColor);
 
-        if (mColorWrapper != null) {
-            mColorWrapper.setColor(mBackgroundColor);
+        DrawableWrapper colorWrapper = getColorWrapper();
+        if (colorWrapper != null) {
+            colorWrapper.setColor(mBackgroundColor);
         }
     }
 
@@ -886,26 +912,28 @@
 
         int dimAlpha = -1;
 
-        if (mImageOutWrapper != null) {
+        if (getImageOutWrapper() != null) {
             dimAlpha = mBackgroundColor == Color.TRANSPARENT ? 0 : DIM_ALPHA_ON_SOLID;
         }
 
-        if (mImageInWrapper == null && mBackgroundDrawable != null) {
+        DrawableWrapper imageInWrapper = getImageInWrapper();
+        if (imageInWrapper == null && mBackgroundDrawable != null) {
             if (DEBUG) Log.v(TAG, "creating new imagein drawable");
-            mImageInWrapper = mLayerDrawable.updateDrawable(
+            imageInWrapper = mLayerDrawable.updateDrawable(
                     R.id.background_imagein, mBackgroundDrawable);
-            if (DEBUG) Log.v(TAG, "mImageInWrapper animation starting");
-            mImageInWrapper.setAlpha(0);
+            if (DEBUG) Log.v(TAG, "imageInWrapper animation starting");
+            imageInWrapper.setAlpha(0);
             dimAlpha = FULL_ALPHA;
         }
 
         mAnimator.setDuration(FADE_DURATION);
         mAnimator.start();
 
-        if (mDimWrapper != null && dimAlpha >= 0) {
+        DrawableWrapper dimWrapper = getDimWrapper();
+        if (dimWrapper != null && dimAlpha >= 0) {
             if (DEBUG) Log.v(TAG, "dimwrapper animation starting to " + dimAlpha);
             mDimAnimator.cancel();
-            mDimAnimator.setIntValues(mDimWrapper.getAlpha(), dimAlpha);
+            mDimAnimator.setIntValues(dimWrapper.getAlpha(), dimAlpha);
             mDimAnimator.setDuration(FADE_DURATION);
             mDimAnimator.setInterpolator(
                     dimAlpha == FULL_ALPHA ? mDecelerateInterpolator : mAccelerateInterpolator);
@@ -972,14 +1000,14 @@
 
             releaseBackgroundBitmap();
 
-            if (mImageInWrapper != null) {
+            DrawableWrapper imageInWrapper = getImageInWrapper();
+            if (imageInWrapper != null) {
                 if (DEBUG) Log.v(TAG, "moving image in to image out");
                 // Order is important! Setting a drawable "removes" the
                 // previous one from the view
                 mLayerDrawable.clearDrawable(R.id.background_imagein, mContext);
-                mImageOutWrapper = mLayerDrawable.updateDrawable(R.id.background_imageout,
-                        mImageInWrapper.getDrawable());
-                mImageInWrapper = null;
+                mLayerDrawable.updateDrawable(R.id.background_imageout,
+                        imageInWrapper.getDrawable());
             }
 
             mBackgroundDrawable = mDrawable;
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/BackgroundHelper.java b/v17/leanback/src/android/support/v17/leanback/widget/BackgroundHelper.java
new file mode 100644
index 0000000..2df10a8
--- /dev/null
+++ b/v17/leanback/src/android/support/v17/leanback/widget/BackgroundHelper.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package android.support.v17.leanback.widget;
+
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.support.v17.leanback.widget.BackgroundHelperKitkat;
+import android.view.View;
+
+
+/**
+ * Helper for view backgrounds.
+ * @hide
+ */
+public final class BackgroundHelper {
+
+    final static BackgroundHelperVersionImpl sImpl;
+
+    static interface BackgroundHelperVersionImpl {
+        public void setBackgroundPreservingAlpha(View view, Drawable drawable);
+    }
+
+    private static final class BackgroundHelperStubImpl implements BackgroundHelperVersionImpl {
+        @Override
+        public void setBackgroundPreservingAlpha(View view, Drawable drawable) {
+            // Cannot query drawable alpha
+            view.setBackground(drawable);
+        }
+    }
+
+    private static final class BackgroundHelperKitkatImpl implements BackgroundHelperVersionImpl {
+        @Override
+        public void setBackgroundPreservingAlpha(View view, Drawable drawable) {
+            BackgroundHelperKitkat.setBackgroundPreservingAlpha(view, drawable);
+        }
+    }
+
+    private BackgroundHelper() {
+    }
+
+    static {
+        if (Build.VERSION.SDK_INT >= 19) {
+            sImpl = new BackgroundHelperKitkatImpl();
+        } else {
+            sImpl = new BackgroundHelperStubImpl();
+        }
+    }
+
+    public static void setBackgroundPreservingAlpha(View view, Drawable drawable) {
+        sImpl.setBackgroundPreservingAlpha(view, drawable);
+    }
+}
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 b0849e9..ad2211c 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java
@@ -418,7 +418,8 @@
     private RecyclerView.State mState;
     private RecyclerView.Recycler mRecycler;
 
-    private boolean mInLayout = false;
+    private boolean mInLayout;
+    private boolean mInScroll;
     private boolean mInFastRelayout;
     /**
      * During full layout pass, when GridView had focus: onLayoutChildren will
@@ -1752,6 +1753,7 @@
             return 0;
         }
         saveContext(recycler, state);
+        mInScroll = true;
         int result;
         if (mOrientation == HORIZONTAL) {
             result = scrollDirectionPrimary(dx);
@@ -1759,6 +1761,7 @@
             result = scrollDirectionSecondary(dx);
         }
         leaveContext();
+        mInScroll = false;
         return result;
     }
 
@@ -1768,6 +1771,7 @@
         if (!mLayoutEnabled || !hasDoneFirstLayout()) {
             return 0;
         }
+        mInScroll = true;
         saveContext(recycler, state);
         int result;
         if (mOrientation == VERTICAL) {
@@ -1776,6 +1780,7 @@
             result = scrollDirectionSecondary(dy);
         }
         leaveContext();
+        mInScroll = false;
         return result;
     }
 
@@ -2144,7 +2149,7 @@
             // scroll to a view whose item has been removed.
             return true;
         }
-        if (!mInLayout && !mInSelection) {
+        if (!mInLayout && !mInSelection && !mInScroll) {
             scrollToView(child, true);
         }
         return true;
diff --git a/v17/preference/build.gradle b/v17/preference/build.gradle
new file mode 100644
index 0000000..ed98c4f
--- /dev/null
+++ b/v17/preference/build.gradle
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+
+
+apply plugin: 'android-library'
+
+archivesBaseName = 'preference-v17'
+
+dependencies {
+    compile project(':support-v4')
+    compile project(':support-appcompat-v7')
+    compile project(':support-recyclerview-v7')
+    compile project(':support-preference-v7')
+    compile project(':support-preference-v14')
+    compile project(':support-leanback-v17')
+}
+
+android {
+    compileSdkVersion 'current'
+
+    sourceSets {
+        main.manifest.srcFile 'AndroidManifest.xml'
+        main.java.srcDir 'src'
+        main.res.srcDir 'res'
+        main.assets.srcDir 'assets'
+        main.resources.srcDir 'src'
+
+        // this moves src/instrumentTest to tests so all folders follow:
+        // tests/java, tests/res, tests/assets, ...
+        // This is a *reset* so it replaces the default paths
+        androidTest.setRoot('tests')
+        androidTest.java.srcDir 'tests/src'
+    }
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_7
+        targetCompatibility JavaVersion.VERSION_1_7
+    }
+
+    lintOptions {
+        // TODO: fix errors and reenable.
+        abortOnError false
+    }
+}
diff --git a/v17/tests/res/layout/horizontal_grid.xml b/v17/tests/res/layout/horizontal_grid.xml
index 5119f79..6c4eaf1 100644
--- a/v17/tests/res/layout/horizontal_grid.xml
+++ b/v17/tests/res/layout/horizontal_grid.xml
@@ -4,7 +4,7 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     >
-  <android.support.v17.leanback.widget.HorizontalGridView
+  <android.support.v17.leanback.widget.HorizontalGridViewEx
       android:id="@+id/gridview"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
diff --git a/v17/tests/res/layout/horizontal_grid_testredundantappendremove2.xml b/v17/tests/res/layout/horizontal_grid_testredundantappendremove2.xml
index b539f3c..fdfc0ea 100644
--- a/v17/tests/res/layout/horizontal_grid_testredundantappendremove2.xml
+++ b/v17/tests/res/layout/horizontal_grid_testredundantappendremove2.xml
@@ -4,7 +4,7 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     >
-  <android.support.v17.leanback.widget.HorizontalGridView
+  <android.support.v17.leanback.widget.HorizontalGridViewEx
       android:id="@+id/gridview"
       android:layout_width="960dp"
       android:layout_height="492dp"
diff --git a/v17/tests/res/layout/vertical_grid.xml b/v17/tests/res/layout/vertical_grid.xml
index 85e1d46..f4c0065 100644
--- a/v17/tests/res/layout/vertical_grid.xml
+++ b/v17/tests/res/layout/vertical_grid.xml
@@ -4,7 +4,7 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     >
-  <android.support.v17.leanback.widget.VerticalGridView
+  <android.support.v17.leanback.widget.VerticalGridViewEx
       android:id="@+id/gridview"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
diff --git a/v17/tests/res/layout/vertical_grid_testredundantappendremove.xml b/v17/tests/res/layout/vertical_grid_testredundantappendremove.xml
index 4ce56c5..bf056f8 100644
--- a/v17/tests/res/layout/vertical_grid_testredundantappendremove.xml
+++ b/v17/tests/res/layout/vertical_grid_testredundantappendremove.xml
@@ -4,7 +4,7 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     >
-  <android.support.v17.leanback.widget.VerticalGridView
+  <android.support.v17.leanback.widget.VerticalGridViewEx
       android:id="@+id/gridview"
       android:layout_width="960dp"
       android:layout_height="492dp"
diff --git a/v17/tests/res/layout/vertical_linear.xml b/v17/tests/res/layout/vertical_linear.xml
index b2c74df..0a1d00c 100644
--- a/v17/tests/res/layout/vertical_linear.xml
+++ b/v17/tests/res/layout/vertical_linear.xml
@@ -4,7 +4,7 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     >
-  <android.support.v17.leanback.widget.VerticalGridView
+  <android.support.v17.leanback.widget.VerticalGridViewEx
       android:id="@+id/gridview"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
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 ba6cd39..fdef479 100644
--- a/v17/tests/src/android/support/v17/leanback/widget/GridActivity.java
+++ b/v17/tests/src/android/support/v17/leanback/widget/GridActivity.java
@@ -21,7 +21,6 @@
 import android.support.v17.leanback.widget.BaseGridView;
 import android.support.v17.leanback.widget.OnChildSelectedListener;
 import android.app.Activity;
-import android.content.Context;
 import android.content.Intent;
 import android.graphics.Color;
 import android.os.Bundle;
@@ -38,6 +37,7 @@
  * @hide from javadoc
  */
 public class GridActivity extends Activity {
+
     private static final String TAG = "GridActivity";
 
     public static final String EXTRA_LAYOUT_RESOURCE_ID = "layoutResourceId";
@@ -46,11 +46,13 @@
     public static final String EXTRA_ITEMS_FOCUSABLE = "itemsFocusable";
     public static final String EXTRA_STAGGERED = "staggered";
     public static final String EXTRA_REQUEST_LAYOUT_ONFOCUS = "requestLayoutOnFocus";
+    public static final String EXTRA_REQUEST_FOCUS_ONLAYOUT = "requstFocusOnLayout";
     public static final String SELECT_ACTION = "android.test.leanback.widget.SELECT";
 
     static final int DEFAULT_NUM_ITEMS = 100;
     static final boolean DEFAULT_STAGGERED = true;
     static final boolean DEFAULT_REQUEST_LAYOUT_ONFOCUS = false;
+    static final boolean DEFAULT_REQUEST_FOCUS_ONLAYOUT = false;
 
     private static final boolean DEBUG = false;
 
@@ -59,6 +61,7 @@
     int mNumItems;
     boolean mStaggered;
     boolean mRequestLayoutOnFocus;
+    boolean mRequestFocusOnLayout;
 
     int[] mGridViewLayoutSize;
     BaseGridView mGridView;
@@ -92,6 +95,8 @@
         mStaggered = intent.getBooleanExtra(EXTRA_STAGGERED, DEFAULT_STAGGERED);
         mRequestLayoutOnFocus = intent.getBooleanExtra(EXTRA_REQUEST_LAYOUT_ONFOCUS,
                 DEFAULT_REQUEST_LAYOUT_ONFOCUS);
+        mRequestFocusOnLayout = intent.getBooleanExtra(EXTRA_REQUEST_FOCUS_ONLAYOUT,
+                DEFAULT_REQUEST_FOCUS_ONLAYOUT);
         mItemLengths = intent.getIntArrayExtra(EXTRA_ITEMS);
         mItemFocusables = intent.getBooleanArrayExtra(EXTRA_ITEMS_FOCUSABLE);
 
@@ -200,7 +205,18 @@
         @Override
         public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
             if (DEBUG) Log.v(TAG, "createViewHolder " + viewType);
-            TextView textView = new TextView(parent.getContext());
+            TextView textView = new TextView(parent.getContext()) {
+                @Override
+                protected void onLayout(boolean change, int left, int top, int right, int bottom) {
+                    super.onLayout(change, left, top, right, bottom);
+                    if (mRequestFocusOnLayout) {
+                        if (hasFocus()) {
+                            clearFocus();
+                            requestFocus();
+                        }
+                    }
+                }
+            };
             textView.setTextColor(Color.BLACK);
             textView.setOnFocusChangeListener(mItemFocusChangeListener);
             return new ViewHolder(textView);
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 178d59a..80fc63f 100644
--- a/v17/tests/src/android/support/v17/leanback/widget/GridWidgetTest.java
+++ b/v17/tests/src/android/support/v17/leanback/widget/GridWidgetTest.java
@@ -1089,4 +1089,48 @@
 
     }
 
+    public void testSmoothscrollerInterrupted() 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_REQUEST_FOCUS_ONLAYOUT, true);
+        int[] items = new int[100];
+        for (int i = 0; i < items.length; i++) {
+            items[i] = 680;
+        }
+        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
+        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
+        mOrientation = BaseGridView.VERTICAL;
+        mNumRows = 1;
+
+        initActivity(intent);
+
+        mGridView.setSelectedPositionSmooth(0);
+        waitForScrollIdle(mVerifyLayout);
+        assertTrue(mGridView.getChildAt(0).hasFocus());
+
+        // Pressing lots of key to make sure smooth scroller is running
+        for (int i = 0; i < 20; i++) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+        Thread.sleep(100);
+        int total = 0;
+        while (mGridView.getLayoutManager().isSmoothScrolling() ||
+                mGridView.getScrollState() != BaseGridView.SCROLL_STATE_IDLE) {
+            if ((total += 10) >= WAIT_FOR_SCROLL_IDLE_TIMEOUT_MS) {
+                throw new RuntimeException("waitForScrollIdle Timeout");
+            }
+            try {
+                // Repeatedly pressing to make sure pending keys does not drop to zero.
+                Thread.sleep(10);
+                sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+            } catch (InterruptedException ex) {
+                break;
+            }
+        }
+
+        assertTrue("LinearSmoothScroller would not use many RV.smoothScrollBy() calls",
+                ((VerticalGridViewEx) mGridView).mSmoothScrollByCalled < 10);
+    }
 }
diff --git a/v17/tests/src/android/support/v17/leanback/widget/HorizontalGridViewEx.java b/v17/tests/src/android/support/v17/leanback/widget/HorizontalGridViewEx.java
new file mode 100644
index 0000000..2c49283
--- /dev/null
+++ b/v17/tests/src/android/support/v17/leanback/widget/HorizontalGridViewEx.java
@@ -0,0 +1,27 @@
+package android.support.v17.leanback.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+class HorizontalGridViewEx extends HorizontalGridView {
+
+    public int mSmoothScrollByCalled;
+
+    public HorizontalGridViewEx(Context context) {
+        super(context);
+    }
+
+    public HorizontalGridViewEx(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public HorizontalGridViewEx(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    @Override
+    public void smoothScrollBy(int dx, int dy) {
+        mSmoothScrollByCalled++;
+        super.smoothScrollBy(dx, dy);
+    }
+}
\ No newline at end of file
diff --git a/v17/tests/src/android/support/v17/leanback/widget/VerticalGridViewEx.java b/v17/tests/src/android/support/v17/leanback/widget/VerticalGridViewEx.java
new file mode 100644
index 0000000..e262d54
--- /dev/null
+++ b/v17/tests/src/android/support/v17/leanback/widget/VerticalGridViewEx.java
@@ -0,0 +1,27 @@
+package android.support.v17.leanback.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+class VerticalGridViewEx extends VerticalGridView {
+
+    public int mSmoothScrollByCalled;
+
+    public VerticalGridViewEx(Context context) {
+        super(context);
+    }
+
+    public VerticalGridViewEx(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public VerticalGridViewEx(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    @Override
+    public void smoothScrollBy(int dx, int dy) {
+        mSmoothScrollByCalled++;
+        super.smoothScrollBy(dx, dy);
+    }
+}
\ No newline at end of file
diff --git a/v7/appcompat/res/values-en-rAU/strings.xml b/v7/appcompat/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..a85156e
--- /dev/null
+++ b/v7/appcompat/res/values-en-rAU/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="abc_action_mode_done" msgid="4076576682505996667">"Done"</string>
+    <string name="abc_action_bar_home_description" msgid="4600421777120114993">"Navigate home"</string>
+    <string name="abc_action_bar_up_description" msgid="1594238315039666878">"Navigate up"</string>
+    <string name="abc_action_menu_overflow_description" msgid="3588849162933574182">"More options"</string>
+    <string name="abc_toolbar_collapse_description" msgid="1603543279005712093">"Collapse"</string>
+    <string name="abc_action_bar_home_description_format" msgid="1397052879051804371">"%1$s, %2$s"</string>
+    <string name="abc_action_bar_home_subtitle_description_format" msgid="6623331958280229229">"%1$s, %2$s, %3$s"</string>
+    <string name="abc_searchview_description_search" msgid="8264924765203268293">"Search"</string>
+    <string name="abc_search_hint" msgid="7723749260725869598">"Search…"</string>
+    <string name="abc_searchview_description_query" msgid="2550479030709304392">"Search query"</string>
+    <string name="abc_searchview_description_clear" msgid="3691816814315814921">"Clear query"</string>
+    <string name="abc_searchview_description_submit" msgid="8928215447528550784">"Submit query"</string>
+    <string name="abc_searchview_description_voice" msgid="893419373245838918">"Voice search"</string>
+    <string name="abc_activitychooserview_choose_application" msgid="2031811694353399454">"Choose an app"</string>
+    <string name="abc_activity_chooser_view_see_all" msgid="7468859129482906941">"See all"</string>
+    <string name="abc_shareactionprovider_share_with_application" msgid="7165123711973476752">"Share with %s"</string>
+    <string name="abc_shareactionprovider_share_with" msgid="3421042268587513524">"Share with"</string>
+</resources>
diff --git a/v7/mediarouter/res/values-en-rAU/strings.xml b/v7/mediarouter/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..f5a8531
--- /dev/null
+++ b/v7/mediarouter/res/values-en-rAU/strings.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="mr_system_route_name" msgid="5441529851481176817">"System"</string>
+    <string name="mr_user_route_category_name" msgid="7498112907524977311">"Devices"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Cast"</string>
+    <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Connect to device"</string>
+    <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Searching for devices…"</string>
+    <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Disconnect"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Stop casting"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Route settings"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Play"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Pause"</string>
+</resources>
diff --git a/v7/preference/src/android/support/v7/preference/PreferenceFragmentCompat.java b/v7/preference/src/android/support/v7/preference/PreferenceFragmentCompat.java
index 72f742c..ac4ea17 100644
--- a/v7/preference/src/android/support/v7/preference/PreferenceFragmentCompat.java
+++ b/v7/preference/src/android/support/v7/preference/PreferenceFragmentCompat.java
@@ -436,7 +436,7 @@
     private void bindPreferences() {
         final PreferenceScreen preferenceScreen = getPreferenceScreen();
         if (preferenceScreen != null) {
-            getListView().setAdapter(preferenceScreen.getAdapter());
+            getListView().setAdapter(onCreateAdapter(preferenceScreen));
         }
         onBindPreferences();
     }
@@ -487,6 +487,16 @@
     }
 
     /**
+     * Creates the root adapter.
+     *
+     * @param preferenceScreen Preference screen object to create the adapter for.
+     * @return An adapter that contains the preferences contained in this {@link PreferenceScreen}.
+     */
+    protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {
+        return new PreferenceGroupAdapter(preferenceScreen);
+    }
+
+    /**
      * Called when a preference in the tree requests to display a dialog. Subclasses should
      * override this method to display custom dialogs or to handle dialogs for custom preference
      * classes.
diff --git a/v7/preference/src/android/support/v7/preference/PreferenceScreen.java b/v7/preference/src/android/support/v7/preference/PreferenceScreen.java
index dc1c98f..2010080 100644
--- a/v7/preference/src/android/support/v7/preference/PreferenceScreen.java
+++ b/v7/preference/src/android/support/v7/preference/PreferenceScreen.java
@@ -17,7 +17,6 @@
 package android.support.v7.preference;
 
 import android.content.Context;
-import android.support.v7.widget.RecyclerView;
 import android.util.AttributeSet;
 
 /**
@@ -74,8 +73,6 @@
  */
 public final class PreferenceScreen extends PreferenceGroup  {
 
-    private RecyclerView.Adapter mRootAdapter;
-
     /**
      * Do NOT use this constructor, use {@link PreferenceManager#createPreferenceScreen(Context)}.
      * @hide-
@@ -84,35 +81,6 @@
         super(context, attrs, R.attr.preferenceScreenStyle);
     }
 
-    /**
-     * Returns an adapter that can be attached to a {@link PreferenceFragment}
-     * or {@link PreferenceFragmentCompat} to show the preferences contained in this
-     * {@link PreferenceScreen}.
-     * <p>
-     * This {@link PreferenceScreen} will NOT appear in the returned adapter, instead
-     * it appears in the hierarchy above this {@link PreferenceScreen}.
-     *
-     * @return An adapter that manages the {@link Preference} contained in this
-     *         {@link PreferenceScreen}.
-     */
-    public final RecyclerView.Adapter getAdapter() {
-        if (mRootAdapter == null) {
-            mRootAdapter = onCreateAdapter();
-        }
-
-        return mRootAdapter;
-    }
-
-    /**
-     * Creates the root adapter.
-     *
-     * @return An adapter that contains the preferences contained in this {@link PreferenceScreen}.
-     * @see #getAdapter()
-     */
-    protected RecyclerView.Adapter onCreateAdapter() {
-        return new PreferenceGroupAdapter(this);
-    }
-
     @Override
     protected void onClick() {
         if (getIntent() != null || getFragment() != null || getPreferenceCount() == 0) {