Merge "Deprecate and cleanup usage of KeyEventCompat."
diff --git a/README.md b/README.md
index 46cb691..098a0c6 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,8 @@
 We **are not** currently accepting new modules, features, or behavior changes.
 
 ## Checking Out the Code
+**NOTE: You will need to use Linux or Mac OS. Building under Windows is not currently supported.**
+
 Follow the [“Downloading the Source”](https://source.android.com/source/downloading.html) guide to install and set up `repo` tool, but instead of running the listed `repo` commands to initialize the repository, run the folowing:
 
     repo init -u https://android.googlesource.com/platform/manifest -b ub-supportlib-master
diff --git a/api/25.2.0.txt b/api/25.3.0.txt
similarity index 97%
rename from api/25.2.0.txt
rename to api/25.3.0.txt
index 6709b97..917fd00 100644
--- a/api/25.2.0.txt
+++ b/api/25.3.0.txt
@@ -354,11 +354,18 @@
     method public android.content.res.ColorStateList getItemTextColor();
     method public int getMaxItemCount();
     method public android.view.Menu getMenu();
+    method public int getSelectedItemId();
     method public void inflateMenu(int);
     method public void setItemBackgroundResource(int);
     method public void setItemIconTintList(android.content.res.ColorStateList);
     method public void setItemTextColor(android.content.res.ColorStateList);
+    method public void setOnNavigationItemReselectedListener(android.support.design.widget.BottomNavigationView.OnNavigationItemReselectedListener);
     method public void setOnNavigationItemSelectedListener(android.support.design.widget.BottomNavigationView.OnNavigationItemSelectedListener);
+    method public void setSelectedItemId(int);
+  }
+
+  public static abstract interface BottomNavigationView.OnNavigationItemReselectedListener {
+    method public abstract void onNavigationItemReselected(android.view.MenuItem);
   }
 
   public static abstract interface BottomNavigationView.OnNavigationItemSelectedListener {
@@ -1707,6 +1714,7 @@
     method protected java.lang.Object createEntranceTransition();
     method public android.support.v17.leanback.widget.ObjectAdapter getAdapter();
     method public android.support.v17.leanback.widget.BaseOnItemViewClickedListener getOnItemViewClickedListener();
+    method public android.support.v17.leanback.widget.DetailsParallax getParallax();
     method public android.support.v17.leanback.app.RowsFragment getRowsFragment();
     method protected deprecated android.view.View inflateTitle(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle);
     method protected void onEntranceTransitionEnd();
@@ -1724,11 +1732,30 @@
     method protected void setupPresenter(android.support.v17.leanback.widget.Presenter);
   }
 
+  public class DetailsFragmentBackgroundController {
+    ctor public DetailsFragmentBackgroundController(android.support.v17.leanback.app.DetailsFragment);
+    method public void enableParallax();
+    method public void enableParallax(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.support.v17.leanback.widget.ParallaxTarget.PropertyValuesHolderTarget);
+    method public final android.app.Fragment findOrCreateVideoFragment();
+    method public final android.graphics.drawable.Drawable getBottomDrawable();
+    method public final android.graphics.Bitmap getCoverBitmap();
+    method public final android.graphics.drawable.Drawable getCoverDrawable();
+    method public final int getParallaxDrawableMaxOffset();
+    method public final int getSolidColor();
+    method public android.support.v17.leanback.media.PlaybackGlueHost onCreateGlueHost();
+    method public android.app.Fragment onCreateVideoFragment();
+    method public final void setCoverBitmap(android.graphics.Bitmap);
+    method public final void setParallaxDrawableMaxOffset(int);
+    method public final void setSolidColor(int);
+    method public void setupVideoPlayback(android.support.v17.leanback.media.PlaybackGlue);
+  }
+
   public class DetailsSupportFragment extends android.support.v17.leanback.app.BrandedSupportFragment {
     ctor public DetailsSupportFragment();
     method protected java.lang.Object createEntranceTransition();
     method public android.support.v17.leanback.widget.ObjectAdapter getAdapter();
     method public android.support.v17.leanback.widget.BaseOnItemViewClickedListener getOnItemViewClickedListener();
+    method public android.support.v17.leanback.widget.DetailsParallax getParallax();
     method public android.support.v17.leanback.app.RowsSupportFragment getRowsSupportFragment();
     method protected deprecated android.view.View inflateTitle(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle);
     method protected void onEntranceTransitionEnd();
@@ -1746,6 +1773,24 @@
     method protected void setupPresenter(android.support.v17.leanback.widget.Presenter);
   }
 
+  public class DetailsSupportFragmentBackgroundController {
+    ctor public DetailsSupportFragmentBackgroundController(android.support.v17.leanback.app.DetailsSupportFragment);
+    method public void enableParallax();
+    method public void enableParallax(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.support.v17.leanback.widget.ParallaxTarget.PropertyValuesHolderTarget);
+    method public final android.support.v4.app.Fragment findOrCreateVideoSupportFragment();
+    method public final android.graphics.drawable.Drawable getBottomDrawable();
+    method public final android.graphics.Bitmap getCoverBitmap();
+    method public final android.graphics.drawable.Drawable getCoverDrawable();
+    method public final int getParallaxDrawableMaxOffset();
+    method public final int getSolidColor();
+    method public android.support.v17.leanback.media.PlaybackGlueHost onCreateGlueHost();
+    method public android.support.v4.app.Fragment onCreateVideoSupportFragment();
+    method public final void setCoverBitmap(android.graphics.Bitmap);
+    method public final void setParallaxDrawableMaxOffset(int);
+    method public final void setSolidColor(int);
+    method public void setupVideoPlayback(android.support.v17.leanback.media.PlaybackGlue);
+  }
+
   public class ErrorFragment extends android.support.v17.leanback.app.BrandedFragment {
     ctor public ErrorFragment();
     method public android.graphics.drawable.Drawable getBackgroundDrawable();
@@ -2040,6 +2085,7 @@
     method public void setFadingEnabled(boolean);
     method public void setHostCallback(android.support.v17.leanback.media.PlaybackGlueHost.HostCallback);
     method public void setOnItemViewClickedListener(android.support.v17.leanback.widget.BaseOnItemViewClickedListener);
+    method public void setOnItemViewSelectedListener(android.support.v17.leanback.widget.BaseOnItemViewSelectedListener);
     method public final void setOnKeyInterceptListener(android.view.View.OnKeyListener);
     method public void setOnPlaybackItemViewClickedListener(android.support.v17.leanback.widget.BaseOnItemViewClickedListener);
     method public void setPlaybackRow(android.support.v17.leanback.widget.Row);
@@ -2124,6 +2170,7 @@
     method public void setFadingEnabled(boolean);
     method public void setHostCallback(android.support.v17.leanback.media.PlaybackGlueHost.HostCallback);
     method public void setOnItemViewClickedListener(android.support.v17.leanback.widget.BaseOnItemViewClickedListener);
+    method public void setOnItemViewSelectedListener(android.support.v17.leanback.widget.BaseOnItemViewSelectedListener);
     method public final void setOnKeyInterceptListener(android.view.View.OnKeyListener);
     method public void setOnPlaybackItemViewClickedListener(android.support.v17.leanback.widget.BaseOnItemViewClickedListener);
     method public void setPlaybackRow(android.support.v17.leanback.widget.Row);
@@ -2290,6 +2337,28 @@
     method public void setSelectedPosition(int);
   }
 
+  public class VideoFragment extends android.support.v17.leanback.app.PlaybackFragment {
+    ctor public VideoFragment();
+    method public android.view.SurfaceView getSurfaceView();
+    method public void setSurfaceHolderCallback(android.view.SurfaceHolder.Callback);
+  }
+
+  public class VideoFragmentGlueHost extends android.support.v17.leanback.app.PlaybackFragmentGlueHost implements android.support.v17.leanback.media.SurfaceHolderGlueHost {
+    ctor public VideoFragmentGlueHost(android.support.v17.leanback.app.VideoFragment);
+    method public void setSurfaceHolderCallback(android.view.SurfaceHolder.Callback);
+  }
+
+  public class VideoSupportFragment extends android.support.v17.leanback.app.PlaybackSupportFragment {
+    ctor public VideoSupportFragment();
+    method public android.view.SurfaceView getSurfaceView();
+    method public void setSurfaceHolderCallback(android.view.SurfaceHolder.Callback);
+  }
+
+  public class VideoSupportFragmentGlueHost extends android.support.v17.leanback.app.PlaybackSupportFragmentGlueHost implements android.support.v17.leanback.media.SurfaceHolderGlueHost {
+    ctor public VideoSupportFragmentGlueHost(android.support.v17.leanback.app.VideoSupportFragment);
+    method public void setSurfaceHolderCallback(android.view.SurfaceHolder.Callback);
+  }
+
 }
 
 package android.support.v17.leanback.database {
@@ -2305,6 +2374,26 @@
 
 package android.support.v17.leanback.graphics {
 
+  public class BoundsRule {
+    ctor public BoundsRule();
+    ctor public BoundsRule(android.support.v17.leanback.graphics.BoundsRule);
+    method public static android.support.v17.leanback.graphics.BoundsRule.ValueRule absoluteValue(int);
+    method public void calculateBounds(android.graphics.Rect, android.graphics.Rect);
+    method public static android.support.v17.leanback.graphics.BoundsRule.ValueRule inheritFromParent(float);
+    method public static android.support.v17.leanback.graphics.BoundsRule.ValueRule inheritFromParentWithOffset(float, int);
+    field public android.support.v17.leanback.graphics.BoundsRule.ValueRule bottom;
+    field public android.support.v17.leanback.graphics.BoundsRule.ValueRule left;
+    field public android.support.v17.leanback.graphics.BoundsRule.ValueRule right;
+    field public android.support.v17.leanback.graphics.BoundsRule.ValueRule top;
+  }
+
+  public static final class BoundsRule.ValueRule {
+    method public int getAbsoluteValue();
+    method public float getFraction();
+    method public void setAbsoluteValue(int);
+    method public void setFraction(float);
+  }
+
   public final class ColorFilterCache {
     method public static android.support.v17.leanback.graphics.ColorFilterCache getColorFilterCache(int);
     method public android.graphics.ColorFilter getFilterForLevel(float);
@@ -2331,6 +2420,54 @@
     method public void setActiveLevel(float);
   }
 
+  public class CompositeDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
+    ctor public CompositeDrawable();
+    method public void addChildDrawable(android.graphics.drawable.Drawable);
+    method public void draw(android.graphics.Canvas);
+    method public android.support.v17.leanback.graphics.CompositeDrawable.ChildDrawable getChildAt(int);
+    method public int getChildCount();
+    method public android.graphics.drawable.Drawable getDrawable(int);
+    method public int getOpacity();
+    method public void invalidateDrawable(android.graphics.drawable.Drawable);
+    method public void removeChild(int);
+    method public void removeDrawable(android.graphics.drawable.Drawable);
+    method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
+    method public void setAlpha(int);
+    method public void setChildDrawableAt(int, android.graphics.drawable.Drawable);
+    method public void setColorFilter(android.graphics.ColorFilter);
+    method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
+  }
+
+  public static final class CompositeDrawable.ChildDrawable {
+    ctor public CompositeDrawable.ChildDrawable(android.graphics.drawable.Drawable, android.support.v17.leanback.graphics.CompositeDrawable);
+    method public android.support.v17.leanback.graphics.BoundsRule getBoundsRule();
+    method public android.graphics.drawable.Drawable getDrawable();
+    method public void recomputeBounds();
+    field public static final android.util.Property<android.support.v17.leanback.graphics.CompositeDrawable.ChildDrawable, java.lang.Integer> BOTTOM_ABSOLUTE;
+    field public static final android.util.Property<android.support.v17.leanback.graphics.CompositeDrawable.ChildDrawable, java.lang.Float> BOTTOM_FRACTION;
+    field public static final android.util.Property<android.support.v17.leanback.graphics.CompositeDrawable.ChildDrawable, java.lang.Integer> LEFT_ABSOLUTE;
+    field public static final android.util.Property<android.support.v17.leanback.graphics.CompositeDrawable.ChildDrawable, java.lang.Float> LEFT_FRACTION;
+    field public static final android.util.Property<android.support.v17.leanback.graphics.CompositeDrawable.ChildDrawable, java.lang.Integer> RIGHT_ABSOLUTE;
+    field public static final android.util.Property<android.support.v17.leanback.graphics.CompositeDrawable.ChildDrawable, java.lang.Float> RIGHT_FRACTION;
+    field public static final android.util.Property<android.support.v17.leanback.graphics.CompositeDrawable.ChildDrawable, java.lang.Integer> TOP_ABSOLUTE;
+    field public static final android.util.Property<android.support.v17.leanback.graphics.CompositeDrawable.ChildDrawable, java.lang.Float> TOP_FRACTION;
+  }
+
+  public class FitWidthBitmapDrawable extends android.graphics.drawable.Drawable {
+    ctor public FitWidthBitmapDrawable();
+    method public void draw(android.graphics.Canvas);
+    method public android.graphics.Bitmap getBitmap();
+    method public int getOpacity();
+    method public android.graphics.Rect getSource();
+    method public int getVerticalOffset();
+    method public void setAlpha(int);
+    method public void setBitmap(android.graphics.Bitmap);
+    method public void setColorFilter(android.graphics.ColorFilter);
+    method public void setSource(android.graphics.Rect);
+    method public void setVerticalOffset(int);
+    field public static final android.util.Property<android.support.v17.leanback.graphics.FitWidthBitmapDrawable, java.lang.Integer> PROPERTY_VERTICAL_OFFSET;
+  }
+
 }
 
 package android.support.v17.leanback.media {
@@ -2727,6 +2864,12 @@
     field public final android.support.v17.leanback.widget.Presenter.ViewHolder mDetailsDescriptionViewHolder;
   }
 
+  public class DetailsParallax extends android.support.v17.leanback.widget.RecyclerViewParallax {
+    ctor public DetailsParallax();
+    method public android.support.v17.leanback.widget.Parallax.IntProperty getOverviewRowBottom();
+    method public android.support.v17.leanback.widget.Parallax.IntProperty getOverviewRowTop();
+  }
+
   public class DividerPresenter extends android.support.v17.leanback.widget.Presenter {
     ctor public DividerPresenter();
     method public void onBindViewHolder(android.support.v17.leanback.widget.Presenter.ViewHolder, java.lang.Object);
@@ -3347,6 +3490,115 @@
     method public final boolean isRenderedAsRowView();
   }
 
+  public abstract class Parallax<PropertyT extends android.util.Property> {
+    ctor public Parallax();
+    method public void addEffect(android.support.v17.leanback.widget.ParallaxEffect);
+    method public android.support.v17.leanback.widget.ParallaxEffect addEffect(android.support.v17.leanback.widget.Parallax.IntPropertyMarkerValue...);
+    method public android.support.v17.leanback.widget.ParallaxEffect addEffect(android.support.v17.leanback.widget.Parallax.FloatPropertyMarkerValue...);
+    method public abstract PropertyT addProperty(java.lang.String);
+    method public abstract PropertyT createProperty(java.lang.String, int);
+    method public java.util.List<android.support.v17.leanback.widget.ParallaxEffect> getEffects();
+    method public final java.util.List<PropertyT> getProperties();
+    method public void removeAllEffects();
+    method public void removeEffect(android.support.v17.leanback.widget.ParallaxEffect);
+    method public void updateValues();
+    method public abstract void verifyProperties() throws java.lang.IllegalStateException;
+  }
+
+  public static abstract class Parallax.FloatParallax<FloatPropertyT extends android.support.v17.leanback.widget.Parallax.FloatProperty> extends android.support.v17.leanback.widget.Parallax {
+    ctor public Parallax.FloatParallax();
+    method public final FloatPropertyT addProperty(java.lang.String);
+    method public abstract float getMaxValue();
+    method public final float getPropertyValue(int);
+    method public final void setPropertyValue(int, float);
+    method public final void verifyProperties() throws java.lang.IllegalStateException;
+  }
+
+  public static class Parallax.FloatProperty extends android.util.Property {
+    ctor public Parallax.FloatProperty(java.lang.String, int);
+    method public final android.support.v17.leanback.widget.Parallax.FloatPropertyMarkerValue at(float, float);
+    method public final android.support.v17.leanback.widget.Parallax.FloatPropertyMarkerValue atAbsolute(float);
+    method public final android.support.v17.leanback.widget.Parallax.FloatPropertyMarkerValue atFraction(float);
+    method public final java.lang.Float get(android.support.v17.leanback.widget.Parallax.FloatParallax);
+    method public final int getIndex();
+    method public final void set(android.support.v17.leanback.widget.Parallax.FloatParallax, java.lang.Float);
+    field public static final float UNKNOWN_AFTER = 3.4028235E38f;
+    field public static final float UNKNOWN_BEFORE = -3.4028235E38f;
+  }
+
+  public static class Parallax.FloatPropertyMarkerValue extends android.support.v17.leanback.widget.Parallax.PropertyMarkerValue {
+    ctor public Parallax.FloatPropertyMarkerValue(android.support.v17.leanback.widget.Parallax.FloatProperty, float);
+    ctor public Parallax.FloatPropertyMarkerValue(android.support.v17.leanback.widget.Parallax.FloatProperty, float, float);
+    method public final float getMarkerValue(android.support.v17.leanback.widget.Parallax.FloatParallax);
+  }
+
+  public static abstract class Parallax.IntParallax<IntPropertyT extends android.support.v17.leanback.widget.Parallax.IntProperty> extends android.support.v17.leanback.widget.Parallax {
+    ctor public Parallax.IntParallax();
+    method public final IntPropertyT addProperty(java.lang.String);
+    method public abstract int getMaxValue();
+    method public final int getPropertyValue(int);
+    method public final void setPropertyValue(int, int);
+    method public final void verifyProperties() throws java.lang.IllegalStateException;
+  }
+
+  public static class Parallax.IntProperty extends android.util.Property {
+    ctor public Parallax.IntProperty(java.lang.String, int);
+    method public final android.support.v17.leanback.widget.Parallax.IntPropertyMarkerValue at(int, float);
+    method public final android.support.v17.leanback.widget.Parallax.IntPropertyMarkerValue atAbsolute(int);
+    method public final android.support.v17.leanback.widget.Parallax.IntPropertyMarkerValue atFraction(float);
+    method public final java.lang.Integer get(android.support.v17.leanback.widget.Parallax.IntParallax);
+    method public final int getIndex();
+    method public final void set(android.support.v17.leanback.widget.Parallax.IntParallax, java.lang.Integer);
+    field public static final int UNKNOWN_AFTER = 2147483647; // 0x7fffffff
+    field public static final int UNKNOWN_BEFORE = -2147483648; // 0x80000000
+  }
+
+  public static class Parallax.IntPropertyMarkerValue extends android.support.v17.leanback.widget.Parallax.PropertyMarkerValue {
+    ctor public Parallax.IntPropertyMarkerValue(android.support.v17.leanback.widget.Parallax.IntProperty, int);
+    ctor public Parallax.IntPropertyMarkerValue(android.support.v17.leanback.widget.Parallax.IntProperty, int, float);
+    method public final int getMarkerValue(android.support.v17.leanback.widget.Parallax.IntParallax);
+  }
+
+  public static class Parallax.PropertyMarkerValue<PropertyT> {
+    ctor public Parallax.PropertyMarkerValue(PropertyT);
+    method public PropertyT getProperty();
+  }
+
+  public abstract class ParallaxEffect<ParallaxEffectT extends android.support.v17.leanback.widget.ParallaxEffect, PropertyMarkerValueT extends android.support.v17.leanback.widget.Parallax.PropertyMarkerValue> {
+    ctor public ParallaxEffect();
+    method public final void addTarget(android.support.v17.leanback.widget.ParallaxTarget);
+    method protected abstract float calculateFraction(android.support.v17.leanback.widget.Parallax);
+    method public final java.util.List<PropertyMarkerValueT> getPropertyRanges();
+    method public final java.util.List<android.support.v17.leanback.widget.ParallaxTarget> getTargets();
+    method public final void performMapping(android.support.v17.leanback.widget.Parallax);
+    method public final void removeTarget(android.support.v17.leanback.widget.ParallaxTarget);
+    method public final void setPropertyRanges(PropertyMarkerValueT...);
+    method public final android.support.v17.leanback.widget.ParallaxEffect target(android.support.v17.leanback.widget.ParallaxTarget);
+    method public final android.support.v17.leanback.widget.ParallaxEffect target(java.lang.Object, android.animation.PropertyValuesHolder);
+  }
+
+  public static final class ParallaxEffect.FloatEffect extends android.support.v17.leanback.widget.ParallaxEffect {
+    ctor public ParallaxEffect.FloatEffect();
+    method protected float calculateFraction(android.support.v17.leanback.widget.Parallax);
+  }
+
+  public static final class ParallaxEffect.IntEffect extends android.support.v17.leanback.widget.ParallaxEffect {
+    ctor public ParallaxEffect.IntEffect();
+    method protected float calculateFraction(android.support.v17.leanback.widget.Parallax);
+  }
+
+  public abstract class ParallaxTarget {
+    ctor public ParallaxTarget();
+    method public abstract float getFraction();
+    method public abstract void update(float);
+  }
+
+  public static final class ParallaxTarget.PropertyValuesHolderTarget extends android.support.v17.leanback.widget.ParallaxTarget {
+    ctor public ParallaxTarget.PropertyValuesHolderTarget(java.lang.Object, android.animation.PropertyValuesHolder);
+    method public float getFraction();
+    method public void update(float);
+  }
+
   public class PlaybackControlsRow extends android.support.v17.leanback.widget.Row {
     ctor public PlaybackControlsRow(java.lang.Object);
     ctor public PlaybackControlsRow();
@@ -3536,6 +3788,25 @@
     method public void unselect();
   }
 
+  public class RecyclerViewParallax extends android.support.v17.leanback.widget.Parallax.IntParallax {
+    ctor public RecyclerViewParallax();
+    method public android.support.v17.leanback.widget.RecyclerViewParallax.ChildPositionProperty createProperty(java.lang.String, int);
+    method public int getMaxValue();
+    method public android.support.v7.widget.RecyclerView getRecyclerView();
+    method public void setRecyclerView(android.support.v7.widget.RecyclerView);
+  }
+
+  public static final class RecyclerViewParallax.ChildPositionProperty extends android.support.v17.leanback.widget.Parallax.IntProperty {
+    method public android.support.v17.leanback.widget.RecyclerViewParallax.ChildPositionProperty adapterPosition(int);
+    method public android.support.v17.leanback.widget.RecyclerViewParallax.ChildPositionProperty fraction(float);
+    method public int getAdapterPosition();
+    method public float getFraction();
+    method public int getOffset();
+    method public int getViewId();
+    method public android.support.v17.leanback.widget.RecyclerViewParallax.ChildPositionProperty offset(int);
+    method public android.support.v17.leanback.widget.RecyclerViewParallax.ChildPositionProperty viewId(int);
+  }
+
   public class Row {
     ctor public Row(long, android.support.v17.leanback.widget.HeaderItem);
     ctor public Row(android.support.v17.leanback.widget.HeaderItem);
@@ -5264,6 +5535,10 @@
     method public static int setAlphaComponent(int, int);
   }
 
+  public final class PaintCompat {
+    method public static boolean hasGlyph(android.graphics.Paint, java.lang.String);
+  }
+
 }
 
 package android.support.v4.graphics.drawable {
diff --git a/api/current.txt b/api/current.txt
index f9cbc2f..13200de 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -904,7 +904,8 @@
     method public java.lang.String getAttribute(java.lang.String);
     method public double getAttributeDouble(java.lang.String, double);
     method public int getAttributeInt(java.lang.String, int);
-    method public boolean getLatLong(float[]);
+    method public deprecated boolean getLatLong(float[]);
+    method public double[] getLatLong();
     method public byte[] getThumbnail();
     method public android.graphics.Bitmap getThumbnailBitmap();
     method public byte[] getThumbnailBytes();
@@ -913,6 +914,7 @@
     method public boolean isThumbnailCompressed();
     method public void saveAttributes() throws java.io.IOException;
     method public void setAttribute(java.lang.String, java.lang.String);
+    method public void setLatLong(double, double);
     field public static final int ORIENTATION_FLIP_HORIZONTAL = 2; // 0x2
     field public static final int ORIENTATION_FLIP_VERTICAL = 4; // 0x4
     field public static final int ORIENTATION_NORMAL = 1; // 0x1
@@ -5908,17 +5910,17 @@
   }
 
   public final class IntentCompat {
-    method public static android.content.Intent makeMainActivity(android.content.ComponentName);
+    method public static deprecated android.content.Intent makeMainActivity(android.content.ComponentName);
     method public static android.content.Intent makeMainSelectorActivity(java.lang.String, java.lang.String);
-    method public static android.content.Intent makeRestartActivityTask(android.content.ComponentName);
-    field public static final java.lang.String ACTION_EXTERNAL_APPLICATIONS_AVAILABLE = "android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE";
-    field public static final java.lang.String ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE = "android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE";
+    method public static deprecated android.content.Intent makeRestartActivityTask(android.content.ComponentName);
+    field public static final deprecated java.lang.String ACTION_EXTERNAL_APPLICATIONS_AVAILABLE = "android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE";
+    field public static final deprecated java.lang.String ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE = "android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE";
     field public static final java.lang.String CATEGORY_LEANBACK_LAUNCHER = "android.intent.category.LEANBACK_LAUNCHER";
-    field public static final java.lang.String EXTRA_CHANGED_PACKAGE_LIST = "android.intent.extra.changed_package_list";
-    field public static final java.lang.String EXTRA_CHANGED_UID_LIST = "android.intent.extra.changed_uid_list";
+    field public static final deprecated java.lang.String EXTRA_CHANGED_PACKAGE_LIST = "android.intent.extra.changed_package_list";
+    field public static final deprecated java.lang.String EXTRA_CHANGED_UID_LIST = "android.intent.extra.changed_uid_list";
     field public static final java.lang.String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
-    field public static final int FLAG_ACTIVITY_CLEAR_TASK = 32768; // 0x8000
-    field public static final int FLAG_ACTIVITY_TASK_ON_HOME = 16384; // 0x4000
+    field public static final deprecated int FLAG_ACTIVITY_CLEAR_TASK = 32768; // 0x8000
+    field public static final deprecated int FLAG_ACTIVITY_TASK_ON_HOME = 16384; // 0x4000
   }
 
   public class Loader<D> {
@@ -6821,15 +6823,15 @@
   }
 
   public final class TrafficStatsCompat {
-    method public static void clearThreadStatsTag();
-    method public static int getThreadStatsTag();
-    method public static void incrementOperationCount(int);
-    method public static void incrementOperationCount(int, int);
-    method public static void setThreadStatsTag(int);
+    method public static deprecated void clearThreadStatsTag();
+    method public static deprecated int getThreadStatsTag();
+    method public static deprecated void incrementOperationCount(int);
+    method public static deprecated void incrementOperationCount(int, int);
+    method public static deprecated void setThreadStatsTag(int);
     method public static void tagDatagramSocket(java.net.DatagramSocket) throws java.net.SocketException;
-    method public static void tagSocket(java.net.Socket) throws java.net.SocketException;
+    method public static deprecated void tagSocket(java.net.Socket) throws java.net.SocketException;
     method public static void untagDatagramSocket(java.net.DatagramSocket) throws java.net.SocketException;
-    method public static void untagSocket(java.net.Socket) throws java.net.SocketException;
+    method public static deprecated void untagSocket(java.net.Socket) throws java.net.SocketException;
   }
 
 }
@@ -8621,26 +8623,26 @@
     method public void startScroll(int, int, int, int, int);
   }
 
-  public final class SearchViewCompat {
-    method public static java.lang.CharSequence getQuery(android.view.View);
-    method public static boolean isIconified(android.view.View);
-    method public static boolean isQueryRefinementEnabled(android.view.View);
-    method public static boolean isSubmitButtonEnabled(android.view.View);
-    method public static android.view.View newSearchView(android.content.Context);
-    method public static void setIconified(android.view.View, boolean);
-    method public static void setImeOptions(android.view.View, int);
-    method public static void setInputType(android.view.View, int);
-    method public static void setMaxWidth(android.view.View, int);
-    method public static void setOnCloseListener(android.view.View, android.support.v4.widget.SearchViewCompat.OnCloseListener);
-    method public static void setOnQueryTextListener(android.view.View, android.support.v4.widget.SearchViewCompat.OnQueryTextListener);
-    method public static void setQuery(android.view.View, java.lang.CharSequence, boolean);
-    method public static void setQueryHint(android.view.View, java.lang.CharSequence);
-    method public static void setQueryRefinementEnabled(android.view.View, boolean);
-    method public static void setSearchableInfo(android.view.View, android.content.ComponentName);
-    method public static void setSubmitButtonEnabled(android.view.View, boolean);
+  public final deprecated class SearchViewCompat {
+    method public static deprecated java.lang.CharSequence getQuery(android.view.View);
+    method public static deprecated boolean isIconified(android.view.View);
+    method public static deprecated boolean isQueryRefinementEnabled(android.view.View);
+    method public static deprecated boolean isSubmitButtonEnabled(android.view.View);
+    method public static deprecated android.view.View newSearchView(android.content.Context);
+    method public static deprecated void setIconified(android.view.View, boolean);
+    method public static deprecated void setImeOptions(android.view.View, int);
+    method public static deprecated void setInputType(android.view.View, int);
+    method public static deprecated void setMaxWidth(android.view.View, int);
+    method public static deprecated void setOnCloseListener(android.view.View, android.support.v4.widget.SearchViewCompat.OnCloseListener);
+    method public static deprecated void setOnQueryTextListener(android.view.View, android.support.v4.widget.SearchViewCompat.OnQueryTextListener);
+    method public static deprecated void setQuery(android.view.View, java.lang.CharSequence, boolean);
+    method public static deprecated void setQueryHint(android.view.View, java.lang.CharSequence);
+    method public static deprecated void setQueryRefinementEnabled(android.view.View, boolean);
+    method public static deprecated void setSearchableInfo(android.view.View, android.content.ComponentName);
+    method public static deprecated void setSubmitButtonEnabled(android.view.View, boolean);
   }
 
-  public static abstract interface SearchViewCompat.OnCloseListener {
+  public static abstract deprecated interface SearchViewCompat.OnCloseListener {
     method public abstract boolean onClose();
   }
 
@@ -8649,7 +8651,7 @@
     method public boolean onClose();
   }
 
-  public static abstract interface SearchViewCompat.OnQueryTextListener {
+  public static abstract deprecated interface SearchViewCompat.OnQueryTextListener {
     method public abstract boolean onQueryTextChange(java.lang.String);
     method public abstract boolean onQueryTextSubmit(java.lang.String);
   }
@@ -11118,7 +11120,6 @@
     method public boolean isLayoutHierarchical(android.support.v7.widget.RecyclerView.Recycler, android.support.v7.widget.RecyclerView.State);
     method public boolean isMeasurementCacheEnabled();
     method public boolean isSmoothScrolling();
-    method public boolean isViewPartiallyVisible(android.view.View, boolean, boolean);
     method public void layoutDecorated(android.view.View, int, int, int, int);
     method public void layoutDecoratedWithMargins(android.view.View, int, int, int, int);
     method public void measureChild(android.view.View, int, int);
@@ -11163,7 +11164,6 @@
     method public void removeView(android.view.View);
     method public void removeViewAt(int);
     method public boolean requestChildRectangleOnScreen(android.support.v7.widget.RecyclerView, android.view.View, android.graphics.Rect, boolean);
-    method public boolean requestChildRectangleOnScreen(android.support.v7.widget.RecyclerView, android.view.View, android.graphics.Rect, boolean, boolean);
     method public void requestLayout();
     method public void requestSimpleAnimationsInNextLayout();
     method public int scrollHorizontallyBy(int, android.support.v7.widget.RecyclerView.Recycler, android.support.v7.widget.RecyclerView.State);
diff --git a/compat/api23/android/support/v4/text/ICUCompatApi23.java b/compat/api23/android/support/v4/text/ICUCompatApi21.java
similarity index 88%
rename from compat/api23/android/support/v4/text/ICUCompatApi23.java
rename to compat/api23/android/support/v4/text/ICUCompatApi21.java
index 0088f95..086a7cd 100644
--- a/compat/api23/android/support/v4/text/ICUCompatApi23.java
+++ b/compat/api23/android/support/v4/text/ICUCompatApi21.java
@@ -11,7 +11,7 @@
  * 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
+ * limitations under the License.
  */
 
 package android.support.v4.text;
@@ -23,16 +23,16 @@
 import java.lang.reflect.Method;
 import java.util.Locale;
 
-@RequiresApi(23)
-class ICUCompatApi23 {
+@RequiresApi(21)
+class ICUCompatApi21 {
 
-    private static final String TAG = "ICUCompatIcs";
+    private static final String TAG = "ICUCompatApi21";
 
     private static Method sAddLikelySubtagsMethod;
 
     static {
         try {
-            // This class should always exist on API-23 since it's CTS tested.
+            // This class should always exist on API-21 since it's CTS tested.
             final Class<?> clazz = Class.forName("libcore.icu.ICU");
             sAddLikelySubtagsMethod = clazz.getMethod("addLikelySubtags",
                     new Class[]{ Locale.class });
@@ -41,7 +41,6 @@
         }
     }
 
-
     public static String maximizeAndGetScript(Locale locale) {
         try {
             final Object[] args = new Object[] { locale };
diff --git a/compat/api24/android/support/v4/net/ConnectivityManagerCompatApi24.java b/compat/api24/android/support/v4/net/ConnectivityManagerCompatApi24.java
deleted file mode 100644
index c63062d..0000000
--- a/compat/api24/android/support/v4/net/ConnectivityManagerCompatApi24.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2016 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.v4.net;
-
-import android.net.ConnectivityManager;
-import android.support.annotation.RequiresApi;
-
-/**
- * Implementation of ConnectivityManagerCompat that can use API 24 APIs.
- */
-@RequiresApi(24)
-class ConnectivityManagerCompatApi24 {
-    public static int getRestrictBackgroundStatus(ConnectivityManager cm) {
-        return cm.getRestrictBackgroundStatus();
-    }
-}
diff --git a/compat/api24/android/support/v4/net/TrafficStatsCompatApi24.java b/compat/api24/android/support/v4/net/TrafficStatsCompatApi24.java
deleted file mode 100644
index 7a9e248..0000000
--- a/compat/api24/android/support/v4/net/TrafficStatsCompatApi24.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.v4.net;
-
-import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
-
-import android.net.TrafficStats;
-import android.support.annotation.RequiresApi;
-import android.support.annotation.RestrictTo;
-
-import java.net.DatagramSocket;
-import java.net.SocketException;
-
-/** @hide */
-@RequiresApi(24)
-@RestrictTo(LIBRARY_GROUP)
-public class TrafficStatsCompatApi24 {
-    public static void tagDatagramSocket(DatagramSocket socket) throws SocketException {
-        TrafficStats.tagDatagramSocket(socket);
-    }
-
-    public static void untagDatagramSocket(DatagramSocket socket) throws SocketException {
-        TrafficStats.untagDatagramSocket(socket);
-    }
-}
diff --git a/compat/honeycomb/android/support/v4/content/IntentCompatHoneycomb.java b/compat/honeycomb/android/support/v4/content/IntentCompatHoneycomb.java
deleted file mode 100644
index d3243d6..0000000
--- a/compat/honeycomb/android/support/v4/content/IntentCompatHoneycomb.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.
- */
-
-package android.support.v4.content;
-
-import android.content.ComponentName;
-import android.content.Intent;
-import android.support.annotation.RequiresApi;
-
-@RequiresApi(11)
-class IntentCompatHoneycomb {
-    public static Intent makeMainActivity(ComponentName mainActivity) {
-        return Intent.makeMainActivity(mainActivity);
-    }
-
-    public static Intent makeRestartActivityTask(ComponentName mainActivity) {
-        return Intent.makeRestartActivityTask(mainActivity);
-    }
-}
diff --git a/compat/honeycomb/android/support/v4/widget/SearchViewCompatHoneycomb.java b/compat/honeycomb/android/support/v4/widget/SearchViewCompatHoneycomb.java
deleted file mode 100644
index f44e398..0000000
--- a/compat/honeycomb/android/support/v4/widget/SearchViewCompatHoneycomb.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2011 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.v4.widget;
-
-import android.app.SearchManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.support.annotation.RequiresApi;
-import android.view.View;
-import android.widget.SearchView;
-import android.widget.SearchView.OnCloseListener;
-import android.widget.SearchView.OnQueryTextListener;
-
-/**
- * Implementation of SearchView compatibility that can call Honeycomb APIs.
- */
-
-@RequiresApi(11)
-class SearchViewCompatHoneycomb {
-
-    public static void checkIfLegalArg(View searchView) {
-        if (searchView == null) {
-            throw new IllegalArgumentException("searchView must be non-null");
-        }
-        if (!(searchView instanceof SearchView)) {
-            throw new IllegalArgumentException("searchView must be an instance of" +
-                    "android.widget.SearchView");
-        }
-    }
-
-    interface OnQueryTextListenerCompatBridge {
-        boolean onQueryTextSubmit(String query);
-        boolean onQueryTextChange(String newText);
-    }
-
-    interface OnCloseListenerCompatBridge {
-        boolean onClose();
-    }
-
-    public static View newSearchView(Context context) {
-        return new SearchView(context);
-    }
-
-    public static void setSearchableInfo(View searchView, ComponentName searchableComponent) {
-        SearchView sv = ((SearchView) searchView);
-        SearchManager searchManager = (SearchManager)
-                sv.getContext().getSystemService(Context.SEARCH_SERVICE);
-        sv.setSearchableInfo(searchManager.getSearchableInfo(searchableComponent));
-    }
-
-    public static Object newOnQueryTextListener(final OnQueryTextListenerCompatBridge listener) {
-        return new OnQueryTextListener() {
-            @Override
-            public boolean onQueryTextSubmit(String query) {
-                return listener.onQueryTextSubmit(query);
-            }
-
-            @Override
-            public boolean onQueryTextChange(String newText) {
-                return listener.onQueryTextChange(newText);
-            }
-        };
-    }
-
-    public static void setOnQueryTextListener(View searchView, Object listener) {
-        ((SearchView) searchView).setOnQueryTextListener((OnQueryTextListener) listener);
-    }
-
-    public static Object newOnCloseListener(final OnCloseListenerCompatBridge listener) {
-        return new OnCloseListener() {
-            @Override
-            public boolean onClose() {
-                return listener.onClose();
-            }
-        };
-    }
-
-    public static void setOnCloseListener(View searchView, Object listener) {
-        ((SearchView) searchView).setOnCloseListener((OnCloseListener) listener);
-    }
-
-    public static CharSequence getQuery(View searchView) {
-        return ((SearchView) searchView).getQuery();
-    }
-
-    public static void setQuery(View searchView, CharSequence query, boolean submit) {
-        ((SearchView) searchView).setQuery(query, submit);
-    }
-
-    public static void setQueryHint(View searchView, CharSequence hint) {
-        ((SearchView) searchView).setQueryHint(hint);
-    }
-
-    public static void setIconified(View searchView, boolean iconify) {
-        ((SearchView) searchView).setIconified(iconify);
-    }
-
-    public static boolean isIconified(View searchView) {
-        return ((SearchView) searchView).isIconified();
-    }
-
-    public static void setSubmitButtonEnabled(View searchView, boolean enabled) {
-        ((SearchView) searchView).setSubmitButtonEnabled(enabled);
-    }
-
-    public static boolean isSubmitButtonEnabled(View searchView) {
-        return ((SearchView) searchView).isSubmitButtonEnabled();
-    }
-
-    public static void setQueryRefinementEnabled(View searchView, boolean enable) {
-        ((SearchView) searchView).setQueryRefinementEnabled(enable);
-    }
-
-    public static boolean isQueryRefinementEnabled(View searchView) {
-        return ((SearchView) searchView).isQueryRefinementEnabled();
-    }
-
-    public static void setMaxWidth(View searchView, int maxpixels) {
-        ((SearchView) searchView).setMaxWidth(maxpixels);
-    }
-}
diff --git a/compat/honeycomb_mr2/android/support/v4/net/ConnectivityManagerCompatHoneycombMR2.java b/compat/honeycomb_mr2/android/support/v4/net/ConnectivityManagerCompatHoneycombMR2.java
deleted file mode 100644
index 5a93799..0000000
--- a/compat/honeycomb_mr2/android/support/v4/net/ConnectivityManagerCompatHoneycombMR2.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.
- */
-
-package android.support.v4.net;
-
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.support.annotation.RequiresApi;
-
-import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
-import static android.net.ConnectivityManager.TYPE_ETHERNET;
-import static android.net.ConnectivityManager.TYPE_MOBILE;
-import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
-import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
-import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
-import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL;
-import static android.net.ConnectivityManager.TYPE_WIFI;
-import static android.net.ConnectivityManager.TYPE_WIMAX;
-
-/**
- * Implementation of ConnectivityManagerCompat that can use Honeycomb MR2 APIs.
- */
-
-@RequiresApi(13)
-class ConnectivityManagerCompatHoneycombMR2 {
-    public static boolean isActiveNetworkMetered(ConnectivityManager cm) {
-        final NetworkInfo info = cm.getActiveNetworkInfo();
-        if (info == null) {
-            // err on side of caution
-            return true;
-        }
-
-        final int type = info.getType();
-        switch (type) {
-            case TYPE_MOBILE:
-            case TYPE_MOBILE_DUN:
-            case TYPE_MOBILE_HIPRI:
-            case TYPE_MOBILE_MMS:
-            case TYPE_MOBILE_SUPL:
-            case TYPE_WIMAX:
-                return true;
-            case TYPE_WIFI:
-            case TYPE_BLUETOOTH:
-            case TYPE_ETHERNET:
-                return false;
-            default:
-                // err on side of caution
-                return true;
-        }
-    }
-}
diff --git a/compat/ics-mr1/android/support/v4/content/IntentCompatIcsMr1.java b/compat/ics-mr1/android/support/v4/content/IntentCompatIcsMr1.java
deleted file mode 100644
index 8dd75d8..0000000
--- a/compat/ics-mr1/android/support/v4/content/IntentCompatIcsMr1.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.
- */
-
-package android.support.v4.content;
-
-import android.content.Intent;
-import android.support.annotation.RequiresApi;
-
-@RequiresApi(15)
-class IntentCompatIcsMr1 {
-
-    public static Intent makeMainSelectorActivity(String selectorAction, String selectorCategory) {
-        return Intent.makeMainSelectorActivity(selectorAction, selectorCategory);
-    }
-
-}
diff --git a/compat/ics/android/support/v4/net/TrafficStatsCompatIcs.java b/compat/ics/android/support/v4/net/TrafficStatsCompatIcs.java
deleted file mode 100644
index 4066386..0000000
--- a/compat/ics/android/support/v4/net/TrafficStatsCompatIcs.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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.
- */
-
-package android.support.v4.net;
-
-import android.net.TrafficStats;
-import android.os.ParcelFileDescriptor;
-import android.support.annotation.RequiresApi;
-
-import java.net.DatagramSocket;
-import java.net.Socket;
-import java.net.SocketException;
-
-/**
- * Implementation of TrafficStatsCompat that can call ICS APIs.
- */
-
-@RequiresApi(14)
-class TrafficStatsCompatIcs {
-    public static void clearThreadStatsTag() {
-        TrafficStats.clearThreadStatsTag();
-    }
-
-    public static int getThreadStatsTag() {
-        return TrafficStats.getThreadStatsTag();
-    }
-
-    public static void incrementOperationCount(int operationCount) {
-        TrafficStats.incrementOperationCount(operationCount);
-    }
-
-    public static void incrementOperationCount(int tag, int operationCount) {
-        TrafficStats.incrementOperationCount(tag, operationCount);
-    }
-
-    public static void setThreadStatsTag(int tag) {
-        TrafficStats.setThreadStatsTag(tag);
-    }
-
-    public static void tagSocket(Socket socket) throws SocketException {
-        TrafficStats.tagSocket(socket);
-    }
-
-    public static void untagSocket(Socket socket) throws SocketException {
-        TrafficStats.untagSocket(socket);
-    }
-
-    public static void tagDatagramSocket(DatagramSocket socket) throws SocketException {
-        final ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket);
-        TrafficStats.tagSocket(new DatagramSocketWrapper(socket, pfd.getFileDescriptor()));
-        // The developer is still using the FD, so we need to detach it to
-        // prevent the PFD finalizer from closing it in their face. We had to
-        // wait until after the tagging call above, since detaching clears out
-        // the getFileDescriptor() result which tagging depends on.
-        pfd.detachFd();
-    }
-
-    public static void untagDatagramSocket(DatagramSocket socket) throws SocketException {
-        final ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket);
-        TrafficStats.untagSocket(new DatagramSocketWrapper(socket, pfd.getFileDescriptor()));
-        // The developer is still using the FD, so we need to detach it to
-        // prevent the PFD finalizer from closing it in their face. We had to
-        // wait until after the tagging call above, since detaching clears out
-        // the getFileDescriptor() result which tagging depends on.
-        pfd.detachFd();
-    }
-}
diff --git a/compat/ics/android/support/v4/widget/SearchViewCompatIcs.java b/compat/ics/android/support/v4/widget/SearchViewCompatIcs.java
deleted file mode 100644
index bf5c44e..0000000
--- a/compat/ics/android/support/v4/widget/SearchViewCompatIcs.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.
- */
-
-package android.support.v4.widget;
-
-import android.content.Context;
-import android.support.annotation.RequiresApi;
-import android.view.View;
-import android.widget.SearchView;
-
-/**
- * Implementation of SearchView compatibility that can call ICS APIs.
- */
-
-@RequiresApi(14)
-class SearchViewCompatIcs {
-
-    public static class MySearchView extends SearchView {
-        public MySearchView(Context context) {
-            super(context);
-        }
-
-        // The normal SearchView doesn't clear its search text when
-        // collapsed, so we will do this for it.
-        @Override
-        public void onActionViewCollapsed() {
-            setQuery("", false);
-            super.onActionViewCollapsed();
-        }
-    }
-
-    public static View newSearchView(Context context) {
-        return new MySearchView(context);
-    }
-
-    public static void setImeOptions(View searchView, int imeOptions) {
-        ((SearchView) searchView).setImeOptions(imeOptions);
-    }
-
-    public static void setInputType(View searchView, int inputType) {
-        ((SearchView) searchView).setInputType(inputType);
-    }
-}
diff --git a/compat/java/android/support/v4/content/IntentCompat.java b/compat/java/android/support/v4/content/IntentCompat.java
index 179824e..d34c914 100644
--- a/compat/java/android/support/v4/content/IntentCompat.java
+++ b/compat/java/android/support/v4/content/IntentCompat.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.Build;
+import android.support.annotation.RequiresApi;
 
 /**
  * Helper for accessing features in {@link android.content.Intent}
@@ -27,22 +28,7 @@
  */
 public final class IntentCompat {
 
-    interface IntentCompatImpl {
-        Intent makeMainActivity(ComponentName componentName);
-        Intent makeMainSelectorActivity(String selectorAction, String selectorCategory);
-        Intent makeRestartActivityTask(ComponentName mainActivity);
-    }
-
-    static class IntentCompatImplBase implements IntentCompatImpl {
-        @Override
-        public Intent makeMainActivity(ComponentName componentName) {
-            Intent intent = new Intent(Intent.ACTION_MAIN);
-            intent.setComponent(componentName);
-            intent.addCategory(Intent.CATEGORY_LAUNCHER);
-            return intent;
-        }
-
-        @Override
+    static class IntentCompatBaseImpl {
         public Intent makeMainSelectorActivity(String selectorAction,
                 String selectorCategory) {
             // Before api 15 you couldn't set a selector intent.
@@ -52,43 +38,23 @@
             intent.addCategory(selectorCategory);
             return intent;
         }
-
-        @Override
-        public Intent makeRestartActivityTask(ComponentName mainActivity) {
-            Intent intent = makeMainActivity(mainActivity);
-            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                    | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
-            return intent;
-        }
     }
 
-    static class IntentCompatImplHC extends IntentCompatImplBase {
-        @Override
-        public Intent makeMainActivity(ComponentName componentName) {
-            return IntentCompatHoneycomb.makeMainActivity(componentName);
-        }
-        @Override
-        public Intent makeRestartActivityTask(ComponentName componentName) {
-            return IntentCompatHoneycomb.makeRestartActivityTask(componentName);
-        }
-    }
-
-    static class IntentCompatImplIcsMr1 extends IntentCompatImplHC {
+    @RequiresApi(15)
+    static class IntentCompatApi15Impl extends IntentCompatBaseImpl {
         @Override
         public Intent makeMainSelectorActivity(String selectorAction, String selectorCategory) {
-            return IntentCompatIcsMr1.makeMainSelectorActivity(selectorAction, selectorCategory);
+            return Intent.makeMainSelectorActivity(selectorAction, selectorCategory);
         }
     }
 
-    private static final IntentCompatImpl IMPL;
+    private static final IntentCompatBaseImpl IMPL;
     static {
         final int version = Build.VERSION.SDK_INT;
         if (version >= 15) {
-            IMPL = new IntentCompatImplIcsMr1();
-        } else if (version >= 11) {
-            IMPL = new IntentCompatImplHC();
+            IMPL = new IntentCompatApi15Impl();
         } else {
-            IMPL = new IntentCompatImplBase();
+            IMPL = new IntentCompatBaseImpl();
         }
     }
 
@@ -118,7 +84,10 @@
      *
      * <p class="note">This is a protected intent that can only be sent
      * by the system.
+     *
+     * @deprecated Use {@link Intent#ACTION_EXTERNAL_APPLICATIONS_AVAILABLE} directly.
      */
+    @Deprecated
     public static final String ACTION_EXTERNAL_APPLICATIONS_AVAILABLE =
         "android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE";
 
@@ -141,7 +110,10 @@
      *
      * <p class="note">This is a protected intent that can only be sent
      * by the system.
+     *
+     * @deprecated Use {@link Intent#ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE} directly.
      */
+    @Deprecated
     public static final String ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE =
         "android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE";
 
@@ -150,7 +122,10 @@
      * {@link android.content.Intent#ACTION_EXTERNAL_APPLICATIONS_AVAILABLE},
      * {@link android.content.Intent#ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE}
      * and contains a string array of all of the components that have changed.
+     *
+     * @deprecated Use {@link Intent#EXTRA_CHANGED_PACKAGE_LIST} directly.
      */
+    @Deprecated
     public static final String EXTRA_CHANGED_PACKAGE_LIST =
             "android.intent.extra.changed_package_list";
 
@@ -160,7 +135,10 @@
      * {@link android.content.Intent#ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE}
      * and contains an integer array of uids of all of the components
      * that have changed.
+     *
+     * @deprecated Use {@link Intent#EXTRA_CHANGED_UID_LIST} directly.
      */
+    @Deprecated
     public static final String EXTRA_CHANGED_UID_LIST =
             "android.intent.extra.changed_uid_list";
 
@@ -186,7 +164,10 @@
      * will always return the user to home even if that was not the last activity they
      * saw. This can only be used in conjunction with
      * {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}.
+     *
+     * @deprecated Use {@link Intent#FLAG_ACTIVITY_TASK_ON_HOME} directly.
      */
+    @Deprecated
     public static final int FLAG_ACTIVITY_TASK_ON_HOME = 0x00004000;
 
     /**
@@ -198,7 +179,10 @@
      * {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}.
      *
      * <p>This flag will only be obeyed on devices supporting API 11 or higher.</p>
+     *
+     * @deprecated Use {@link Intent#FLAG_ACTIVITY_CLEAR_TASK} directly.
      */
+    @Deprecated
     public static final int FLAG_ACTIVITY_CLEAR_TASK = 0x00008000;
 
     /**
@@ -222,12 +206,14 @@
      *
      * @see Intent#setClass
      * @see Intent#setComponent
+     *
+     * @deprecated Use {@link Intent#makeMainActivity(ComponentName)} directly.
      */
+    @Deprecated
     public static Intent makeMainActivity(ComponentName mainActivity) {
-        return IMPL.makeMainActivity(mainActivity);
+        return Intent.makeMainActivity(mainActivity);
     }
 
-
     /**
      * Make an Intent for the main activity of an application, without
      * specifying a specific activity to run but giving a selector to find
@@ -257,7 +243,7 @@
      * Make an Intent that can be used to re-launch an application's task
      * in its base state.  This is like {@link #makeMainActivity(ComponentName)},
      * but also sets the flags {@link Intent#FLAG_ACTIVITY_NEW_TASK} and
-     * {@link IntentCompat#FLAG_ACTIVITY_CLEAR_TASK}.
+     * {@link Intent#FLAG_ACTIVITY_CLEAR_TASK}.
      *
      * @param mainActivity The activity component that is the root of the
      * task; this is the activity that has been published in the application's
@@ -265,8 +251,11 @@
      *
      * @return Returns a newly created Intent that can be used to relaunch the
      * activity's task in its root state.
+     *
+     * @deprecated Use {@link Intent#makeRestartActivityTask(ComponentName)} directly.
      */
+    @Deprecated
     public static Intent makeRestartActivityTask(ComponentName mainActivity) {
-        return IMPL.makeRestartActivityTask(mainActivity);
+        return Intent.makeRestartActivityTask(mainActivity);
     }
 }
diff --git a/compat/java/android/support/v4/content/res/TypedArrayUtils.java b/compat/java/android/support/v4/content/res/TypedArrayUtils.java
new file mode 100644
index 0000000..77d4672
--- /dev/null
+++ b/compat/java/android/support/v4/content/res/TypedArrayUtils.java
@@ -0,0 +1,218 @@
+/*
+ * 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.v4.content.res;
+
+import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.AnyRes;
+import android.support.annotation.ColorInt;
+import android.support.annotation.NonNull;
+import android.support.annotation.RestrictTo;
+import android.support.annotation.StyleableRes;
+import android.util.TypedValue;
+
+import org.xmlpull.v1.XmlPullParser;
+
+/**
+ * Compat methods for accessing TypedArray values.
+ *
+ * @hide
+ */
+@RestrictTo(LIBRARY_GROUP)
+public class TypedArrayUtils {
+
+    private static final String NAMESPACE = "http://schemas.android.com/apk/res/android";
+
+    /**
+     * @return Whether the current node ofthe  {@link XmlPullParser} has an attribute with the
+     * specified {@code attrName}.
+     */
+    public static boolean hasAttribute(@NonNull XmlPullParser parser, @NonNull String attrName) {
+        return parser.getAttributeValue(NAMESPACE, attrName) != null;
+    }
+
+    /**
+     * Retrieves a float attribute value. In addition to the styleable resource ID, we also make
+     * sure that the attribute name matches.
+     *
+     * @return a float value in the {@link TypedArray} with the specified {@code resId}, or
+     * {@code defaultValue} if it does not exist.
+     */
+    public static float getNamedFloat(@NonNull TypedArray a, @NonNull XmlPullParser parser,
+            @NonNull String attrName, @StyleableRes int resId, float defaultValue) {
+        final boolean hasAttr = hasAttribute(parser, attrName);
+        if (!hasAttr) {
+            return defaultValue;
+        } else {
+            return a.getFloat(resId, defaultValue);
+        }
+    }
+
+    /**
+     * Retrieves a boolean attribute value. In addition to the styleable resource ID, we also make
+     * sure that the attribute name matches.
+     *
+     * @return a boolean value in the {@link TypedArray} with the specified {@code resId}, or
+     * {@code defaultValue} if it does not exist.
+     */
+    public static boolean getNamedBoolean(@NonNull TypedArray a, @NonNull XmlPullParser parser,
+            String attrName, @StyleableRes int resId, boolean defaultValue) {
+        final boolean hasAttr = hasAttribute(parser, attrName);
+        if (!hasAttr) {
+            return defaultValue;
+        } else {
+            return a.getBoolean(resId, defaultValue);
+        }
+    }
+
+    /**
+     * Retrieves an int attribute value. In addition to the styleable resource ID, we also make
+     * sure that the attribute name matches.
+     *
+     * @return an int value in the {@link TypedArray} with the specified {@code resId}, or
+     * {@code defaultValue} if it does not exist.
+     */
+    public static int getNamedInt(TypedArray a, XmlPullParser parser, String attrName,
+            int resId, int defaultValue) {
+        final boolean hasAttr = hasAttribute(parser, attrName);
+        if (!hasAttr) {
+            return defaultValue;
+        } else {
+            return a.getInt(resId, defaultValue);
+        }
+    }
+
+    /**
+     * Retrieves a color attribute value. In addition to the styleable resource ID, we also make
+     * sure that the attribute name matches.
+     *
+     * @return a color value in the {@link TypedArray} with the specified {@code resId}, or
+     * {@code defaultValue} if it does not exist.
+     */
+    @ColorInt
+    public static int getNamedColor(@NonNull TypedArray a, @NonNull XmlPullParser parser,
+            String attrName, @StyleableRes int resId, @ColorInt int defaultValue) {
+        final boolean hasAttr = hasAttribute(parser, attrName);
+        if (!hasAttr) {
+            return defaultValue;
+        } else {
+            return a.getColor(resId, defaultValue);
+        }
+    }
+
+    /**
+     * @return a boolean value of {@code index}. If it does not exist, a boolean value of
+     * {@code fallbackIndex}. If it still does not exist, {@code defaultValue}.
+     */
+    public static boolean getBoolean(TypedArray a, @StyleableRes int index,
+            @StyleableRes int fallbackIndex, boolean defaultValue) {
+        boolean val = a.getBoolean(fallbackIndex, defaultValue);
+        return a.getBoolean(index, val);
+    }
+
+    /**
+     * @return a drawable value of {@code index}. If it does not exist, a drawable value of
+     * {@code fallbackIndex}. If it still does not exist, {@code null}.
+     */
+    public static Drawable getDrawable(TypedArray a, @StyleableRes int index,
+            @StyleableRes int fallbackIndex) {
+        Drawable val = a.getDrawable(index);
+        if (val == null) {
+            val = a.getDrawable(fallbackIndex);
+        }
+        return val;
+    }
+
+    /**
+     * @return an int value of {@code index}. If it does not exist, an int value of
+     * {@code fallbackIndex}. If it still does not exist, {@code defaultValue}.
+     */
+    public static int getInt(TypedArray a, @StyleableRes int index,
+            @StyleableRes int fallbackIndex, int defaultValue) {
+        int val = a.getInt(fallbackIndex, defaultValue);
+        return a.getInt(index, val);
+    }
+
+    /**
+     * @return a resource ID value of {@code index}. If it does not exist, a resource ID value of
+     * {@code fallbackIndex}. If it still does not exist, {@code defaultValue}.
+     */
+    @AnyRes
+    public static int getResourceId(TypedArray a, @StyleableRes int index,
+            @StyleableRes int fallbackIndex, @AnyRes int defaultValue) {
+        int val = a.getResourceId(fallbackIndex, defaultValue);
+        return a.getResourceId(index, val);
+    }
+
+    /**
+     * @return a string value of {@code index}. If it does not exist, a string value of
+     * {@code fallbackIndex}. If it still does not exist, {@code null}.
+     */
+    public static String getString(TypedArray a, @StyleableRes int index,
+            @StyleableRes int fallbackIndex) {
+        String val = a.getString(index);
+        if (val == null) {
+            val = a.getString(fallbackIndex);
+        }
+        return val;
+    }
+
+    /**
+     * Retrieves a text attribute value with the specified fallback ID.
+     *
+     * @return a text value of {@code index}. If it does not exist, a text value of
+     * {@code fallbackIndex}. If it still does not exist, {@code null}.
+     */
+    public static CharSequence getText(TypedArray a, @StyleableRes int index,
+            @StyleableRes int fallbackIndex) {
+        CharSequence val = a.getText(index);
+        if (val == null) {
+            val = a.getText(fallbackIndex);
+        }
+        return val;
+    }
+
+    /**
+     * Retrieves a string array attribute value with the specified fallback ID.
+     *
+     * @return a string array value of {@code index}. If it does not exist, a string array value
+     * of {@code fallbackIndex}. If it still does not exist, {@code null}.
+     */
+    public static CharSequence[] getTextArray(TypedArray a, @StyleableRes int index,
+            @StyleableRes int fallbackIndex) {
+        CharSequence[] val = a.getTextArray(index);
+        if (val == null) {
+            val = a.getTextArray(fallbackIndex);
+        }
+        return val;
+    }
+
+    /**
+     * @return The resource ID value in the {@code context} specified by {@code attr}. If it does
+     * not exist, {@code fallbackAttr}.
+     */
+    public static int getAttr(Context context, int attr, int fallbackAttr) {
+        TypedValue value = new TypedValue();
+        context.getTheme().resolveAttribute(attr, value, true);
+        if (value.resourceId != 0) {
+            return attr;
+        }
+        return fallbackAttr;
+    }
+}
diff --git a/compat/java/android/support/v4/net/ConnectivityManagerCompat.java b/compat/java/android/support/v4/net/ConnectivityManagerCompat.java
index f9ff971..5c61193 100644
--- a/compat/java/android/support/v4/net/ConnectivityManagerCompat.java
+++ b/compat/java/android/support/v4/net/ConnectivityManagerCompat.java
@@ -16,6 +16,8 @@
 
 package android.support.v4.net;
 
+import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
+import static android.net.ConnectivityManager.TYPE_ETHERNET;
 import static android.net.ConnectivityManager.TYPE_MOBILE;
 import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
 import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
@@ -30,6 +32,7 @@
 import android.net.NetworkInfo;
 import android.os.Build;
 import android.support.annotation.IntDef;
+import android.support.annotation.RequiresApi;
 import android.support.annotation.RestrictTo;
 
 import java.lang.annotation.Retention;
@@ -51,7 +54,7 @@
     /** @hide */
     @RestrictTo(LIBRARY_GROUP)
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef(flag = false, value = {
+    @IntDef(value = {
             RESTRICT_BACKGROUND_STATUS_DISABLED,
             RESTRICT_BACKGROUND_STATUS_WHITELISTED,
             RESTRICT_BACKGROUND_STATUS_ENABLED,
@@ -82,7 +85,8 @@
      */
     public static final int RESTRICT_BACKGROUND_STATUS_ENABLED = 3;
 
-    static class BaseConnectivityManagerCompatImpl implements ConnectivityManagerCompatImpl {
+    static class ConnectivityManagerCompatBaseImpl implements ConnectivityManagerCompatImpl {
+        @SuppressWarnings("deprecation")
         @Override
         public boolean isActiveNetworkMetered(ConnectivityManager cm) {
             final NetworkInfo info = cm.getActiveNetworkInfo();
@@ -101,6 +105,8 @@
                 case TYPE_WIMAX:
                     return true;
                 case TYPE_WIFI:
+                case TYPE_BLUETOOTH:
+                case TYPE_ETHERNET:
                     return false;
                 default:
                     // err on side of caution
@@ -114,28 +120,20 @@
         }
     }
 
-    static class HoneycombMR2ConnectivityManagerCompatImpl
-            extends BaseConnectivityManagerCompatImpl {
+    @RequiresApi(16)
+    static class ConnectivityManagerCompatApi16Impl extends ConnectivityManagerCompatBaseImpl {
         @Override
         public boolean isActiveNetworkMetered(ConnectivityManager cm) {
-            return ConnectivityManagerCompatHoneycombMR2.isActiveNetworkMetered(cm);
+            return cm.isActiveNetworkMetered();
         }
     }
 
-    static class JellyBeanConnectivityManagerCompatImpl
-            extends HoneycombMR2ConnectivityManagerCompatImpl {
-        @Override
-        public boolean isActiveNetworkMetered(ConnectivityManager cm) {
-            return ConnectivityManagerCompatJellyBean.isActiveNetworkMetered(cm);
-        }
-    }
-
-    static class Api24ConnectivityManagerCompatImpl
-            extends JellyBeanConnectivityManagerCompatImpl {
+    @RequiresApi(24)
+    static class ConnectivityManagerCompatApi24Impl extends ConnectivityManagerCompatApi16Impl {
         @Override
         public int getRestrictBackgroundStatus(ConnectivityManager cm) {
             //noinspection ResourceType
-            return ConnectivityManagerCompatApi24.getRestrictBackgroundStatus(cm);
+            return cm.getRestrictBackgroundStatus();
         }
     }
 
@@ -143,13 +141,11 @@
 
     static {
         if (Build.VERSION.SDK_INT >= 24) {
-            IMPL = new Api24ConnectivityManagerCompatImpl();
+            IMPL = new ConnectivityManagerCompatApi24Impl();
         } else if (Build.VERSION.SDK_INT >= 16) {
-            IMPL = new JellyBeanConnectivityManagerCompatImpl();
-        } else if (Build.VERSION.SDK_INT >= 13) {
-            IMPL = new HoneycombMR2ConnectivityManagerCompatImpl();
+            IMPL = new ConnectivityManagerCompatApi16Impl();
         } else {
-            IMPL = new BaseConnectivityManagerCompatImpl();
+            IMPL = new ConnectivityManagerCompatBaseImpl();
         }
     }
 
diff --git a/compat/java/android/support/v4/net/TrafficStatsCompat.java b/compat/java/android/support/v4/net/TrafficStatsCompat.java
index 2e0fa69..5c76b59 100644
--- a/compat/java/android/support/v4/net/TrafficStatsCompat.java
+++ b/compat/java/android/support/v4/net/TrafficStatsCompat.java
@@ -16,171 +16,86 @@
 
 package android.support.v4.net;
 
+import android.annotation.TargetApi;
+import android.net.TrafficStats;
 import android.os.Build;
+import android.os.ParcelFileDescriptor;
 
 import java.net.DatagramSocket;
 import java.net.Socket;
 import java.net.SocketException;
 
 /**
- * Helper for accessing features in TrafficStats introduced after API level 14
+ * Helper for accessing features in {@link TrafficStats} introduced after API level 14
  * in a backwards compatible fashion.
  */
 public final class TrafficStatsCompat {
-
-    interface TrafficStatsCompatImpl {
-        void clearThreadStatsTag();
-        int getThreadStatsTag();
-        void incrementOperationCount(int operationCount);
-        void incrementOperationCount(int tag, int operationCount);
-        void setThreadStatsTag(int tag);
-        void tagSocket(Socket socket) throws SocketException;
-        void untagSocket(Socket socket) throws SocketException;
-        void tagDatagramSocket(DatagramSocket socket) throws SocketException;
-        void untagDatagramSocket(DatagramSocket socket) throws SocketException;
-    }
-
-    static class BaseTrafficStatsCompatImpl implements TrafficStatsCompatImpl {
-        private static class SocketTags {
-            public int statsTag = -1;
-
-            SocketTags() {
-            }
+    static class TrafficStatsCompatBaseImpl {
+        public void tagDatagramSocket(DatagramSocket socket) throws SocketException {
+            final ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket);
+            TrafficStats.tagSocket(new DatagramSocketWrapper(socket, pfd.getFileDescriptor()));
+            // The developer is still using the FD, so we need to detach it to
+            // prevent the PFD finalizer from closing it in their face. We had to
+            // wait until after the tagging call above, since detaching clears out
+            // the getFileDescriptor() result which tagging depends on.
+            pfd.detachFd();
         }
 
-        private ThreadLocal<SocketTags> mThreadSocketTags = new ThreadLocal<SocketTags>() {
-            @Override
-            protected SocketTags initialValue() {
-                return new SocketTags();
-            }
-        };
-
-        @Override
-        public void clearThreadStatsTag() {
-            mThreadSocketTags.get().statsTag = -1;
-        }
-
-        @Override
-        public int getThreadStatsTag() {
-            return mThreadSocketTags.get().statsTag;
-        }
-
-        @Override
-        public void incrementOperationCount(int operationCount) {
-        }
-
-        @Override
-        public void incrementOperationCount(int tag, int operationCount) {
-        }
-
-        @Override
-        public void setThreadStatsTag(int tag) {
-            mThreadSocketTags.get().statsTag = tag;
-        }
-
-        @Override
-        public void tagSocket(Socket socket) {
-        }
-
-        @Override
-        public void untagSocket(Socket socket) {
-        }
-
-        @Override
-        public void tagDatagramSocket(DatagramSocket socket) {
-        }
-
-        @Override
-        public void untagDatagramSocket(DatagramSocket socket) {
+        public void untagDatagramSocket(DatagramSocket socket) throws SocketException {
+            final ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket);
+            TrafficStats.untagSocket(new DatagramSocketWrapper(socket, pfd.getFileDescriptor()));
+            // The developer is still using the FD, so we need to detach it to
+            // prevent the PFD finalizer from closing it in their face. We had to
+            // wait until after the tagging call above, since detaching clears out
+            // the getFileDescriptor() result which tagging depends on.
+            pfd.detachFd();
         }
     }
 
-    static class IcsTrafficStatsCompatImpl implements TrafficStatsCompatImpl {
-        @Override
-        public void clearThreadStatsTag() {
-            TrafficStatsCompatIcs.clearThreadStatsTag();
-        }
-
-        @Override
-        public int getThreadStatsTag() {
-            return TrafficStatsCompatIcs.getThreadStatsTag();
-        }
-
-        @Override
-        public void incrementOperationCount(int operationCount) {
-            TrafficStatsCompatIcs.incrementOperationCount(operationCount);
-        }
-
-        @Override
-        public void incrementOperationCount(int tag, int operationCount) {
-            TrafficStatsCompatIcs.incrementOperationCount(tag, operationCount);
-        }
-
-        @Override
-        public void setThreadStatsTag(int tag) {
-            TrafficStatsCompatIcs.setThreadStatsTag(tag);
-        }
-
-        @Override
-        public void tagSocket(Socket socket) throws SocketException {
-            TrafficStatsCompatIcs.tagSocket(socket);
-        }
-
-        @Override
-        public void untagSocket(Socket socket) throws SocketException {
-            TrafficStatsCompatIcs.untagSocket(socket);
-        }
-
+    @TargetApi(24)
+    static class TrafficStatsCompatApi24Impl extends TrafficStatsCompatBaseImpl {
         @Override
         public void tagDatagramSocket(DatagramSocket socket) throws SocketException {
-            TrafficStatsCompatIcs.tagDatagramSocket(socket);
+            TrafficStats.tagDatagramSocket(socket);
         }
 
         @Override
         public void untagDatagramSocket(DatagramSocket socket) throws SocketException {
-            TrafficStatsCompatIcs.untagDatagramSocket(socket);
+            TrafficStats.untagDatagramSocket(socket);
         }
     }
 
-    static class Api24TrafficStatsCompatImpl extends IcsTrafficStatsCompatImpl {
-        @Override
-        public void tagDatagramSocket(DatagramSocket socket) throws SocketException {
-            TrafficStatsCompatApi24.tagDatagramSocket(socket);
-        }
-
-        @Override
-        public void untagDatagramSocket(DatagramSocket socket) throws SocketException {
-            TrafficStatsCompatApi24.untagDatagramSocket(socket);
-        }
-    }
-
-    private static final TrafficStatsCompatImpl IMPL;
+    private static final TrafficStatsCompatBaseImpl IMPL;
 
     static {
-        if ("N".equals(Build.VERSION.CODENAME)) {
-            IMPL = new Api24TrafficStatsCompatImpl();
-        } else if (Build.VERSION.SDK_INT >= 14) {
-            IMPL = new IcsTrafficStatsCompatImpl();
+        if (Build.VERSION.SDK_INT >= 24) {
+            IMPL = new TrafficStatsCompatApi24Impl();
         } else {
-            IMPL = new BaseTrafficStatsCompatImpl();
+            IMPL = new TrafficStatsCompatBaseImpl();
         }
     }
 
     /**
      * Clear active tag used when accounting {@link Socket} traffic originating
      * from the current thread.
+     *
+     * @deprecated Use {@link TrafficStats#clearThreadStatsTag()} directly.
      */
+    @Deprecated
     public static void clearThreadStatsTag() {
-        IMPL.clearThreadStatsTag();
+        TrafficStats.clearThreadStatsTag();
     }
 
     /**
      * Get the active tag used when accounting {@link Socket} traffic originating
      * from the current thread. Only one active tag per thread is supported.
      * {@link #tagSocket(Socket)}.
+     *
+     * @deprecated Use {@link TrafficStats#getThreadStatsTag()} directly.
      */
+    @Deprecated
     public static int getThreadStatsTag() {
-        return IMPL.getThreadStatsTag();
+        return TrafficStats.getThreadStatsTag();
     }
 
     /**
@@ -189,9 +104,12 @@
      * bytes-per-operation.
      *
      * @param operationCount Number of operations to increment count by.
+     *
+     * @deprecated Use {@link TrafficStats#incrementOperationCount(int)} directly.
      */
+    @Deprecated
     public static void incrementOperationCount(int operationCount) {
-        IMPL.incrementOperationCount(operationCount);
+        TrafficStats.incrementOperationCount(operationCount);
     }
 
     /**
@@ -200,9 +118,12 @@
      *
      * @param tag Accounting tag used in {@link #setThreadStatsTag(int)}.
      * @param operationCount Number of operations to increment count by.
+     *
+     * @deprecated Use {@link TrafficStats#incrementOperationCount(int, int)} directly.
      */
+    @Deprecated
     public static void incrementOperationCount(int tag, int operationCount) {
-        IMPL.incrementOperationCount(tag, operationCount);
+        TrafficStats.incrementOperationCount(tag, operationCount);
     }
 
     /**
@@ -215,9 +136,12 @@
      * Tags between {@code 0xFFFFFF00} and {@code 0xFFFFFFFF} are reserved and
      * used internally by system services like DownloadManager when performing
      * traffic on behalf of an application.
+     *
+     * @deprecated Use {@link TrafficStats#setThreadStatsTag(int)} directly.
      */
+    @Deprecated
     public static void setThreadStatsTag(int tag) {
-        IMPL.setThreadStatsTag(tag);
+        TrafficStats.setThreadStatsTag(tag);
     }
 
     /**
@@ -227,16 +151,22 @@
      * statistics parameters.
      *
      * @see #setThreadStatsTag(int)
+     *
+     * @deprecated Use {@link TrafficStats#tagSocket(Socket)} directly.
      */
+    @Deprecated
     public static void tagSocket(Socket socket) throws SocketException {
-        IMPL.tagSocket(socket);
+        TrafficStats.tagSocket(socket);
     }
 
     /**
      * Remove any statistics parameters from the given {@link Socket}.
+     *
+     * @deprecated Use {@link TrafficStats#untagSocket(Socket)} directly.
      */
+    @Deprecated
     public static void untagSocket(Socket socket) throws SocketException {
-        IMPL.untagSocket(socket);
+        TrafficStats.untagSocket(socket);
     }
 
     /**
diff --git a/compat/java/android/support/v4/text/ICUCompat.java b/compat/java/android/support/v4/text/ICUCompat.java
index 0632513..cd26961 100644
--- a/compat/java/android/support/v4/text/ICUCompat.java
+++ b/compat/java/android/support/v4/text/ICUCompat.java
@@ -16,47 +16,35 @@
 
 package android.support.v4.text;
 
+import android.annotation.TargetApi;
 import android.os.Build;
+import android.support.annotation.Nullable;
 
 import java.util.Locale;
 
 public final class ICUCompat {
-
-    interface ICUCompatImpl {
-        public String maximizeAndGetScript(Locale locale);
-    }
-
-    static class ICUCompatImplBase implements ICUCompatImpl {
-        @Override
-        public String maximizeAndGetScript(Locale locale) {
-            return null;
-        }
-    }
-
-    static class ICUCompatImplIcs implements ICUCompatImpl {
-        @Override
+    static class ICUCompatBaseImpl {
         public String maximizeAndGetScript(Locale locale) {
             return ICUCompatIcs.maximizeAndGetScript(locale);
         }
     }
 
-    static class ICUCompatImplLollipop implements ICUCompatImpl {
+    @TargetApi(23)
+    static class ICUCompatApi21Impl extends ICUCompatBaseImpl {
         @Override
         public String maximizeAndGetScript(Locale locale) {
-            return ICUCompatApi23.maximizeAndGetScript(locale);
+            return ICUCompatApi21.maximizeAndGetScript(locale);
         }
     }
 
-    private static final ICUCompatImpl IMPL;
+    private static final ICUCompatBaseImpl IMPL;
 
     static {
         final int version = Build.VERSION.SDK_INT;
         if (version >= 21) {
-            IMPL = new ICUCompatImplLollipop();
-        } else if (version >= 14) {
-            IMPL = new ICUCompatImplIcs();
+            IMPL = new ICUCompatApi21Impl();
         } else {
-            IMPL = new ICUCompatImplBase();
+            IMPL = new ICUCompatBaseImpl();
         }
     }
 
@@ -81,8 +69,9 @@
      * "sh" maximizes to "sr_Latn_RS" (Note this will not reverse.)
      * "zh_Hani" maximizes to "zh_Hans_CN" (Note this will not reverse.)
      *
-     * @return
+     * @return The script for a given Locale if ICU library is available, otherwise null.
      */
+    @Nullable
     public static String maximizeAndGetScript(Locale locale) {
         return IMPL.maximizeAndGetScript(locale);
     }
diff --git a/compat/java/android/support/v4/widget/SearchViewCompat.java b/compat/java/android/support/v4/widget/SearchViewCompat.java
index 2b69f55..83cb0fc 100644
--- a/compat/java/android/support/v4/widget/SearchViewCompat.java
+++ b/compat/java/android/support/v4/widget/SearchViewCompat.java
@@ -17,267 +17,28 @@
 package android.support.v4.widget;
 
 import android.app.SearchManager;
+import android.app.SearchableInfo;
 import android.content.ComponentName;
 import android.content.Context;
-import android.os.Build;
 import android.view.View;
+import android.widget.SearchView;
 import android.widget.TextView;
 
 /**
- * Helper for accessing features in {@link android.widget.SearchView}
+ * Helper for accessing features in {@link SearchView}
  * introduced after API level 4 in a backwards compatible fashion.
+ *
+ * @deprecated Use {@link SearchView} directly.
  */
+@Deprecated
 public final class SearchViewCompat {
-
-    interface SearchViewCompatImpl {
-        View newSearchView(Context context);
-        void setSearchableInfo(View searchView, ComponentName searchableComponent);
-        void setImeOptions(View searchView, int imeOptions);
-        void setInputType(View searchView, int inputType);
-        Object newOnQueryTextListener(OnQueryTextListener listener);
-        void setOnQueryTextListener(View searchView, OnQueryTextListener listener);
-        Object newOnCloseListener(OnCloseListener listener);
-        void setOnCloseListener(View searchView, OnCloseListener listener);
-        CharSequence getQuery(View searchView);
-        void setQuery(View searchView, CharSequence query, boolean submit);
-        void setQueryHint(View searchView, CharSequence hint);
-        void setIconified(View searchView, boolean iconify);
-        boolean isIconified(View searchView);
-        void setSubmitButtonEnabled(View searchView, boolean enabled);
-        boolean isSubmitButtonEnabled(View searchView);
-        void setQueryRefinementEnabled(View searchView, boolean enable);
-        boolean isQueryRefinementEnabled(View searchView);
-        void setMaxWidth(View searchView, int maxpixels);
-    }
-
-    static class SearchViewCompatStubImpl implements SearchViewCompatImpl {
-
-        @Override
-        public View newSearchView(Context context) {
-            return null;
+    private static void checkIfLegalArg(View searchView) {
+        if (searchView == null) {
+            throw new IllegalArgumentException("searchView must be non-null");
         }
-
-        @Override
-        public void setSearchableInfo(View searchView, ComponentName searchableComponent) {
-        }
-
-        @Override
-        public void setImeOptions(View searchView, int imeOptions) {
-        }
-
-        @Override
-        public void setInputType(View searchView, int inputType) {
-        }
-
-        @Override
-        public Object newOnQueryTextListener(OnQueryTextListener listener) {
-            return null;
-        }
-
-        @Override
-        public void setOnQueryTextListener(View searchView, OnQueryTextListener listener) {
-        }
-
-        @Override
-        public Object newOnCloseListener(OnCloseListener listener) {
-            return null;
-        }
-
-        @Override
-        public void setOnCloseListener(View searchView, OnCloseListener listener) {
-        }
-
-        @Override
-        public CharSequence getQuery(View searchView) {
-            return null;
-        }
-
-        @Override
-        public void setQuery(View searchView, CharSequence query, boolean submit) {
-        }
-
-        @Override
-        public void setQueryHint(View searchView, CharSequence hint) {
-        }
-
-        @Override
-        public void setIconified(View searchView, boolean iconify) {
-        }
-
-        @Override
-        public boolean isIconified(View searchView) {
-            return true;
-        }
-
-        @Override
-        public void setSubmitButtonEnabled(View searchView, boolean enabled) {
-        }
-
-        @Override
-        public boolean isSubmitButtonEnabled(View searchView) {
-            return false;
-        }
-
-        @Override
-        public void setQueryRefinementEnabled(View searchView, boolean enable) {
-        }
-
-        @Override
-        public boolean isQueryRefinementEnabled(View searchView) {
-            return false;
-        }
-
-        @Override
-        public void setMaxWidth(View searchView, int maxpixels) {
-        }
-    }
-
-    static class SearchViewCompatHoneycombImpl extends SearchViewCompatStubImpl {
-
-        @Override
-        public View newSearchView(Context context) {
-            return SearchViewCompatHoneycomb.newSearchView(context);
-        }
-
-        @Override
-        public void setSearchableInfo(View searchView, ComponentName searchableComponent) {
-            checkIfLegalArg(searchView);
-            SearchViewCompatHoneycomb.setSearchableInfo(searchView, searchableComponent);
-        }
-
-        @Override
-        public Object newOnQueryTextListener(final OnQueryTextListener listener) {
-            return SearchViewCompatHoneycomb.newOnQueryTextListener(
-                    new SearchViewCompatHoneycomb.OnQueryTextListenerCompatBridge() {
-                        @Override
-                        public boolean onQueryTextSubmit(String query) {
-                            return listener.onQueryTextSubmit(query);
-                        }
-                        @Override
-                        public boolean onQueryTextChange(String newText) {
-                            return listener.onQueryTextChange(newText);
-                        }
-                    });
-        }
-
-        @Override
-        public void setOnQueryTextListener(View searchView, OnQueryTextListener listener) {
-            checkIfLegalArg(searchView);
-            SearchViewCompatHoneycomb.setOnQueryTextListener(searchView,
-                    newOnQueryTextListener(listener));
-        }
-
-        @Override
-        public Object newOnCloseListener(final OnCloseListener listener) {
-            return SearchViewCompatHoneycomb.newOnCloseListener(
-                    new SearchViewCompatHoneycomb.OnCloseListenerCompatBridge() {
-                        @Override
-                        public boolean onClose() {
-                            return listener.onClose();
-                        }
-                    });
-        }
-
-        @Override
-        public void setOnCloseListener(View searchView, OnCloseListener listener) {
-            checkIfLegalArg(searchView);
-            SearchViewCompatHoneycomb.setOnCloseListener(searchView, newOnCloseListener(listener));
-        }
-
-        @Override
-        public CharSequence getQuery(View searchView) {
-            checkIfLegalArg(searchView);
-            return SearchViewCompatHoneycomb.getQuery(searchView);
-        }
-
-        @Override
-        public void setQuery(View searchView, CharSequence query, boolean submit) {
-            checkIfLegalArg(searchView);
-            SearchViewCompatHoneycomb.setQuery(searchView, query, submit);
-        }
-
-        @Override
-        public void setQueryHint(View searchView, CharSequence hint) {
-            checkIfLegalArg(searchView);
-            SearchViewCompatHoneycomb.setQueryHint(searchView, hint);
-        }
-
-        @Override
-        public void setIconified(View searchView, boolean iconify) {
-            checkIfLegalArg(searchView);
-            SearchViewCompatHoneycomb.setIconified(searchView, iconify);
-        }
-
-        @Override
-        public boolean isIconified(View searchView) {
-            checkIfLegalArg(searchView);
-            return SearchViewCompatHoneycomb.isIconified(searchView);
-        }
-
-        @Override
-        public void setSubmitButtonEnabled(View searchView, boolean enabled) {
-            checkIfLegalArg(searchView);
-            SearchViewCompatHoneycomb.setSubmitButtonEnabled(searchView, enabled);
-        }
-
-        @Override
-        public boolean isSubmitButtonEnabled(View searchView) {
-            checkIfLegalArg(searchView);
-            return SearchViewCompatHoneycomb.isSubmitButtonEnabled(searchView);
-        }
-
-        @Override
-        public void setQueryRefinementEnabled(View searchView, boolean enable) {
-            checkIfLegalArg(searchView);
-            SearchViewCompatHoneycomb.setQueryRefinementEnabled(searchView, enable);
-        }
-
-        @Override
-        public boolean isQueryRefinementEnabled(View searchView) {
-            checkIfLegalArg(searchView);
-            return SearchViewCompatHoneycomb.isQueryRefinementEnabled(searchView);
-        }
-
-        @Override
-        public void setMaxWidth(View searchView, int maxpixels) {
-            checkIfLegalArg(searchView);
-            SearchViewCompatHoneycomb.setMaxWidth(searchView, maxpixels);
-        }
-
-        protected void checkIfLegalArg(View searchView) {
-            SearchViewCompatHoneycomb.checkIfLegalArg(searchView);
-        }
-    }
-
-    static class SearchViewCompatIcsImpl extends SearchViewCompatHoneycombImpl {
-
-        @Override
-        public View newSearchView(Context context) {
-            return SearchViewCompatIcs.newSearchView(context);
-        }
-
-        @Override
-        public void setImeOptions(View searchView, int imeOptions) {
-            checkIfLegalArg(searchView);
-            SearchViewCompatIcs.setImeOptions(searchView, imeOptions);
-        }
-
-        @Override
-        public void setInputType(View searchView, int inputType) {
-            checkIfLegalArg(searchView);
-            SearchViewCompatIcs.setInputType(searchView, inputType);
-        }
-    }
-
-    private static final SearchViewCompatImpl IMPL;
-
-    static {
-        if (Build.VERSION.SDK_INT >= 14) { // ICS
-            IMPL = new SearchViewCompatIcsImpl();
-        } else if (Build.VERSION.SDK_INT >= 11) { // Honeycomb
-            IMPL = new SearchViewCompatHoneycombImpl();
-        } else {
-            IMPL = new SearchViewCompatStubImpl();
+        if (!(searchView instanceof SearchView)) {
+            throw new IllegalArgumentException("searchView must be an instance of "
+                    + "android.widget.SearchView");
         }
     }
 
@@ -291,9 +52,12 @@
      * @param context The Context the view is running in.
      * @return A SearchView instance if the class is present on the current
      *         platform, null otherwise.
+     *
+     * @deprecated Use {@link SearchView} constructor directly.
      */
+    @Deprecated
     public static View newSearchView(Context context) {
-        return IMPL.newSearchView(context);
+        return new SearchView(context);
     }
 
     /**
@@ -305,9 +69,16 @@
      * @param searchableComponent The application component whose
      * {@link android.app.SearchableInfo} should be loaded and applied to
      * the SearchView.
+     *
+     * @deprecated Use {@link SearchView#setSearchableInfo(SearchableInfo)} directly.
      */
+    @Deprecated
     public static void setSearchableInfo(View searchView, ComponentName searchableComponent) {
-        IMPL.setSearchableInfo(searchView, searchableComponent);
+        checkIfLegalArg(searchView);
+        SearchManager searchManager = (SearchManager)
+                searchView.getContext().getSystemService(Context.SEARCH_SERVICE);
+        ((SearchView) searchView).setSearchableInfo(
+                searchManager.getSearchableInfo(searchableComponent));
     }
 
     /**
@@ -318,9 +89,13 @@
      * @see TextView#setImeOptions(int)
      * @param searchView The SearchView to operate on.
      * @param imeOptions the options to set on the query text field
+     *
+     * @deprecated Use {@link SearchView#setImeOptions(int)} directly.
      */
+    @Deprecated
     public static void setImeOptions(View searchView, int imeOptions) {
-        IMPL.setImeOptions(searchView, imeOptions);
+        checkIfLegalArg(searchView);
+        ((SearchView) searchView).setImeOptions(imeOptions);
     }
 
     /**
@@ -331,9 +106,13 @@
      * @see TextView#setInputType(int)
      * @param searchView The SearchView to operate on.
      * @param inputType the input type to set on the query text field
+     *
+     * @deprecated Use {@link SearchView#setInputType(int)} directly.
      */
+    @Deprecated
     public static void setInputType(View searchView, int inputType) {
-        IMPL.setInputType(searchView, inputType);
+        checkIfLegalArg(searchView);
+        ((SearchView) searchView).setInputType(inputType);
     }
 
     /**
@@ -342,13 +121,33 @@
      * @param searchView The SearchView in which to register the listener.
      * @param listener the listener object that receives callbacks when the user performs
      *     actions in the SearchView such as clicking on buttons or typing a query.
+     *
+     * @deprecated Use {@link SearchView#setOnQueryTextListener(SearchView.OnQueryTextListener)}
+     * directly.
      */
+    @Deprecated
     public static void setOnQueryTextListener(View searchView, OnQueryTextListener listener) {
-        IMPL.setOnQueryTextListener(searchView, listener);
+        checkIfLegalArg(searchView);
+        ((SearchView) searchView).setOnQueryTextListener(newOnQueryTextListener(listener));
+    }
+
+    private static SearchView.OnQueryTextListener newOnQueryTextListener(
+            final OnQueryTextListener listener) {
+        return new SearchView.OnQueryTextListener() {
+            @Override
+            public boolean onQueryTextSubmit(String query) {
+                return listener.onQueryTextSubmit(query);
+            }
+
+            @Override
+            public boolean onQueryTextChange(String newText) {
+                return listener.onQueryTextChange(newText);
+            }
+        };
     }
 
     /**
-     * @deprecated Use {@link OnQueryTextListener} instead.
+     * @deprecated Use {@link SearchView.OnQueryTextListener} instead.
      */
     @Deprecated
     public static abstract class OnQueryTextListenerCompat implements OnQueryTextListener {
@@ -364,8 +163,9 @@
     }
 
     /**
-     * Callbacks for changes to the query text.
+     * @deprecated Use {@link SearchView.OnQueryTextListener} instead.
      */
+    @Deprecated
     public interface OnQueryTextListener {
         /**
          * Called when the user submits the query. This could be due to a key press on the
@@ -397,13 +197,26 @@
      *
      * @param searchView The SearchView in which to register the listener.
      * @param listener the listener to call when the user closes the SearchView.
+     *
+     * @deprecated Use {@link SearchView#setOnCloseListener(SearchView.OnCloseListener)} directly.
      */
+    @Deprecated
     public static void setOnCloseListener(View searchView, OnCloseListener listener) {
-        IMPL.setOnCloseListener(searchView, listener);
+        checkIfLegalArg(searchView);
+        ((SearchView) searchView).setOnCloseListener(newOnCloseListener(listener));
+    }
+
+    private static SearchView.OnCloseListener newOnCloseListener(final OnCloseListener listener) {
+        return new SearchView.OnCloseListener() {
+            @Override
+            public boolean onClose() {
+                return listener.onClose();
+            }
+        };
     }
 
     /**
-     * @deprecated Use {@link OnCloseListener} instead.
+     * @deprecated Use {@link SearchView.OnCloseListener} instead.
      */
     @Deprecated
     public static abstract class OnCloseListenerCompat implements OnCloseListener {
@@ -415,7 +228,10 @@
 
     /**
      * Callback for closing the query UI.
+     *
+     * @deprecated Use {@link SearchView.OnCloseListener} instead.
      */
+    @Deprecated
     public interface OnCloseListener {
         /**
          * The user is attempting to close the SearchView.
@@ -432,9 +248,13 @@
      * @param searchView The SearchView to operate on.
      *
      * @return the query string
+     *
+     * @deprecated Use {@link SearchView#getQuery()} directly.
      */
+    @Deprecated
     public static CharSequence getQuery(View searchView) {
-        return IMPL.getQuery(searchView);
+        checkIfLegalArg(searchView);
+        return ((SearchView) searchView).getQuery();
     }
 
     /**
@@ -445,9 +265,13 @@
      * text field.
      * @param submit whether to submit the query right now or only update the contents of
      * text field.
+     *
+     * @deprecated Use {@link SearchView#setQuery(CharSequence, boolean)} directly.
      */
+    @Deprecated
     public static void setQuery(View searchView, CharSequence query, boolean submit) {
-        IMPL.setQuery(searchView, query, submit);
+        checkIfLegalArg(searchView);
+        ((SearchView) searchView).setQuery(query, submit);
     }
 
     /**
@@ -456,9 +280,13 @@
      *
      * @param searchView The SearchView to operate on.
      * @param hint the hint text to display
+     *
+     * @deprecated Use {@link SearchView#setQueryHint(CharSequence)} directly.
      */
+    @Deprecated
     public static void setQueryHint(View searchView, CharSequence hint) {
-        IMPL.setQueryHint(searchView, hint);
+        checkIfLegalArg(searchView);
+        ((SearchView) searchView).setQueryHint(hint);
     }
 
     /**
@@ -471,9 +299,13 @@
      * @param searchView The SearchView to operate on.
      * @param iconify a true value will collapse the SearchView to an icon, while a false will
      * expand it.
+     *
+     * @deprecated Use {@link SearchView#setIconified(boolean)} directly.
      */
+    @Deprecated
     public static void setIconified(View searchView, boolean iconify) {
-        IMPL.setIconified(searchView, iconify);
+        checkIfLegalArg(searchView);
+        ((SearchView) searchView).setIconified(iconify);
     }
 
     /**
@@ -482,9 +314,13 @@
      * @param searchView The SearchView to operate on.
      * @return true if the SearchView is currently iconified, false if the search field is
      * fully visible.
+     *
+     * @deprecated Use {@link SearchView#isIconified()} directly.
      */
+    @Deprecated
     public static boolean isIconified(View searchView) {
-        return IMPL.isIconified(searchView);
+        checkIfLegalArg(searchView);
+        return ((SearchView) searchView).isIconified();
     }
 
     /**
@@ -495,9 +331,13 @@
      * @param searchView The SearchView to operate on.
      * @param enabled true to show a submit button for submitting queries, false if a submit
      * button is not required.
+     *
+     * @deprecated Use {@link SearchView#setSubmitButtonEnabled(boolean)} directly.
      */
+    @Deprecated
     public static void setSubmitButtonEnabled(View searchView, boolean enabled) {
-        IMPL.setSubmitButtonEnabled(searchView, enabled);
+        checkIfLegalArg(searchView);
+        ((SearchView) searchView).setSubmitButtonEnabled(enabled);
     }
 
     /**
@@ -505,9 +345,13 @@
      *
      * @param searchView The SearchView to operate on.
      * @return whether the submit button is enabled automatically when necessary
+     *
+     * @deprecated Use {@link SearchView#isSubmitButtonEnabled()} directly.
      */
+    @Deprecated
     public static boolean isSubmitButtonEnabled(View searchView) {
-        return IMPL.isSubmitButtonEnabled(searchView);
+        checkIfLegalArg(searchView);
+        return ((SearchView) searchView).isSubmitButtonEnabled();
     }
 
     /**
@@ -524,25 +368,37 @@
      *
      * @see SearchManager#SUGGEST_COLUMN_FLAGS
      * @see SearchManager#FLAG_QUERY_REFINEMENT
+     *
+     * @deprecated Use {@link SearchView#setQueryRefinementEnabled(boolean)} directly.
      */
+    @Deprecated
     public static void setQueryRefinementEnabled(View searchView, boolean enable) {
-        IMPL.setQueryRefinementEnabled(searchView, enable);
+        checkIfLegalArg(searchView);
+        ((SearchView) searchView).setQueryRefinementEnabled(enable);
     }
 
     /**
      * Returns whether query refinement is enabled for all items or only specific ones.
      * @param searchView The SearchView to operate on.
      * @return true if enabled for all items, false otherwise.
+     *
+     * @deprecated Use {@link SearchView#isQueryRefinementEnabled()} directly.
      */
+    @Deprecated
     public static boolean isQueryRefinementEnabled(View searchView) {
-        return IMPL.isQueryRefinementEnabled(searchView);
+        checkIfLegalArg(searchView);
+        return ((SearchView) searchView).isQueryRefinementEnabled();
     }
 
     /**
      * Makes the view at most this many pixels wide
      * @param searchView The SearchView to operate on.
+     *
+     * @deprecated Use {@link SearchView#setMaxWidth(int)} directly.
      */
+    @Deprecated
     public static void setMaxWidth(View searchView, int maxpixels) {
-        IMPL.setMaxWidth(searchView, maxpixels);
+        checkIfLegalArg(searchView);
+        ((SearchView) searchView).setMaxWidth(maxpixels);
     }
 }
diff --git a/compat/jellybean/android/support/v4/net/ConnectivityManagerCompatJellyBean.java b/compat/jellybean/android/support/v4/net/ConnectivityManagerCompatJellyBean.java
deleted file mode 100644
index 7e47298..0000000
--- a/compat/jellybean/android/support/v4/net/ConnectivityManagerCompatJellyBean.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.
- */
-
-package android.support.v4.net;
-
-import android.net.ConnectivityManager;
-import android.support.annotation.RequiresApi;
-
-/**
- * Implementation of ConnectivityManagerCompat that can use Jellybean APIs.
- */
-
-@RequiresApi(16)
-class ConnectivityManagerCompatJellyBean {
-    public static boolean isActiveNetworkMetered(ConnectivityManager cm) {
-        return cm.isActiveNetworkMetered();
-    }
-}
diff --git a/compat/tests/java/android/support/v4/app/RemoteInputTest.java b/compat/tests/java/android/support/v4/app/RemoteInputTest.java
index 08fdf0e..4c3d81b 100644
--- a/compat/tests/java/android/support/v4/app/RemoteInputTest.java
+++ b/compat/tests/java/android/support/v4/app/RemoteInputTest.java
@@ -94,6 +94,7 @@
         assertTrue(input.getAllowedDataTypes().contains(MIME_TYPE));
     }
 
+    @SdkSuppress(minSdkVersion = 17)
     @Test
     public void testRemoteInputBuilder_addAndGetDataResultsFromIntent() throws Throwable {
         Uri uri = Uri.parse("Some Uri");
@@ -106,6 +107,7 @@
         verifyIntentHasDataResults(intent, uri);
     }
 
+    @SdkSuppress(minSdkVersion = 17)
     @Test
     public void testRemoteInputBuilder_addAndGetTextResultsFromIntent() throws Throwable {
         CharSequence charSequence = "value doesn't matter";
diff --git a/compat/tests/java/android/support/v4/graphics/PaintCompatHasGlyphTest.java b/compat/tests/java/android/support/v4/graphics/PaintCompatHasGlyphTest.java
index 202d30f..26f0691 100644
--- a/compat/tests/java/android/support/v4/graphics/PaintCompatHasGlyphTest.java
+++ b/compat/tests/java/android/support/v4/graphics/PaintCompatHasGlyphTest.java
@@ -16,6 +16,8 @@
 
 package android.support.v4.graphics;
 
+import static android.os.Build.VERSION.SDK_INT;
+
 import static org.junit.Assert.assertEquals;
 
 import android.graphics.Paint;
@@ -37,10 +39,14 @@
         return Arrays.asList(new Object[][]{
                 {"B", true},
                 {"\uDB3F\uDFFD", false},
-                {"☺", true},
+                {"Ō", true},
+                {"£", true},
+                {"⅓", true},
                 {"Hello", false},
                 {"\u0020", true},  // white space
                 {"\t\t\t", false},  // more white space
+                {"☺", SDK_INT >= 16}, // glyph added in API 16
+                {"\uD83D\uDC66\uD83C\uDFFF", SDK_INT >= 24}, // glyph added in API 24
         });
     }
 
@@ -54,6 +60,8 @@
 
     @Test
     public void testHasGlyph() {
-        assertEquals(mExpectedResult, PaintCompat.hasGlyph(new Paint(), mTestString));
+        final boolean hasGlyph = PaintCompat.hasGlyph(new Paint(), mTestString);
+        assertEquals("hasGlyph() returned " + hasGlyph + " for '" + mTestString + "'",
+                mExpectedResult, hasGlyph);
     }
 }
diff --git a/core-ui/tests/res/values/styles.xml b/core-ui/tests/res/values/styles.xml
index ae6325b..e530e60 100644
--- a/core-ui/tests/res/values/styles.xml
+++ b/core-ui/tests/res/values/styles.xml
@@ -13,8 +13,8 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <style name="TestActivityTheme">
+<resources>
+    <style name="TestActivityTheme" parent="android:Theme.Holo">
         <item name="android:windowAnimationStyle">@null</item>
     </style>
     <style name="TextMediumStyle" parent="@android:style/TextAppearance.Medium">
diff --git a/core-utils/honeycomb/android/support/v4/app/TaskStackBuilderHoneycomb.java b/core-utils/honeycomb/android/support/v4/app/TaskStackBuilderHoneycomb.java
deleted file mode 100644
index e41fdd8..0000000
--- a/core-utils/honeycomb/android/support/v4/app/TaskStackBuilderHoneycomb.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.
- */
-
-package android.support.v4.app;
-
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.support.annotation.RequiresApi;
-
-/**
- * Implementation of TaskStackBuilder that can call Honeycomb APIs.
- */
-@RequiresApi(11)
-class TaskStackBuilderHoneycomb {
-    public static PendingIntent getActivitiesPendingIntent(Context context, int requestCode,
-            Intent[] intents, int flags) {
-        return PendingIntent.getActivities(context, requestCode, intents, flags);
-    }
-}
diff --git a/core-utils/java/android/support/v4/app/NavUtils.java b/core-utils/java/android/support/v4/app/NavUtils.java
index f9661a7..ae1bb10 100644
--- a/core-utils/java/android/support/v4/app/NavUtils.java
+++ b/core-utils/java/android/support/v4/app/NavUtils.java
@@ -16,6 +16,7 @@
 
 package android.support.v4.app;
 
+import android.annotation.TargetApi;
 import android.app.Activity;
 import android.content.ComponentName;
 import android.content.Context;
@@ -24,7 +25,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.support.annotation.Nullable;
-import android.support.v4.content.IntentCompat;
 import android.util.Log;
 
 /**
@@ -58,7 +58,7 @@
             try {
                 final String grandparent = NavUtils.getParentActivityName(activity, target);
                 final Intent parentIntent = grandparent == null
-                        ? IntentCompat.makeMainActivity(target)
+                        ? Intent.makeMainActivity(target)
                         : new Intent().setComponent(target);
                 return parentIntent;
             } catch (NameNotFoundException e) {
@@ -93,6 +93,7 @@
         }
     }
 
+    @TargetApi(16)
     static class NavUtilsImplJB extends NavUtilsImplBase {
 
         @Override
@@ -236,7 +237,7 @@
         final ComponentName target = new ComponentName(context, parentActivity);
         final String grandparent = getParentActivityName(context, target);
         final Intent parentIntent = grandparent == null
-                ? IntentCompat.makeMainActivity(target)
+                ? Intent.makeMainActivity(target)
                 : new Intent().setComponent(target);
         return parentIntent;
     }
@@ -261,7 +262,7 @@
                 componentName.getPackageName(), parentActivity);
         final String grandparent = getParentActivityName(context, target);
         final Intent parentIntent = grandparent == null
-                ? IntentCompat.makeMainActivity(target)
+                ? Intent.makeMainActivity(target)
                 : new Intent().setComponent(target);
         return parentIntent;
     }
diff --git a/core-utils/java/android/support/v4/app/TaskStackBuilder.java b/core-utils/java/android/support/v4/app/TaskStackBuilder.java
index 0358b46..d95e1a4 100644
--- a/core-utils/java/android/support/v4/app/TaskStackBuilder.java
+++ b/core-utils/java/android/support/v4/app/TaskStackBuilder.java
@@ -16,6 +16,7 @@
 
 package android.support.v4.app;
 
+import android.annotation.TargetApi;
 import android.app.Activity;
 import android.app.PendingIntent;
 import android.content.ComponentName;
@@ -25,7 +26,6 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.support.v4.content.ContextCompat;
-import android.support.v4.content.IntentCompat;
 import android.util.Log;
 
 import java.util.ArrayList;
@@ -73,49 +73,32 @@
         Intent getSupportParentActivityIntent();
     }
 
-    interface TaskStackBuilderImpl {
-        PendingIntent getPendingIntent(Context context, Intent[] intents, int requestCode,
-                int flags, Bundle options);
-    }
-
-    static class TaskStackBuilderImplBase implements TaskStackBuilderImpl {
+    static class TaskStackBuilderBaseImpl {
         public PendingIntent getPendingIntent(Context context, Intent[] intents, int requestCode,
                 int flags, Bundle options) {
-            Intent topIntent = new Intent(intents[intents.length - 1]);
-            topIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            return PendingIntent.getActivity(context, requestCode, topIntent, flags);
+            intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                    | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
+            return PendingIntent.getActivities(context, requestCode, intents, flags);
         }
     }
 
-    static class TaskStackBuilderImplHoneycomb implements TaskStackBuilderImpl {
+    @TargetApi(16)
+    static class TaskStackBuilderApi16Impl extends TaskStackBuilderBaseImpl {
         public PendingIntent getPendingIntent(Context context, Intent[] intents, int requestCode,
                 int flags, Bundle options) {
-            intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
-                    IntentCompat.FLAG_ACTIVITY_CLEAR_TASK |
-                    IntentCompat.FLAG_ACTIVITY_TASK_ON_HOME);
-            return TaskStackBuilderHoneycomb.getActivitiesPendingIntent(context, requestCode,
-                    intents, flags);
+            intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                    | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
+            return PendingIntent.getActivities(context, requestCode, intents, flags, options);
         }
     }
 
-    static class TaskStackBuilderImplJellybean implements TaskStackBuilderImpl {
-        public PendingIntent getPendingIntent(Context context, Intent[] intents, int requestCode,
-                int flags, Bundle options) {
-            intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
-                    IntentCompat.FLAG_ACTIVITY_CLEAR_TASK |
-                    IntentCompat.FLAG_ACTIVITY_TASK_ON_HOME);
-            return TaskStackBuilderJellybean.getActivitiesPendingIntent(context, requestCode,
-                    intents, flags, options);
-        }
-    }
-
-    private static final TaskStackBuilderImpl IMPL;
+    private static final TaskStackBuilderBaseImpl IMPL;
 
     static {
-        if (Build.VERSION.SDK_INT >= 11) {
-            IMPL = new TaskStackBuilderImplHoneycomb();
+        if (Build.VERSION.SDK_INT >= 16) {
+            IMPL = new TaskStackBuilderApi16Impl();
         } else {
-            IMPL = new TaskStackBuilderImplBase();
+            IMPL = new TaskStackBuilderBaseImpl();
         }
     }
 
@@ -322,9 +305,8 @@
         }
 
         Intent[] intents = mIntents.toArray(new Intent[mIntents.size()]);
-        intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
-                IntentCompat.FLAG_ACTIVITY_CLEAR_TASK |
-                IntentCompat.FLAG_ACTIVITY_TASK_ON_HOME);
+        intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
         if (!ContextCompat.startActivities(mSourceContext, intents, options)) {
             Intent topIntent = new Intent(intents[intents.length - 1]);
             topIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -367,9 +349,8 @@
         }
 
         Intent[] intents = mIntents.toArray(new Intent[mIntents.size()]);
-        intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
-                IntentCompat.FLAG_ACTIVITY_CLEAR_TASK |
-                IntentCompat.FLAG_ACTIVITY_TASK_ON_HOME);
+        intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
         // Appropriate flags will be added by the call below.
         return IMPL.getPendingIntent(mSourceContext, intents, requestCode, flags, options);
     }
@@ -385,9 +366,8 @@
         Intent[] intents = new Intent[mIntents.size()];
         if (intents.length == 0) return intents;
 
-        intents[0] = new Intent(mIntents.get(0)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
-                IntentCompat.FLAG_ACTIVITY_CLEAR_TASK |
-                IntentCompat.FLAG_ACTIVITY_TASK_ON_HOME);
+        intents[0] = new Intent(mIntents.get(0)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
         for (int i = 1; i < intents.length; i++) {
             intents[i] = new Intent(mIntents.get(i));
         }
diff --git a/core-utils/java/android/support/v4/content/res/TypedArrayUtils.java b/core-utils/java/android/support/v4/content/res/TypedArrayUtils.java
deleted file mode 100644
index be4ff11..0000000
--- a/core-utils/java/android/support/v4/content/res/TypedArrayUtils.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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.v4.content.res;
-
-import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
-import android.support.annotation.AnyRes;
-import android.support.annotation.RestrictTo;
-import android.support.annotation.StyleableRes;
-import android.util.TypedValue;
-
-/**
- * Compat methods for accessing TypedArray values.
- *
- * @hide
- */
-@RestrictTo(LIBRARY_GROUP)
-public class TypedArrayUtils {
-    public static boolean getBoolean(TypedArray a, @StyleableRes int index,
-            @StyleableRes int fallbackIndex, boolean defaultValue) {
-        boolean val = a.getBoolean(fallbackIndex, defaultValue);
-        return a.getBoolean(index, val);
-    }
-
-    public static Drawable getDrawable(TypedArray a, @StyleableRes int index,
-            @StyleableRes int fallbackIndex) {
-        Drawable val = a.getDrawable(index);
-        if (val == null) {
-            val = a.getDrawable(fallbackIndex);
-        }
-        return val;
-    }
-
-    public static int getInt(TypedArray a, @StyleableRes int index,
-            @StyleableRes int fallbackIndex, int defaultValue) {
-        int val = a.getInt(fallbackIndex, defaultValue);
-        return a.getInt(index, val);
-    }
-
-    public static @AnyRes int getResourceId(TypedArray a, @StyleableRes int index,
-            @StyleableRes int fallbackIndex, @AnyRes int defaultValue) {
-        int val = a.getResourceId(fallbackIndex, defaultValue);
-        return a.getResourceId(index, val);
-    }
-
-    public static String getString(TypedArray a, @StyleableRes int index,
-            @StyleableRes int fallbackIndex) {
-        String val = a.getString(index);
-        if (val == null) {
-            val = a.getString(fallbackIndex);
-        }
-        return val;
-    }
-
-    public static CharSequence getText(TypedArray a, @StyleableRes int index,
-            @StyleableRes int fallbackIndex) {
-        CharSequence val = a.getText(index);
-        if (val == null) {
-            val = a.getText(fallbackIndex);
-        }
-        return val;
-    }
-
-    public static CharSequence[] getTextArray(TypedArray a, @StyleableRes int index,
-            @StyleableRes int fallbackIndex) {
-        CharSequence[] val = a.getTextArray(index);
-        if (val == null) {
-            val = a.getTextArray(fallbackIndex);
-        }
-        return val;
-    }
-
-    public static int getAttr(Context context, int attr, int fallbackAttr) {
-        TypedValue value = new TypedValue();
-        context.getTheme().resolveAttribute(attr, value, true);
-        if (value.resourceId != 0) {
-            return attr;
-        }
-        return fallbackAttr;
-    }
-}
diff --git a/core-utils/jellybean/android/support/v4/app/TaskStackBuilderJellybean.java b/core-utils/jellybean/android/support/v4/app/TaskStackBuilderJellybean.java
deleted file mode 100644
index 2a18971..0000000
--- a/core-utils/jellybean/android/support/v4/app/TaskStackBuilderJellybean.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.
- */
-
-package android.support.v4.app;
-
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.annotation.RequiresApi;
-
-@RequiresApi(16)
-class TaskStackBuilderJellybean {
-
-    public static PendingIntent getActivitiesPendingIntent(Context context, int requestCode,
-            Intent[] intents, int flags, Bundle options) {
-        return PendingIntent.getActivities(context, requestCode, intents, flags, options);
-    }
-
-}
diff --git a/design/src/android/support/design/widget/TabLayout.java b/design/src/android/support/design/widget/TabLayout.java
index 7f3e231..8b81eaa 100755
--- a/design/src/android/support/design/widget/TabLayout.java
+++ b/design/src/android/support/design/widget/TabLayout.java
@@ -1084,17 +1084,7 @@
         final int targetScrollX = calculateScrollXForTab(newPosition, 0);
 
         if (startScrollX != targetScrollX) {
-            if (mScrollAnimator == null) {
-                mScrollAnimator = new ValueAnimator();
-                mScrollAnimator.setInterpolator(AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR);
-                mScrollAnimator.setDuration(ANIMATION_DURATION);
-                mScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-                    @Override
-                    public void onAnimationUpdate(ValueAnimator animator) {
-                        scrollTo((int) animator.getAnimatedValue(), 0);
-                    }
-                });
-            }
+            ensureScrollAnimator();
 
             mScrollAnimator.setIntValues(startScrollX, targetScrollX);
             mScrollAnimator.start();
@@ -1104,6 +1094,25 @@
         mTabStrip.animateIndicatorToPosition(newPosition, ANIMATION_DURATION);
     }
 
+    private void ensureScrollAnimator() {
+        if (mScrollAnimator == null) {
+            mScrollAnimator = new ValueAnimator();
+            mScrollAnimator.setInterpolator(AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR);
+            mScrollAnimator.setDuration(ANIMATION_DURATION);
+            mScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+                @Override
+                public void onAnimationUpdate(ValueAnimator animator) {
+                    scrollTo((int) animator.getAnimatedValue(), 0);
+                }
+            });
+        }
+    }
+
+    void setScrollAnimatorListener(Animator.AnimatorListener listener) {
+        ensureScrollAnimator();
+        mScrollAnimator.addListener(listener);
+    }
+
     private void setSelectedTabView(int position) {
         final int tabCount = mTabStrip.getChildCount();
         if (position < tabCount) {
@@ -1177,10 +1186,14 @@
             final int selectedWidth = selectedChild != null ? selectedChild.getWidth() : 0;
             final int nextWidth = nextChild != null ? nextChild.getWidth() : 0;
 
-            return selectedChild.getLeft()
-                    + ((int) ((selectedWidth + nextWidth) * positionOffset * 0.5f))
-                    + (selectedChild.getWidth() / 2)
-                    - (getWidth() / 2);
+            // base scroll amount: places center of tab in center of parent
+            int scrollBase = selectedChild.getLeft() + (selectedWidth / 2) - (getWidth() / 2);
+            // offset amount: fraction of the distance between centers of tabs
+            int scrollOffset = (int) ((selectedWidth + nextWidth) * 0.5f * positionOffset);
+
+            return (ViewCompat.getLayoutDirection(this) == ViewCompat.LAYOUT_DIRECTION_LTR)
+                    ? scrollBase + scrollOffset
+                    : scrollBase - scrollOffset;
         }
         return 0;
     }
diff --git a/design/tests/res/layout/design_tabs_fixed_width.xml b/design/tests/res/layout/design_tabs_fixed_width.xml
new file mode 100644
index 0000000..752034f
--- /dev/null
+++ b/design/tests/res/layout/design_tabs_fixed_width.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2017 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.
+-->
+
+<!-- Width is fixed to test scrolling -->
+<android.support.design.widget.TabLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/tabs"
+    android:layout_width="160dp"
+    android:layout_height="wrap_content"
+    app:tabMode="scrollable">
+
+    <android.support.design.widget.TabItem
+        android:text="Tab 0" />
+
+    <android.support.design.widget.TabItem
+        android:text="Tab 1" />
+
+    <android.support.design.widget.TabItem
+        android:text="Tab 2" />
+
+    <android.support.design.widget.TabItem
+        android:text="Tab 3" />
+
+    <android.support.design.widget.TabItem
+        android:text="Tab 4" />
+
+    <android.support.design.widget.TabItem
+        android:text="Tab 5" />
+
+    <android.support.design.widget.TabItem
+        android:text="Tab 6" />
+
+    <android.support.design.widget.TabItem
+        android:text="Tab 7" />
+
+</android.support.design.widget.TabLayout>
diff --git a/design/tests/src/android/support/design/testutils/TabLayoutActions.java b/design/tests/src/android/support/design/testutils/TabLayoutActions.java
index 149b14f..7c17850 100644
--- a/design/tests/src/android/support/design/testutils/TabLayoutActions.java
+++ b/design/tests/src/android/support/design/testutils/TabLayoutActions.java
@@ -16,23 +16,17 @@
 
 package android.support.design.testutils;
 
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayingAtLeast;
+
 import android.support.annotation.Nullable;
 import android.support.design.widget.TabLayout;
 import android.support.test.espresso.UiController;
 import android.support.test.espresso.ViewAction;
-import android.support.test.espresso.action.CoordinatesProvider;
-import android.support.test.espresso.action.GeneralClickAction;
-import android.support.test.espresso.action.Press;
-import android.support.test.espresso.action.Tap;
-import android.support.v4.view.PagerAdapter;
-import android.support.v4.view.PagerTitleStrip;
+import android.support.test.espresso.matcher.ViewMatchers;
 import android.support.v4.view.ViewPager;
 import android.view.View;
-import android.widget.TextView;
-import org.hamcrest.Matcher;
 
-import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayingAtLeast;
+import org.hamcrest.Matcher;
 
 public class TabLayoutActions {
     /**
@@ -143,4 +137,30 @@
             }
         };
     }
+
+    /**
+     * Calls <code>setScrollPosition(position, positionOffset, true)</code> on the
+     * <code>TabLayout</code>
+     */
+    public static ViewAction setScrollPosition(final int position, final float positionOffset) {
+        return new ViewAction() {
+
+            @Override
+            public Matcher<View> getConstraints() {
+                return ViewMatchers.isAssignableFrom(TabLayout.class);
+            }
+
+            @Override
+            public String getDescription() {
+                return "setScrollPosition(" + position + ", " + positionOffset + ", true)";
+            }
+
+            @Override
+            public void perform(UiController uiController, View view) {
+                TabLayout tabs = (TabLayout) view;
+                tabs.setScrollPosition(position, positionOffset, true);
+                uiController.loopMainThreadUntilIdle();
+            }
+        };
+    }
 }
diff --git a/design/tests/src/android/support/design/widget/TabLayoutTest.java b/design/tests/src/android/support/design/widget/TabLayoutTest.java
index cb4e669..1806019 100755
--- a/design/tests/src/android/support/design/widget/TabLayoutTest.java
+++ b/design/tests/src/android/support/design/widget/TabLayoutTest.java
@@ -16,6 +16,12 @@
 
 package android.support.design.widget;
 
+import static android.support.design.testutils.TabLayoutActions.selectTab;
+import static android.support.design.testutils.TabLayoutActions.setScrollPosition;
+import static android.support.design.testutils.TestUtilsActions.setLayoutDirection;
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
@@ -27,11 +33,18 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.os.Build;
 import android.support.design.test.R;
 import android.support.test.annotation.UiThreadTest;
+import android.support.test.espresso.Espresso;
+import android.support.test.espresso.IdlingResource;
+import android.support.test.espresso.NoMatchingViewException;
+import android.support.test.espresso.ViewAssertion;
 import android.support.test.filters.SdkSuppress;
 import android.support.test.filters.SmallTest;
+import android.support.v4.view.ViewCompat;
 import android.support.v7.app.AppCompatActivity;
 import android.view.InflateException;
 import android.view.LayoutInflater;
@@ -41,6 +54,8 @@
 
 import org.junit.Test;
 
+import java.util.concurrent.atomic.AtomicInteger;
+
 @SmallTest
 public class TabLayoutTest extends BaseInstrumentationTestCase<AppCompatActivity> {
     public TabLayoutTest() {
@@ -210,4 +225,105 @@
             }
         }
     }
+
+    @Test
+    public void setScrollPositionLtr() throws Throwable {
+        testSetScrollPosition(true);
+    }
+
+    @Test
+    public void setScrollPositionRtl() throws Throwable {
+        testSetScrollPosition(false);
+    }
+
+    private void testSetScrollPosition(final boolean isLtr) throws Throwable {
+        mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mActivityTestRule.getActivity().setContentView(R.layout.design_tabs_fixed_width);
+            }
+        });
+        final TabLayout tabs = (TabLayout) mActivityTestRule.getActivity().findViewById(R.id.tabs);
+        assertEquals(TabLayout.MODE_SCROLLABLE, tabs.getTabMode());
+
+        final TabLayoutScrollIdlingResource idler = new TabLayoutScrollIdlingResource(tabs);
+        Espresso.registerIdlingResources(idler);
+
+        // We're going to call setScrollPosition() incrementally, as if scrolling between one tab
+        // and the next. Use the middle tab for best results. The positionOffsets should be in the
+        // range [0, 1), so the final call will wrap to 0 but use the next tab's position.
+        final int middleTab = tabs.getTabCount() / 2;
+        final int[] positions = {middleTab, middleTab, middleTab, middleTab, middleTab + 1};
+        final float[] positionOffsets = {0f, .25f, .5f, .75f, 0f};
+
+        // Set layout direction
+        onView(withId(R.id.tabs)).perform(setLayoutDirection(
+                isLtr ? ViewCompat.LAYOUT_DIRECTION_LTR : ViewCompat.LAYOUT_DIRECTION_RTL));
+        // Make sure it's scrolled all the way to the start
+        onView(withId(R.id.tabs)).perform(selectTab(0));
+
+        // Perform a series of setScrollPosition() calls
+        final AtomicInteger lastScrollX = new AtomicInteger(tabs.getScrollX());
+        for (int i = 0; i < positions.length; i++) {
+            onView(withId(R.id.tabs))
+                    .perform(setScrollPosition(positions[i], positionOffsets[i]))
+                    .check(new ViewAssertion() {
+                        @Override
+                        public void check(View view, NoMatchingViewException notFoundException) {
+                            if (view == null) {
+                                throw notFoundException;
+                            }
+                            // Verify increasing or decreasing scroll X values
+                            int sx = view.getScrollX();
+                            assertTrue(isLtr ? sx > lastScrollX.get() : sx < lastScrollX.get());
+                            lastScrollX.set(sx);
+                        }
+                    });
+        }
+
+        Espresso.unregisterIdlingResources(idler);
+    }
+
+    static class TabLayoutScrollIdlingResource implements IdlingResource {
+
+        private boolean mIsIdle = true;
+        private ResourceCallback mCallback;
+
+        TabLayoutScrollIdlingResource(final TabLayout tabLayout) {
+            tabLayout.setScrollAnimatorListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationStart(Animator animator) {
+                    setIdle(false);
+                }
+
+                @Override
+                public void onAnimationEnd(Animator animator) {
+                    setIdle(true);
+                }
+            });
+        }
+
+        @Override
+        public String getName() {
+            return "TabLayoutScrollIdlingResource";
+        }
+
+        @Override
+        public boolean isIdleNow() {
+            return mIsIdle;
+        }
+
+        @Override
+        public void registerIdleTransitionCallback(ResourceCallback callback) {
+            mCallback = callback;
+        }
+
+        private void setIdle(boolean idle) {
+            boolean wasIdle = mIsIdle;
+            mIsIdle = idle;
+            if (mIsIdle && !wasIdle && mCallback != null) {
+                mCallback.onTransitionToIdle();
+            }
+        }
+    }
 }
diff --git a/exifinterface/src/android/support/media/ExifInterface.java b/exifinterface/src/android/support/media/ExifInterface.java
index fccab43..4830ecc 100644
--- a/exifinterface/src/android/support/media/ExifInterface.java
+++ b/exifinterface/src/android/support/media/ExifInterface.java
@@ -1850,11 +1850,31 @@
     }
 
     /**
-     * Stores the latitude and longitude value in a float array. The first element is
-     * the latitude, and the second element is the longitude. Returns false if the
-     * Exif tags are not available.
+     * Stores the latitude and longitude value in a float array. The first element is the latitude,
+     * and the second element is the longitude. Returns false if the Exif tags are not available.
+     *
+     * @deprecated Use {@link #getLatLong()} instead.
      */
+    @Deprecated
     public boolean getLatLong(float output[]) {
+        double[] latLong = getLatLong();
+        if (latLong == null) {
+            return false;
+        }
+
+        output[0] = (float) latLong[0];
+        output[1] = (float) latLong[1];
+        return true;
+    }
+
+    /**
+     * Gets the latitude and longitude values.
+     * <p>
+     * If there are valid latitude and longitude values in the image, this method returns a double
+     * array where the first element is the latitude and the second element is the longitude.
+     * Otherwise, it returns null.
+     */
+    public double[] getLatLong() {
         String latValue = getAttribute(TAG_GPS_LATITUDE);
         String latRef = getAttribute(TAG_GPS_LATITUDE_REF);
         String lngValue = getAttribute(TAG_GPS_LONGITUDE);
@@ -1862,16 +1882,39 @@
 
         if (latValue != null && latRef != null && lngValue != null && lngRef != null) {
             try {
-                output[0] = convertRationalLatLonToFloat(latValue, latRef);
-                output[1] = convertRationalLatLonToFloat(lngValue, lngRef);
-                return true;
+                double latitude = convertRationalLatLonToDouble(latValue, latRef);
+                double longitude = convertRationalLatLonToDouble(lngValue, lngRef);
+                return new double[] {latitude, longitude};
             } catch (IllegalArgumentException e) {
                 Log.w(TAG, "Latitude/longitude values are not parseable. " +
                         String.format("latValue=%s, latRef=%s, lngValue=%s, lngRef=%s",
                                 latValue, latRef, lngValue, lngRef));
             }
         }
-        return false;
+        return null;
+    }
+
+    /**
+     * Sets the latitude and longitude values.
+     *
+     * @param latitude the decimal value of latitude. Must be a valid double value between -90.0 and
+     *                 90.0.
+     * @param longitude the decimal value of longitude. Must be a valid double value between -180.0
+     *                  and 180.0.
+     * @throws IllegalArgumentException If {@code latitude} or {@code longitude} is outside the
+     *                                  specified range.
+     */
+    public void setLatLong(double latitude, double longitude) {
+        if (latitude < -90.0 || latitude > 90.0 || Double.isNaN(latitude)) {
+            throw new IllegalArgumentException("Latitude value " + latitude + " is not valid.");
+        }
+        if (longitude < -180.0 || longitude > 180.0 || Double.isNaN(longitude)) {
+            throw new IllegalArgumentException("Longitude value " + longitude + " is not valid.");
+        }
+        setAttribute(TAG_GPS_LATITUDE_REF, latitude >= 0 ? "N" : "S");
+        setAttribute(TAG_GPS_LATITUDE, convertDecimalDegree(Math.abs(latitude)));
+        setAttribute(TAG_GPS_LONGITUDE_REF, longitude >= 0 ? "E" : "W");
+        setAttribute(TAG_GPS_LONGITUDE, convertDecimalDegree(Math.abs(longitude)));
     }
 
     /**
@@ -1953,7 +1996,7 @@
         }
     }
 
-    private static float convertRationalLatLonToFloat(String rationalString, String ref) {
+    private static double convertRationalLatLonToDouble(String rationalString, String ref) {
         try {
             String [] parts = rationalString.split(",");
 
@@ -1972,15 +2015,26 @@
 
             double result = degrees + (minutes / 60.0) + (seconds / 3600.0);
             if ((ref.equals("S") || ref.equals("W"))) {
-                return (float) -result;
+                return -result;
+            } else if (ref.equals("N") || ref.equals("E")) {
+                return result;
+            } else {
+                // Not valid
+                throw new IllegalArgumentException();
             }
-            return (float) result;
         } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
             // Not valid
             throw new IllegalArgumentException();
         }
     }
 
+    private String convertDecimalDegree(double decimalDegree) {
+        long degrees = (long) decimalDegree;
+        long minutes = (long) ((decimalDegree - degrees) * 60.0);
+        long seconds = Math.round((decimalDegree - degrees - minutes / 60.0) * 3600.0 * 1e7);
+        return degrees + "/1," + minutes + "/1," + seconds + "/10000000";
+    }
+
     // Checks the type of image file
     private int getMimeType(BufferedInputStream in) throws IOException {
         in.mark(SIGNATURE_CHECK_SIZE);
diff --git a/exifinterface/tests/src/android/support/media/ExifInterfaceTest.java b/exifinterface/tests/src/android/support/media/ExifInterfaceTest.java
index 87fb950..ee9e38e 100644
--- a/exifinterface/tests/src/android/support/media/ExifInterfaceTest.java
+++ b/exifinterface/tests/src/android/support/media/ExifInterfaceTest.java
@@ -16,6 +16,13 @@
 
 package android.support.media;
 
+import static android.support.test.InstrumentationRegistry.getContext;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.fail;
+
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.os.Environment;
@@ -40,12 +47,6 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 
-import static android.support.test.InstrumentationRegistry.getContext;
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertNull;
-import static junit.framework.Assert.fail;
-
 /**
  * Test {@link ExifInterface}.
  */
@@ -53,7 +54,6 @@
 public class ExifInterfaceTest {
     private static final String TAG = ExifInterface.class.getSimpleName();
     private static final boolean VERBOSE = false;  // lots of logging
-
     private static final double DIFFERENCE_TOLERANCE = .001;
 
     private static final String EXIF_BYTE_ORDER_II_JPEG = "image_exif_byte_order_ii.jpg";
@@ -64,6 +64,20 @@
     private static final String[] IMAGE_FILENAMES = new String[] {
             EXIF_BYTE_ORDER_II_JPEG, EXIF_BYTE_ORDER_MM_JPEG, LG_G4_ISO_800_DNG};
 
+    private static final String TEST_TEMP_FILE_NAME = "testImage";
+    private static final double DELTA = 1e-8;
+    private static final int TEST_LAT_LONG_VALUES_ARRAY_LENGTH = 8;
+    private static final double[] TEST_LATITUDE_VALID_VALUES = new double[]
+            {0, 45, 90, -60, 0.00000001, -89.999999999, 14.2465923626, -68.3434534737};
+    private static final double[] TEST_LONGITUDE_VALID_VALUES = new double[]
+            {0, -45, 90, -120, 180, 0.00000001, -179.99999999999, -58.57834236352};
+    private static final double[] TEST_LATITUDE_INVALID_VALUES = new double[]
+            {Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, 90.0000000001,
+                    263.34763236326, -1e5, 347.32525, -176.346347754};
+    private static final double[] TEST_LONGITUDE_INVALID_VALUES = new double[]
+            {Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, 180.0000000001,
+                    263.34763236326, -1e10, 347.325252623, -4000.346323236};
+
     private static final String[] EXIF_TAGS = {
             ExifInterface.TAG_MAKE,
             ExifInterface.TAG_MODEL,
@@ -235,6 +249,52 @@
         }
     }
 
+    @Test
+    @SmallTest
+    public void testSetLatLong_withValidValues() throws IOException {
+        for (int i = 0; i < TEST_LAT_LONG_VALUES_ARRAY_LENGTH; i++) {
+            ExifInterface exif = createTestExifInterface();
+            exif.setLatLong(TEST_LATITUDE_VALID_VALUES[i], TEST_LONGITUDE_VALID_VALUES[i]);
+
+            double[] latLong = exif.getLatLong();
+            assertNotNull(latLong);
+            assertEquals(TEST_LATITUDE_VALID_VALUES[i], latLong[0], DELTA);
+            assertEquals(TEST_LONGITUDE_VALID_VALUES[i], latLong[1], DELTA);
+        }
+    }
+
+    @Test
+    @SmallTest
+    public void testSetLatLong_withInvalidLatitude() throws IOException {
+        for (int i = 0; i < TEST_LAT_LONG_VALUES_ARRAY_LENGTH; i++) {
+            ExifInterface exif = createTestExifInterface();
+            try {
+                exif.setLatLong(TEST_LATITUDE_INVALID_VALUES[i], TEST_LONGITUDE_VALID_VALUES[i]);
+                fail();
+            } catch (IllegalArgumentException e) {
+                // expected
+            }
+            assertNull(exif.getLatLong());
+            assertLatLongValuesAreNotSet(exif);
+        }
+    }
+
+    @Test
+    @SmallTest
+    public void testSetLatLong_withInvalidLongitude() throws IOException {
+        for (int i = 0; i < TEST_LAT_LONG_VALUES_ARRAY_LENGTH; i++) {
+            ExifInterface exif = createTestExifInterface();
+            try {
+                exif.setLatLong(TEST_LATITUDE_VALID_VALUES[i], TEST_LONGITUDE_INVALID_VALUES[i]);
+                fail();
+            } catch (IllegalArgumentException e) {
+                // expected
+            }
+            assertNull(exif.getLatLong());
+            assertLatLongValuesAreNotSet(exif);
+        }
+    }
+
     private void printExifTagsAndValues(String fileName, ExifInterface exifInterface) {
         // Prints thumbnail information.
         if (exifInterface.hasThumbnail()) {
@@ -264,8 +324,8 @@
         // Prints GPS information.
         Log.v(TAG, fileName + " Altitude = " + exifInterface.getAltitude(.0));
 
-        float[] latLong = new float[2];
-        if (exifInterface.getLatLong(latLong)) {
+        double[] latLong = exifInterface.getLatLong();
+        if (latLong != null) {
             Log.v(TAG, fileName + " Latitude = " + latLong[0]);
             Log.v(TAG, fileName + " Longitude = " + latLong[1]);
         } else {
@@ -318,8 +378,8 @@
         }
 
         // Checks GPS information.
-        float[] latLong = new float[2];
-        assertEquals(expectedValue.hasLatLong, exifInterface.getLatLong(latLong));
+        double[] latLong = exifInterface.getLatLong();
+        assertEquals(expectedValue.hasLatLong, latLong != null);
         if (expectedValue.hasLatLong) {
             assertEquals(expectedValue.latitude, latLong[0], DIFFERENCE_TOLERANCE);
             assertEquals(expectedValue.longitude, latLong[1], DIFFERENCE_TOLERANCE);
@@ -443,4 +503,17 @@
         }
         return total;
     }
+
+    private void assertLatLongValuesAreNotSet(ExifInterface exif) {
+        assertNull(exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE));
+        assertNull(exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF));
+        assertNull(exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE));
+        assertNull(exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF));
+    }
+
+    private ExifInterface createTestExifInterface() throws IOException {
+        File image = File.createTempFile(TEST_TEMP_FILE_NAME, ".jpg");
+        image.deleteOnExit();
+        return new ExifInterface(image.getAbsolutePath());
+    }
 }
diff --git a/fragment/java/android/support/v4/app/BackStackRecord.java b/fragment/java/android/support/v4/app/BackStackRecord.java
index 0debe7a..108d2e6 100644
--- a/fragment/java/android/support/v4/app/BackStackRecord.java
+++ b/fragment/java/android/support/v4/app/BackStackRecord.java
@@ -798,8 +798,11 @@
     /**
      * Reverses the execution of the operations within this transaction. The Fragment states will
      * only be modified if optimizations are not allowed.
+     *
+     * @param moveToState {@code true} if added fragments should be moved to their final state
+     *                    in unoptimized transactions
      */
-    void executePopOps() {
+    void executePopOps(boolean moveToState) {
         for (int opNum = mOps.size() - 1; opNum >= 0; opNum--) {
             final Op op = mOps.get(opNum);
             Fragment f = op.fragment;
@@ -845,7 +848,7 @@
                 mManager.moveFragmentToExpectedState(f);
             }
         }
-        if (!mAllowOptimization) {
+        if (!mAllowOptimization && moveToState) {
             mManager.moveToState(mManager.mCurState, true);
         }
     }
diff --git a/fragment/java/android/support/v4/app/Fragment.java b/fragment/java/android/support/v4/app/Fragment.java
index 297d4bf..09b1464 100644
--- a/fragment/java/android/support/v4/app/Fragment.java
+++ b/fragment/java/android/support/v4/app/Fragment.java
@@ -66,9 +66,9 @@
     final boolean mDetached;
     final Bundle mArguments;
     final boolean mHidden;
-    
+
     Bundle mSavedFragmentState;
-    
+
     Fragment mInstance;
 
     public FragmentState(Fragment frag) {
@@ -83,7 +83,7 @@
         mArguments = frag.mArguments;
         mHidden = frag.mHidden;
     }
-    
+
     public FragmentState(Parcel in) {
         mClassName = in.readString();
         mIndex = in.readInt();
@@ -153,7 +153,7 @@
         dest.writeInt(mHidden? 1 : 0);
         dest.writeBundle(mSavedFragmentState);
     }
-    
+
     public static final Parcelable.Creator<FragmentState> CREATOR
             = new Parcelable.Creator<FragmentState>() {
         @Override
@@ -195,19 +195,19 @@
     static final int STOPPED = 3;          // Fully created, not started.
     static final int STARTED = 4;          // Created and started, not resumed.
     static final int RESUMED = 5;          // Created started and resumed.
-    
+
     int mState = INITIALIZING;
-    
+
     // When instantiated from saved state, this is the saved state.
     Bundle mSavedFragmentState;
     SparseArray<Parcelable> mSavedViewState;
-    
+
     // Index into active fragment array.
     int mIndex = -1;
-    
+
     // Internal unique name for this fragment;
     String mWho;
-    
+
     // Construction arguments;
     Bundle mArguments;
 
@@ -222,13 +222,13 @@
 
     // True if the fragment is in the list of added fragments.
     boolean mAdded;
-    
+
     // If set this fragment is being removed from its activity.
     boolean mRemoving;
-    
+
     // Set to true if this fragment was instantiated from a layout file.
     boolean mFromLayout;
-    
+
     // Set to true when the view has actually been inflated in its layout.
     boolean mInLayout;
 
@@ -264,19 +264,19 @@
     // was dynamically added to the view hierarchy, or the ID supplied in
     // layout.
     int mFragmentId;
-    
+
     // When a fragment is being dynamically added to the view hierarchy, this
     // is the identifier of the parent container it is being added to.
     int mContainerId;
-    
+
     // The optional named tag for this fragment -- usually used to find
     // fragments that are not part of the layout.
     String mTag;
-    
+
     // Set to true when the app has requested that this fragment be hidden
     // from the user.
     boolean mHidden;
-    
+
     // Set to true when the app has requested that this fragment be deactivated.
     boolean mDetached;
 
@@ -286,7 +286,7 @@
 
     // If set this fragment is being retained across the current config change.
     boolean mRetaining;
-    
+
     // If set this fragment has menu items to contribute.
     boolean mHasMenu;
 
@@ -295,20 +295,20 @@
 
     // Used to verify that subclasses call through to super class.
     boolean mCalled;
-    
+
     // The parent container of the fragment after dynamically added to UI.
     ViewGroup mContainer;
-    
+
     // The View generated for this fragment.
     View mView;
-    
+
     // The real inner view that will save/restore state.
     View mInnerView;
 
     // Whether this fragment should defer starting until after other fragments
     // have been started and their loaders are finished.
     boolean mDeferStart;
-    
+
     // Hint provided by the app that this fragment is currently visible to the user.
     boolean mUserVisibleHint = true;
 
@@ -395,7 +395,7 @@
      * will not be called when the fragment is re-instantiated; instead,
      * arguments can be supplied by the caller with {@link #setArguments}
      * and later retrieved by the Fragment with {@link #getArguments}.
-     * 
+     *
      * <p>Applications should generally not implement a constructor. Prefer
      * {@link #onAttach(Context)} instead. It is the first place application code can run where
      * the fragment is ready to be used - the point where the fragment is actually associated with
@@ -477,7 +477,7 @@
             return false;
         }
     }
-    
+
     final void restoreViewState(Bundle savedInstanceState) {
         if (mSavedViewState != null) {
             mInnerView.restoreHierarchyState(mSavedViewState);
@@ -517,7 +517,7 @@
     @Override final public int hashCode() {
         return super.hashCode();
     }
-    
+
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder(128);
@@ -537,7 +537,7 @@
         sb.append('}');
         return sb.toString();
     }
-    
+
     /**
      * Return the identifier this fragment is known by.  This is either
      * the android:id value supplied in a layout or the container view ID
@@ -546,14 +546,14 @@
     final public int getId() {
         return mFragmentId;
     }
-    
+
     /**
      * Get the tag name of the fragment, if specified.
      */
     final public String getTag() {
         return mTag;
     }
-    
+
     /**
      * Supply the construction arguments for this fragment.
      * The arguments supplied here will be retained across fragment destroy and
@@ -796,7 +796,7 @@
     final public boolean isRemoving() {
         return mRemoving;
     }
-    
+
     /**
      * Return true if the layout is included as part of an activity view
      * hierarchy via the &lt;fragment&gt; tag.  This will always be true when
@@ -815,17 +815,17 @@
     final public boolean isResumed() {
         return mState >= RESUMED;
     }
-    
+
     /**
      * Return true if the fragment is currently visible to the user.  This means
-     * it: (1) has been added, (2) has its view attached to the window, and 
+     * it: (1) has been added, (2) has its view attached to the window, and
      * (3) is not hidden.
      */
     final public boolean isVisible() {
         return isAdded() && !isHidden() && mView != null
                 && mView.getWindowToken() != null && mView.getVisibility() == View.VISIBLE;
     }
-    
+
     /**
      * Return true if the fragment has been hidden.  By default fragments
      * are shown.  You can find out about changes to this state with
@@ -857,7 +857,7 @@
      */
     public void onHiddenChanged(boolean hidden) {
     }
-    
+
     /**
      * Control whether a fragment instance is retained across Activity
      * re-creation (such as from a configuration change).  This can only
@@ -875,11 +875,11 @@
     public void setRetainInstance(boolean retain) {
         mRetainInstance = retain;
     }
-    
+
     final public boolean getRetainInstance() {
         return mRetainInstance;
     }
-    
+
     /**
      * Report that this fragment would like to participate in populating
      * the options menu by receiving a call to {@link #onCreateOptionsMenu}
@@ -1181,7 +1181,7 @@
      * tag in a layout file.  Note this is <em>before</em> the fragment's
      * {@link #onAttach(Activity)} has been called; all you should do here is
      * parse the attributes and save them away.
-     * 
+     *
      * <p>This is called every time the fragment is inflated, even if it is
      * being inflated into a new instance with saved state.  It typically makes
      * sense to re-parse the parameters each time, to allow them to change with
@@ -1197,7 +1197,7 @@
      * declaration for the styleable used here is:</p>
      *
      * {@sample frameworks/support/samples/Support4Demos/res/values/attrs.xml fragment_arguments}
-     * 
+     *
      * <p>The fragment can then be declared within its activity's content layout
      * through a tag like this:</p>
      *
@@ -1287,7 +1287,7 @@
      * Called to do initial creation of a fragment.  This is called after
      * {@link #onAttach(Activity)} and before
      * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}.
-     * 
+     *
      * <p>Note that this can be called while the fragment's activity is
      * still in the process of being created.  As such, you can not rely
      * on things like the activity's content view hierarchy being initialized
@@ -1296,7 +1296,7 @@
      *
      * <p>Any restored child fragments will be created before the base
      * <code>Fragment.onCreate</code> method returns.</p>
-     * 
+     *
      * @param savedInstanceState If the fragment is being re-created from
      * a previous saved state, this is the state.
      */
@@ -1342,10 +1342,10 @@
      * This is optional, and non-graphical fragments can return null (which
      * is the default implementation).  This will be called between
      * {@link #onCreate(Bundle)} and {@link #onActivityCreated(Bundle)}.
-     * 
+     *
      * <p>If you return a View from here, you will later be called in
      * {@link #onDestroyView} when the view is being released.
-     * 
+     *
      * @param inflater The LayoutInflater object that can be used to inflate
      * any views in the fragment,
      * @param container If non-null, this is the parent view that the fragment's
@@ -1353,7 +1353,7 @@
      * but this can be used to generate the LayoutParams of the view.
      * @param savedInstanceState If non-null, this fragment is being re-constructed
      * from a previous saved state as given here.
-     * 
+     *
      * @return Return the View for the fragment's UI, or null.
      */
     @Nullable
@@ -1378,14 +1378,14 @@
     /**
      * Get the root view for the fragment's layout (the one returned by {@link #onCreateView}),
      * if provided.
-     * 
+     *
      * @return The fragment's root view, or null if it has no layout.
      */
     @Nullable
     public View getView() {
         return mView;
     }
-    
+
     /**
      * Called when the fragment's activity has been created and this
      * fragment's view hierarchy instantiated.  It can be used to do final
@@ -1451,7 +1451,7 @@
     public void onResume() {
         mCalled = true;
     }
-    
+
     /**
      * Called to ask the fragment to save its current dynamic state, so it
      * can later be reconstructed in a new instance of its process is
@@ -1508,7 +1508,7 @@
     public void onPause() {
         mCalled = true;
     }
-    
+
     /**
      * Called when the Fragment is no longer started.  This is generally
      * tied to {@link Activity#onStop() Activity.onStop} of the containing
@@ -1524,7 +1524,7 @@
     public void onLowMemory() {
         mCalled = true;
     }
-    
+
     /**
      * Called when the view previously created by {@link #onCreateView} has
      * been detached from the fragment.  The next time the fragment needs
@@ -1538,7 +1538,7 @@
     public void onDestroyView() {
         mCalled = true;
     }
-    
+
     /**
      * Called when the fragment is no longer in use.  This is called
      * after {@link #onStop()} and before {@link #onDetach()}.
@@ -1594,16 +1594,16 @@
     public void onDetach() {
         mCalled = true;
     }
-    
+
     /**
      * Initialize the contents of the Fragment host's standard options menu.  You
      * should place your menu items in to <var>menu</var>.  For this method
      * to be called, you must have first called {@link #setHasOptionsMenu}.  See
      * {@link Activity#onCreateOptionsMenu(Menu) Activity.onCreateOptionsMenu}
      * for more information.
-     * 
+     *
      * @param menu The options menu in which you place your items.
-     * 
+     *
      * @see #setHasOptionsMenu
      * @see #onPrepareOptionsMenu
      * @see #onOptionsItemSelected
@@ -1618,10 +1618,10 @@
      * dynamically modify the contents.  See
      * {@link Activity#onPrepareOptionsMenu(Menu) Activity.onPrepareOptionsMenu}
      * for more information.
-     * 
+     *
      * @param menu The options menu as last shown or first initialized by
      *             onCreateOptionsMenu().
-     * 
+     *
      * @see #setHasOptionsMenu
      * @see #onCreateOptionsMenu
      */
@@ -1637,7 +1637,7 @@
      */
     public void onDestroyOptionsMenu() {
     }
-    
+
     /**
      * This hook is called whenever an item in your options menu is selected.
      * The default implementation simply returns false to have the normal
@@ -1645,15 +1645,15 @@
      * its Handler as appropriate).  You can use this method for any items
      * for which you would like to do processing without those other
      * facilities.
-     * 
+     *
      * <p>Derived classes should call through to the base class for it to
      * perform the default menu handling.
-     * 
+     *
      * @param item The menu item that was selected.
-     * 
+     *
      * @return boolean Return false to allow normal menu processing to
      *         proceed, true to consume it here.
-     * 
+     *
      * @see #onCreateOptionsMenu
      */
     public boolean onOptionsItemSelected(MenuItem item) {
@@ -1663,13 +1663,13 @@
     /**
      * This hook is called whenever the options menu is being closed (either by the user canceling
      * the menu with the back/menu button, or when an item is selected).
-     *  
+     *
      * @param menu The options menu as last shown or first initialized by
      *             onCreateOptionsMenu().
      */
     public void onOptionsMenuClosed(Menu menu) {
     }
-    
+
     /**
      * Called when a context menu for the {@code view} is about to be shown.
      * Unlike {@link #onCreateOptionsMenu}, this will be called every
@@ -1698,25 +1698,25 @@
      * {@link OnCreateContextMenuListener} on the view to this fragment, so
      * {@link #onCreateContextMenu(ContextMenu, View, ContextMenuInfo)} will be
      * called when it is time to show the context menu.
-     * 
+     *
      * @see #unregisterForContextMenu(View)
      * @param view The view that should show a context menu.
      */
     public void registerForContextMenu(View view) {
         view.setOnCreateContextMenuListener(this);
     }
-    
+
     /**
      * Prevents a context menu to be shown for the given view. This method will
      * remove the {@link OnCreateContextMenuListener} on the view.
-     * 
+     *
      * @see #registerForContextMenu(View)
      * @param view The view that should stop showing a context menu.
      */
     public void unregisterForContextMenu(View view) {
         view.setOnCreateContextMenuListener(null);
     }
-    
+
     /**
      * This hook is called whenever an item in a context menu is selected. The
      * default implementation simply returns false to have the normal processing
@@ -1729,7 +1729,7 @@
      * <p>
      * Derived classes should call through to the base class for it to perform
      * the default menu handling.
-     * 
+     *
      * @param item The context menu item that was selected.
      * @return boolean Return false to allow normal context menu processing to
      *         proceed, true to consume it here.
diff --git a/fragment/java/android/support/v4/app/FragmentManager.java b/fragment/java/android/support/v4/app/FragmentManager.java
index 97c13c0..17b6306 100644
--- a/fragment/java/android/support/v4/app/FragmentManager.java
+++ b/fragment/java/android/support/v4/app/FragmentManager.java
@@ -2283,7 +2283,7 @@
                 if (isPop) {
                     record.executeOps();
                 } else {
-                    record.executePopOps();
+                    record.executePopOps(false);
                 }
 
                 // move to the end
@@ -2402,7 +2402,10 @@
             final boolean isPop = isRecordPop.get(i);
             if (isPop) {
                 record.bumpBackStackNesting(-1);
-                record.executePopOps();
+                // Only execute the add operations at the end of
+                // all transactions.
+                boolean moveToState = i == (endIndex - 1);
+                record.executePopOps(moveToState);
             } else {
                 record.bumpBackStackNesting(1);
                 record.executeOps();
diff --git a/fragment/tests/java/android/support/v4/app/FragmentViewTests.java b/fragment/tests/java/android/support/v4/app/FragmentViewTests.java
index 211ec35..ace24e9 100644
--- a/fragment/tests/java/android/support/v4/app/FragmentViewTests.java
+++ b/fragment/tests/java/android/support/v4/app/FragmentViewTests.java
@@ -1036,6 +1036,10 @@
 
         FragmentTestUtil.executePendingTransactions(mActivityRule);
 
+        assertEquals(1, fragment1.onCreateViewCount);
+        assertEquals(1, fragment2.onCreateViewCount);
+        assertEquals(1, fragment3.onCreateViewCount);
+
         FragmentTestUtil.popBackStackImmediate(mActivityRule, "two",
                 FragmentManager.POP_BACK_STACK_INCLUSIVE);
 
@@ -1043,6 +1047,10 @@
                 mActivityRule.getActivity().findViewById(R.id.fragmentContainer);
 
         FragmentTestUtil.assertChildren(container, fragment1);
+
+        assertEquals(2, fragment1.onCreateViewCount);
+        assertEquals(1, fragment2.onCreateViewCount);
+        assertEquals(1, fragment3.onCreateViewCount);
     }
 
     private View findViewById(int viewId) {
@@ -1091,10 +1099,13 @@
     }
 
     public static class SimpleViewFragment extends Fragment {
+        public int onCreateViewCount;
+
         @Nullable
         @Override
         public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                 @Nullable Bundle savedInstanceState) {
+            onCreateViewCount++;
             return inflater.inflate(R.layout.fragment_a, container, false);
         }
     }
diff --git a/graphics/drawable/static/src/android/support/graphics/drawable/TypedArrayUtils.java b/graphics/drawable/static/src/android/support/graphics/drawable/TypedArrayUtils.java
deleted file mode 100644
index 14200c1..0000000
--- a/graphics/drawable/static/src/android/support/graphics/drawable/TypedArrayUtils.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.graphics.drawable;
-
-import android.content.res.TypedArray;
-
-import org.xmlpull.v1.XmlPullParser;
-
-class TypedArrayUtils {
-    private static final String NAMESPACE = "http://schemas.android.com/apk/res/android";
-
-    public static boolean hasAttribute(XmlPullParser parser, String attrName) {
-        return parser.getAttributeValue(NAMESPACE, attrName) != null;
-    }
-
-    public static float getNamedFloat(TypedArray a, XmlPullParser parser, String attrName,
-                                      int resId, float defaultValue) {
-        final boolean hasAttr = hasAttribute(parser, attrName);
-        if (!hasAttr) {
-            return defaultValue;
-        } else {
-            return a.getFloat(resId, defaultValue);
-        }
-    }
-
-    public static boolean getNamedBoolean(TypedArray a, XmlPullParser parser, String attrName,
-                                          int resId, boolean defaultValue) {
-        final boolean hasAttr = hasAttribute(parser, attrName);
-        if (!hasAttr) {
-            return defaultValue;
-        } else {
-            return a.getBoolean(resId, defaultValue);
-        }
-    }
-
-    public static int getNamedInt(TypedArray a, XmlPullParser parser, String attrName,
-                                  int resId, int defaultValue) {
-        final boolean hasAttr = hasAttribute(parser, attrName);
-        if (!hasAttr) {
-            return defaultValue;
-        } else {
-            return a.getInt(resId, defaultValue);
-        }
-    }
-
-    public static int getNamedColor(TypedArray a, XmlPullParser parser, String attrName,
-                                    int resId, int defaultValue) {
-        final boolean hasAttr = hasAttribute(parser, attrName);
-        if (!hasAttr) {
-            return defaultValue;
-        } else {
-            return a.getColor(resId, defaultValue);
-        }
-    }
-}
diff --git a/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java b/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java
index 5704d6f..5f61127 100644
--- a/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java
+++ b/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java
@@ -42,6 +42,7 @@
 import android.support.annotation.Nullable;
 import android.support.annotation.RestrictTo;
 import android.support.v4.content.res.ResourcesCompat;
+import android.support.v4.content.res.TypedArrayUtils;
 import android.support.v4.graphics.drawable.DrawableCompat;
 import android.support.v4.util.ArrayMap;
 import android.util.AttributeSet;
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderCursorSupport.java b/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderCursorSupport.java
index f2f9b3c..90747ae 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderCursorSupport.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderCursorSupport.java
@@ -16,6 +16,10 @@
 
 package com.example.android.supportv4.app;
 
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.Contacts.People;
 import android.support.v4.app.FragmentActivity;
 import android.support.v4.app.FragmentManager;
 import android.support.v4.app.ListFragment;
@@ -23,16 +27,7 @@
 import android.support.v4.content.CursorLoader;
 import android.support.v4.content.Loader;
 import android.support.v4.view.MenuItemCompat;
-import android.support.v4.widget.SearchViewCompat;
-import android.support.v4.widget.SearchViewCompat.OnCloseListenerCompat;
-import android.support.v4.widget.SearchViewCompat.OnQueryTextListenerCompat;
 import android.support.v4.widget.SimpleCursorAdapter;
-
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.BaseColumns;
-import android.provider.Contacts.People;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.Menu;
@@ -40,6 +35,7 @@
 import android.view.MenuItem;
 import android.view.View;
 import android.widget.ListView;
+import android.widget.SearchView;
 
 /**
  * Demonstration of the use of a CursorLoader to load and display contacts
@@ -102,42 +98,42 @@
             item.setIcon(android.R.drawable.ic_menu_search);
             MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_ALWAYS
                     | MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
-            final View searchView = SearchViewCompat.newSearchView(getActivity());
-            if (searchView != null) {
-                SearchViewCompat.setOnQueryTextListener(searchView,
-                        new OnQueryTextListenerCompat() {
-                    @Override
-                    public boolean onQueryTextChange(String newText) {
-                        // Called when the action bar search text has changed.  Update
-                        // the search filter, and restart the loader to do a new query
-                        // with this filter.
-                        String newFilter = !TextUtils.isEmpty(newText) ? newText : null;
-                        // Don't do anything if the filter hasn't actually changed.
-                        // Prevents restarting the loader when restoring state.
-                        if (mCurFilter == null && newFilter == null) {
-                            return true;
-                        }
-                        if (mCurFilter != null && mCurFilter.equals(newFilter)) {
-                            return true;
-                        }
-                        mCurFilter = newFilter;
-                        getLoaderManager().restartLoader(0, null, CursorLoaderListFragment.this);
+            final SearchView searchView = new SearchView(getActivity());
+            searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
+                @Override
+                public boolean onQueryTextChange(String newText) {
+                    // Called when the action bar search text has changed.  Update
+                    // the search filter, and restart the loader to do a new query
+                    // with this filter.
+                    String newFilter = !TextUtils.isEmpty(newText) ? newText : null;
+                    // Don't do anything if the filter hasn't actually changed.
+                    // Prevents restarting the loader when restoring state.
+                    if (mCurFilter == null && newFilter == null) {
                         return true;
                     }
-                });
-                SearchViewCompat.setOnCloseListener(searchView,
-                        new OnCloseListenerCompat() {
-                            @Override
-                            public boolean onClose() {
-                                if (!TextUtils.isEmpty(SearchViewCompat.getQuery(searchView))) {
-                                    SearchViewCompat.setQuery(searchView, null, true);
-                                }
-                                return true;
-                            }
-                    
-                });
-                MenuItemCompat.setActionView(item, searchView);
-            }
+                    if (mCurFilter != null && mCurFilter.equals(newFilter)) {
+                        return true;
+                    }
+                    mCurFilter = newFilter;
+                    getLoaderManager().restartLoader(0, null, CursorLoaderListFragment.this);
+                    return true;
+                }
+
+                @Override
+                public boolean onQueryTextSubmit(String s) {
+                    return false;
+                }
+            });
+            searchView.setOnCloseListener(new SearchView.OnCloseListener() {
+                @Override
+                public boolean onClose() {
+                    if (!TextUtils.isEmpty(searchView.getQuery())) {
+                        searchView.setQuery(null, true);
+                    }
+                    return true;
+                }
+            });
+            MenuItemCompat.setActionView(item, searchView);
         }
 
         @Override public void onListItemClick(ListView l, View v, int position, long id) {
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderCustomSupport.java b/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderCustomSupport.java
index d9689d2..5dbb78c 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderCustomSupport.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderCustomSupport.java
@@ -33,11 +33,9 @@
 import android.support.v4.app.LoaderManager;
 import android.support.v4.content.AsyncTaskLoader;
 import android.support.v4.content.ContextCompat;
-import android.support.v4.content.IntentCompat;
 import android.support.v4.content.Loader;
 import android.support.v4.content.pm.ActivityInfoCompat;
 import android.support.v4.view.MenuItemCompat;
-import android.support.v4.widget.SearchViewCompat;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.LayoutInflater;
@@ -49,6 +47,7 @@
 import android.widget.ArrayAdapter;
 import android.widget.ImageView;
 import android.widget.ListView;
+import android.widget.SearchView;
 import android.widget.TextView;
 
 import com.example.android.supportv4.R;
@@ -193,8 +192,8 @@
             mLoader.getContext().registerReceiver(this, filter);
             // Register for events related to sdcard installation.
             IntentFilter sdFilter = new IntentFilter();
-            sdFilter.addAction(IntentCompat.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
-            sdFilter.addAction(IntentCompat.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
+            sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
+            sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
             mLoader.getContext().registerReceiver(this, sdFilter);
         }
 
@@ -438,36 +437,34 @@
             item.setIcon(android.R.drawable.ic_menu_search);
             MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM
                     | MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
-            final View searchView = SearchViewCompat.newSearchView(getActivity());
-            if (searchView != null) {
-                SearchViewCompat.setOnQueryTextListener(searchView,
-                        new SearchViewCompat.OnQueryTextListener() {
-                            @Override
-                            public boolean onQueryTextChange(String newText) {
-                                // Called when the action bar search text has changed.  Since this
-                                // is a simple array adapter, we can just have it do the filtering.
-                                mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
-                                mAdapter.getFilter().filter(mCurFilter);
-                                return true;
-                            }
+            final SearchView searchView = new SearchView(getActivity());
+            searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
+                @Override
+                public boolean onQueryTextChange(String newText) {
+                    // Called when the action bar search text has changed.  Since this
+                    // is a simple array adapter, we can just have it do the filtering.
+                    mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
+                    mAdapter.getFilter().filter(mCurFilter);
+                    return true;
+                }
 
-                            @Override
-                            public boolean onQueryTextSubmit(String query) {
-                                return false;
-                            }
-                        });
-                SearchViewCompat.setOnCloseListener(searchView,
-                        new SearchViewCompat.OnCloseListener() {
-                            @Override
-                            public boolean onClose() {
-                                if (!TextUtils.isEmpty(SearchViewCompat.getQuery(searchView))) {
-                                    SearchViewCompat.setQuery(searchView, null, true);
-                                }
-                                return true;
-                            }
-                        });
-                MenuItemCompat.setActionView(item, searchView);
-            }
+                @Override
+                public boolean onQueryTextSubmit(String query) {
+                    return false;
+                }
+            });
+
+            searchView.setOnCloseListener(new SearchView.OnCloseListener() {
+                @Override
+                public boolean onClose() {
+                    if (!TextUtils.isEmpty(searchView.getQuery())) {
+                        searchView.setQuery(null, true);
+                    }
+                    return true;
+                }
+            });
+
+            MenuItemCompat.setActionView(item, searchView);
         }
 
         @Override public void onListItemClick(ListView l, View v, int position, long id) {
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderRetainedSupport.java b/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderRetainedSupport.java
index 8ea47e3..c54d781 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderRetainedSupport.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderRetainedSupport.java
@@ -16,6 +16,10 @@
 
 package com.example.android.supportv4.app;
 
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.Contacts.People;
 import android.support.v4.app.FragmentActivity;
 import android.support.v4.app.FragmentManager;
 import android.support.v4.app.ListFragment;
@@ -23,15 +27,7 @@
 import android.support.v4.content.CursorLoader;
 import android.support.v4.content.Loader;
 import android.support.v4.view.MenuItemCompat;
-import android.support.v4.widget.SearchViewCompat;
-import android.support.v4.widget.SearchViewCompat.OnQueryTextListenerCompat;
 import android.support.v4.widget.SimpleCursorAdapter;
-
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.BaseColumns;
-import android.provider.Contacts.People;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.Menu;
@@ -39,6 +35,7 @@
 import android.view.MenuItem;
 import android.view.View;
 import android.widget.ListView;
+import android.widget.SearchView;
 
 /**
  * Demonstration of the use of a CursorLoader to load and display contacts
@@ -104,31 +101,33 @@
             item.setIcon(android.R.drawable.ic_menu_search);
             MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_ALWAYS
                     | MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
-            View searchView = SearchViewCompat.newSearchView(getActivity());
-            if (searchView != null) {
-                SearchViewCompat.setOnQueryTextListener(searchView,
-                        new OnQueryTextListenerCompat() {
-                    @Override
-                    public boolean onQueryTextChange(String newText) {
-                        // Called when the action bar search text has changed.  Update
-                        // the search filter, and restart the loader to do a new query
-                        // with this filter.
-                        String newFilter = !TextUtils.isEmpty(newText) ? newText : null;
-                        // Don't do anything if the filter hasn't actually changed.
-                        // Prevents restarting the loader when restoring state.
-                        if (mCurFilter == null && newFilter == null) {
-                            return true;
-                        }
-                        if (mCurFilter != null && mCurFilter.equals(newFilter)) {
-                            return true;
-                        }
-                        mCurFilter = newFilter;
-                        getLoaderManager().restartLoader(0, null, CursorLoaderListFragment.this);
+            SearchView searchView = new SearchView(getActivity());
+            searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
+                @Override
+                public boolean onQueryTextChange(String newText) {
+                    // Called when the action bar search text has changed.  Update
+                    // the search filter, and restart the loader to do a new query
+                    // with this filter.
+                    String newFilter = !TextUtils.isEmpty(newText) ? newText : null;
+                    // Don't do anything if the filter hasn't actually changed.
+                    // Prevents restarting the loader when restoring state.
+                    if (mCurFilter == null && newFilter == null) {
                         return true;
                     }
-                });
-                MenuItemCompat.setActionView(item, searchView);
-            }
+                    if (mCurFilter != null && mCurFilter.equals(newFilter)) {
+                        return true;
+                    }
+                    mCurFilter = newFilter;
+                    getLoaderManager().restartLoader(0, null, CursorLoaderListFragment.this);
+                    return true;
+                }
+
+                @Override
+                public boolean onQueryTextSubmit(String s) {
+                    return false;
+                }
+            });
+            MenuItemCompat.setActionView(item, searchView);
         }
 
         @Override public void onListItemClick(ListView l, View v, int position, long id) {
diff --git a/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaRouterActivity.java b/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaRouterActivity.java
index 5d33a1f..363245f 100644
--- a/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaRouterActivity.java
+++ b/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaRouterActivity.java
@@ -234,15 +234,13 @@
         DiscoveryFragment fragment = (DiscoveryFragment) fm.findFragmentByTag(
                 DISCOVERY_FRAGMENT_TAG);
         if (fragment == null) {
-            fragment = new DiscoveryFragment(mMediaRouterCB);
-            fragment.setRouteSelector(mSelector);
+            fragment = new DiscoveryFragment();
             fm.beginTransaction()
                     .add(fragment, DISCOVERY_FRAGMENT_TAG)
                     .commit();
-        } else {
-            fragment.setCallback(mMediaRouterCB);
-            fragment.setRouteSelector(mSelector);
         }
+        fragment.setCallback(mMediaRouterCB);
+        fragment.setRouteSelector(mSelector);
 
         // Populate an array adapter with streaming media items.
         String[] mediaNames = getResources().getStringArray(R.array.media_names);
@@ -639,14 +637,6 @@
         private static final String TAG = "DiscoveryFragment";
         private Callback mCallback;
 
-        public DiscoveryFragment() {
-            mCallback = null;
-        }
-
-        public DiscoveryFragment(Callback cb) {
-            mCallback = cb;
-        }
-
         public void setCallback(Callback cb) {
             mCallback = cb;
         }
diff --git a/tv-provider/src/android/support/media/tv/Program.java b/tv-provider/src/android/support/media/tv/Program.java
index 266755b..c766f96 100644
--- a/tv-provider/src/android/support/media/tv/Program.java
+++ b/tv-provider/src/android/support/media/tv/Program.java
@@ -517,8 +517,8 @@
     public int hashCode() {
         return Objects.hash(mChannelId, mStartTimeUtcMillis, mEndTimeUtcMillis,
                 mTitle, mEpisodeTitle, mDescription, mLongDescription, mVideoWidth, mVideoHeight,
-                mPosterArtUri, mThumbnailUri, mContentRatings, mCanonicalGenres, mSeasonNumber,
-                mEpisodeNumber);
+                mPosterArtUri, mThumbnailUri, Arrays.hashCode(mContentRatings),
+                Arrays.hashCode(mCanonicalGenres), mSeasonNumber, mEpisodeNumber);
     }
 
     @Override
diff --git a/v17/leanback/res/layout/lb_playback_fragment.xml b/v17/leanback/res/layout/lb_playback_fragment.xml
index 85d52cf..1b0ffa1 100644
--- a/v17/leanback/res/layout/lb_playback_fragment.xml
+++ b/v17/leanback/res/layout/lb_playback_fragment.xml
@@ -18,11 +18,12 @@
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@+id/playback_fragment_root"
         android:layout_width="match_parent"
+        android:transitionGroup="false"
         android:layout_height="match_parent">
 
     <FrameLayout
-            xmlns:android="http://schemas.android.com/apk/res/android"
             android:id="@+id/playback_controls_dock"
+            android:transitionGroup="true"
             android:layout_height="match_parent"
             android:layout_width="match_parent"/>
 </FrameLayout>
diff --git a/v17/leanback/res/layout/lb_video_surface.xml b/v17/leanback/res/layout/lb_video_surface.xml
index a3b0fe0..9c6c8fd 100644
--- a/v17/leanback/res/layout/lb_video_surface.xml
+++ b/v17/leanback/res/layout/lb_video_surface.xml
@@ -14,7 +14,8 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<SurfaceView xmlns:android="http://schemas.android.com/apk/res/android"
+<android.support.v17.leanback.widget.VideoSurfaceView
+    xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/video_surface"
     android:layout_width="match_parent"
     android:layout_height="match_parent" />
diff --git a/v17/leanback/res/transition-v21/lb_details_enter_transition.xml b/v17/leanback/res/transition-v21/lb_details_enter_transition.xml
index 3bb7c9f..d535ff4 100644
--- a/v17/leanback/res/transition-v21/lb_details_enter_transition.xml
+++ b/v17/leanback/res/transition-v21/lb_details_enter_transition.xml
@@ -25,6 +25,7 @@
           <target android:excludeId="@id/title_text" />
           <target android:excludeId="@id/title_orb" />
           <target android:excludeId="@id/details_background_view" />
+          <target android:excludeId="@id/video_surface" />
       </targets>
   </transition>
   <!-- The ParallaxTransition runs with with Slide transition, must use same duration
@@ -37,5 +38,8 @@
   </transition>
   <fade
       android:duration="350">
+      <targets>
+          <target android:excludeId="@id/video_surface" />
+      </targets>
   </fade>
 </transitionSet>
\ No newline at end of file
diff --git a/v17/leanback/res/transition-v21/lb_details_return_transition.xml b/v17/leanback/res/transition-v21/lb_details_return_transition.xml
index 5e54d2c..82a55f4 100644
--- a/v17/leanback/res/transition-v21/lb_details_return_transition.xml
+++ b/v17/leanback/res/transition-v21/lb_details_return_transition.xml
@@ -24,6 +24,7 @@
           <target android:excludeId="@id/title_text" />
           <target android:excludeId="@id/title_orb" />
           <target android:excludeId="@id/details_background_view" />
+          <target android:excludeId="@id/video_surface" />
       </targets>
   </transition>
     <!-- The ParallaxTransition runs with with Slide transition, must use same duration
@@ -36,5 +37,8 @@
   </transition>
   <fade
       android:duration="350">
+      <targets>
+          <target android:excludeId="@id/video_surface" />
+      </targets>
   </fade>
 </transitionSet>
\ No newline at end of file
diff --git a/v17/leanback/src/android/support/v17/leanback/app/DetailsBackgroundVideoHelper.java b/v17/leanback/src/android/support/v17/leanback/app/DetailsBackgroundVideoHelper.java
index cb3fa2f..72072a2 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/DetailsBackgroundVideoHelper.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/DetailsBackgroundVideoHelper.java
@@ -22,6 +22,7 @@
 import android.support.v17.leanback.media.PlaybackGlue;
 import android.support.v17.leanback.widget.DetailsParallax;
 import android.support.v17.leanback.widget.Parallax;
+import android.support.v17.leanback.widget.ParallaxEffect;
 import android.support.v17.leanback.widget.ParallaxTarget;
 
 /**
@@ -36,19 +37,19 @@
  */
 final class DetailsBackgroundVideoHelper {
     private static final long BACKGROUND_CROSS_FADE_DURATION = 500;
-    private static final long CROSSFADE_DELAY = 1000;
+    private static final long CROSSFADE_DELAY = 0;
 
     /**
      * Different states {@link DetailsFragment} can be in.
      */
-    enum STATE {
-        INITIAL,
-        PLAY_VIDEO,
-        NO_VIDEO
-    }
+    static final int INITIAL = 0;
+    static final int PLAY_VIDEO = 1;
+    static final int NO_VIDEO = 2;
 
     private final DetailsParallax mDetailsParallax;
-    private STATE mCurrentState = STATE.INITIAL;
+    private ParallaxEffect mParallaxEffect;
+
+    private int mCurrentState = INITIAL;
 
     private ValueAnimator mBackgroundAnimator;
     private Drawable mBackgroundDrawable;
@@ -72,14 +73,17 @@
         this.mPlaybackGlue = playbackGlue;
         this.mDetailsParallax = detailsParallax;
         this.mBackgroundDrawable = backgroundDrawable;
-        setupParallax();
+        startParallax();
     }
 
-    void setupParallax() {
+    void startParallax() {
+        if (mParallaxEffect != null) {
+            return;
+        }
         Parallax.IntProperty frameTop = mDetailsParallax.getOverviewRowTop();
         final float maxFrameTop = 1f;
         final float minFrameTop = 0f;
-        mDetailsParallax
+        mParallaxEffect = mDetailsParallax
                 .addEffect(frameTop.atFraction(maxFrameTop), frameTop.atFraction(minFrameTop))
                 .target(new ParallaxTarget() {
 
@@ -87,9 +91,9 @@
                     @Override
                     public void update(float fraction) {
                         if (fraction == maxFrameTop) {
-                            updateState(STATE.NO_VIDEO);
+                            updateState(NO_VIDEO);
                         } else {
-                            updateState(STATE.PLAY_VIDEO);
+                            updateState(PLAY_VIDEO);
                         }
                         mFraction = fraction;
                     }
@@ -101,7 +105,15 @@
                 });
     }
 
-    private void updateState(STATE state) {
+    void stopParallax() {
+        mDetailsParallax.removeEffect(mParallaxEffect);
+    }
+
+    boolean isVideoVisible() {
+        return mCurrentState == PLAY_VIDEO;
+    }
+
+    private void updateState(int state) {
         if (state == mCurrentState) {
             return;
         }
diff --git a/v17/leanback/src/android/support/v17/leanback/app/DetailsFragment.java b/v17/leanback/src/android/support/v17/leanback/app/DetailsFragment.java
index b26aabc..ac11fde 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/DetailsFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/DetailsFragment.java
@@ -13,13 +13,16 @@
  */
 package android.support.v17.leanback.app;
 
+import android.app.Activity;
 import android.app.Fragment;
 import android.app.FragmentTransaction;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.os.Bundle;
+import android.support.annotation.CallSuper;
 import android.support.v17.leanback.R;
 import android.support.v17.leanback.transition.TransitionHelper;
+import android.support.v17.leanback.transition.TransitionListener;
 import android.support.v17.leanback.widget.BaseOnItemViewClickedListener;
 import android.support.v17.leanback.widget.BaseOnItemViewSelectedListener;
 import android.support.v17.leanback.widget.BrowseFrameLayout;
@@ -38,6 +41,8 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import java.lang.ref.WeakReference;
+
 /**
  * A fragment for creating Leanback details screens.
  *
@@ -76,6 +81,23 @@
     static final String TAG = "DetailsFragment";
     static boolean DEBUG = false;
 
+    /**
+     * Flag for "possibly" having enter transition not finished yet.
+     * @see #mStartAndTransitionFlag
+     */
+    static final int PF_ENTER_TRANSITION_PENDING = 0x1 << 0;
+    /**
+     * Flag for having entrance transition not finished yet.
+     * @see #mStartAndTransitionFlag
+     */
+    static final int PF_ENTRANCE_TRANSITION_PENDING = 0x1 << 1;
+    /**
+     * Flag that onStart() has been called and about to call onSafeStart() when
+     * pending transitions are finished.
+     * @see #mStartAndTransitionFlag
+     */
+    static final int PF_PENDING_START = 0x1 << 2;
+
     private class SetSelectionRunnable implements Runnable {
         int mPosition;
         boolean mSmooth = true;
@@ -92,6 +114,61 @@
         }
     }
 
+    /**
+     * Start this task when first DetailsOverviewRow is created, if there is no entrance transition
+     * started, it will clear PF_ENTRANCE_TRANSITION_PENDING.
+     * @see #mStartAndTransitionFlag
+     */
+    static class WaitEnterTransitionTimeout implements Runnable {
+        static final long WAIT_ENTERTRANSITION_START = 200;
+
+        final WeakReference<DetailsFragment> mRef;
+
+        WaitEnterTransitionTimeout(DetailsFragment f) {
+            mRef = new WeakReference(f);
+            f.getView().postDelayed(this, WAIT_ENTERTRANSITION_START);
+        }
+
+        @Override
+        public void run() {
+            DetailsFragment f = mRef.get();
+            if (f != null) {
+                f.clearPendingEnterTransition();
+            }
+        }
+    }
+
+    /**
+     * @see #mStartAndTransitionFlag
+     */
+    TransitionListener mEnterTransitionListener = new TransitionListener() {
+        @Override
+        public void onTransitionStart(Object transition) {
+            if (mWaitEnterTransitionTimeout != null) {
+                // cancel task of WaitEnterTransitionTimeout, we will clearPendingEnterTransition
+                // when transition finishes.
+                mWaitEnterTransitionTimeout.mRef.clear();
+            }
+        }
+
+        @Override
+        public void onTransitionCancel(Object transition) {
+            clearPendingEnterTransition();
+        }
+
+        @Override
+        public void onTransitionEnd(Object transition) {
+            clearPendingEnterTransition();
+        }
+    };
+
+    TransitionListener mReturnTransitionListener = new TransitionListener() {
+        @Override
+        public void onTransitionStart(Object transition) {
+            onReturnTransitionStart();
+        }
+    };
+
     BrowseFrameLayout mRootView;
     View mBackgroundView;
     Drawable mBackgroundDrawable;
@@ -104,6 +181,25 @@
     BaseOnItemViewClickedListener mOnItemViewClickedListener;
     DetailsFragmentBackgroundController mDetailsBackgroundController;
 
+
+    /**
+     * Flags for enter transition, entrance transition and onStart.  When onStart() is called
+     * and both enter transiton and entrance transition are finished, we could call onSafeStart().
+     * 1. in onCreate:
+     *      if user call prepareEntranceTransition, set PF_ENTRANCE_TRANSITION_PENDING
+     *      if there is enterTransition, set PF_ENTER_TRANSITION_PENDING, but we dont know if
+     *      user will run enterTransition or not.
+     * 2. when user add row, start WaitEnterTransitionTimeout to wait possible enter transition
+     * start. If enter transition onTransitionStart is not invoked with a period, we can assume
+     * there is no enter transition running, then WaitEnterTransitionTimeout will clear
+     * PF_ENTER_TRANSITION_PENDING.
+     * 3. When enterTransition runs (either postponed or not),  we will stop the
+     * WaitEnterTransitionTimeout, and let onTransitionEnd/onTransitionCancel to clear
+     * PF_ENTER_TRANSITION_PENDING.
+     */
+    int mStartAndTransitionFlag = 0;
+    WaitEnterTransitionTimeout mWaitEnterTransitionTimeout;
+
     Object mSceneAfterEntranceTransition;
 
     final SetSelectionRunnable mSetSelectionRunnable = new SetSelectionRunnable();
@@ -181,6 +277,19 @@
         super.onCreate(savedInstanceState);
         mContainerListAlignTop =
             getResources().getDimensionPixelSize(R.dimen.lb_details_rows_align_top);
+
+        Activity activity = getActivity();
+        if (activity != null) {
+            Object transition = TransitionHelper.getEnterTransition(activity.getWindow());
+            if (transition != null) {
+                mStartAndTransitionFlag |= PF_ENTER_TRANSITION_PENDING;
+                TransitionHelper.addTransitionListener(transition, mEnterTransitionListener);
+            }
+            transition = TransitionHelper.getReturnTransition(activity.getWindow());
+            if (transition != null) {
+                TransitionHelper.addTransitionListener(transition, mReturnTransitionListener);
+            }
+        }
     }
 
     @Override
@@ -369,6 +478,11 @@
         if (adapter != null && adapter.size() > selectedPosition) {
             final VerticalGridView gridView = getVerticalGridView();
             final int count = gridView.getChildCount();
+            if (count > 0 && (mStartAndTransitionFlag & PF_ENTER_TRANSITION_PENDING) != 0) {
+                if (mWaitEnterTransitionTimeout == null) {
+                    mWaitEnterTransitionTimeout = new WaitEnterTransitionTimeout(this);
+                }
+            }
             for (int i = 0; i < count; i++) {
                 ItemBridgeAdapter.ViewHolder bridgeViewHolder = (ItemBridgeAdapter.ViewHolder)
                         gridView.getChildViewHolder(gridView.getChildAt(i));
@@ -381,6 +495,52 @@
         }
     }
 
+    void clearPendingEnterTransition() {
+        if ((mStartAndTransitionFlag & PF_ENTER_TRANSITION_PENDING) != 0) {
+            mStartAndTransitionFlag &= ~PF_ENTER_TRANSITION_PENDING;
+            dispatchOnStartAndTransitionFinished();
+        }
+    }
+
+    void dispatchOnStartAndTransitionFinished() {
+        /**
+         * if onStart() was called and there is no pending enter transition or entrance transition.
+         */
+        if ((mStartAndTransitionFlag & PF_PENDING_START) != 0
+                && (mStartAndTransitionFlag
+                & (PF_ENTER_TRANSITION_PENDING | PF_ENTRANCE_TRANSITION_PENDING)) == 0) {
+            mStartAndTransitionFlag &= ~PF_PENDING_START;
+            onSafeStart();
+        }
+    }
+
+    /**
+     * Called when onStart and enter transition (postponed/none postponed) and entrance transition
+     * are all finished.
+     */
+    @CallSuper
+    void onSafeStart() {
+        if (mDetailsBackgroundController != null) {
+            mDetailsBackgroundController.enablePlaybackHost();
+        }
+    }
+
+    @CallSuper
+    void onReturnTransitionStart() {
+        if (mDetailsBackgroundController != null) {
+            // first disable parallax effect that auto-start PlaybackGlue.
+            boolean isVideoVisible = mDetailsBackgroundController.disableVideoParallax();
+            // if video is not visible we can safely remove VideoFragment,
+            // otherwise let video playing during return transition.
+            if (!isVideoVisible && mVideoFragment != null) {
+                FragmentTransaction ft2 = getChildFragmentManager().beginTransaction();
+                ft2.remove(mVideoFragment);
+                ft2.commit();
+                mVideoFragment = null;
+            }
+        }
+    }
+
     /**
      * Called on every visible row to change view status when current selected row position
      * or selected sub position changed.  Subclass may override.   The default
@@ -439,6 +599,10 @@
     @Override
     public void onStart() {
         super.onStart();
+
+        mStartAndTransitionFlag |= PF_PENDING_START;
+        dispatchOnStartAndTransitionFinished();
+
         setupChildFragmentLayout();
         if (isEntranceTransitionEnabled()) {
             mRowsFragment.setEntranceTransitionState(false);
@@ -462,11 +626,14 @@
 
     @Override
     protected void onEntranceTransitionEnd() {
+        mStartAndTransitionFlag &= ~PF_ENTRANCE_TRANSITION_PENDING;
+        dispatchOnStartAndTransitionFinished();
         mRowsFragment.onTransitionEnd();
     }
 
     @Override
     protected void onEntranceTransitionPrepare() {
+        mStartAndTransitionFlag |= PF_ENTRANCE_TRANSITION_PENDING;
         mRowsFragment.onTransitionPrepare();
     }
 
diff --git a/v17/leanback/src/android/support/v17/leanback/app/DetailsFragmentBackgroundController.java b/v17/leanback/src/android/support/v17/leanback/app/DetailsFragmentBackgroundController.java
index 9f9ed26..a0bf00c 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/DetailsFragmentBackgroundController.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/DetailsFragmentBackgroundController.java
@@ -114,6 +114,7 @@
     private DetailsBackgroundVideoHelper mVideoHelper;
     private Bitmap mCoverBitmap;
     private int mSolidColor;
+    private boolean mCanUseHost = false;
 
     /**
      * Creates a DetailsFragmentBackgroundController for a DetailsFragment. Note that
@@ -208,17 +209,47 @@
     /**
      * Enable video playback and set proper {@link PlaybackGlueHost}. This method by default
      * creates a VideoFragment and VideoFragmentGlueHost to host the PlaybackGlue.
-     * This method must be called after calling Fragment super.onCreate().
+     * This method must be called after calling details Fragment super.onCreate().
      *
      * @param playbackGlue
      * @see #onCreateVideoFragment()
      * @see #onCreateGlueHost().
      */
     public void setupVideoPlayback(@NonNull PlaybackGlue playbackGlue) {
+        if (mPlaybackGlue == playbackGlue) {
+            return;
+        }
         mPlaybackGlue = playbackGlue;
-        mPlaybackGlue.setHost(onCreateGlueHost());
         mVideoHelper = new DetailsBackgroundVideoHelper(mPlaybackGlue,
                 mFragment.getParallax(), mParallaxDrawable.getCoverDrawable());
+        if (mCanUseHost) {
+            mPlaybackGlue.setHost(onCreateGlueHost());
+        }
+    }
+
+    /**
+     * Enable Host for PlaybackGlue. This is delayed until: onStart() is called,
+     * activity transitions are finished.
+     */
+    void enablePlaybackHost() {
+        if (!mCanUseHost) {
+            mCanUseHost = true;
+            if (mPlaybackGlue != null) {
+                mPlaybackGlue.setHost(onCreateGlueHost());
+            }
+        }
+    }
+
+    /**
+     * Disable parallax that would auto-start video playback
+     * @return true if video fragment is visible or false otherwise.
+     */
+    boolean disableVideoParallax() {
+        if (mVideoHelper != null) {
+            mVideoHelper.stopParallax();
+            return mVideoHelper.isVideoVisible();
+        }
+        return false;
     }
 
     /**
@@ -360,15 +391,4 @@
         return mParallaxDrawableMaxOffset;
     }
 
-    void onStart() {
-        if (mPlaybackGlue != null) {
-            mPlaybackGlue.play();
-        }
-    }
-
-    void onStop() {
-        if (mPlaybackGlue != null) {
-            mPlaybackGlue.pause();
-        }
-    }
 }
diff --git a/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragment.java
index 2a759de..53300ac 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragment.java
@@ -16,13 +16,16 @@
  */
 package android.support.v17.leanback.app;
 
+import android.support.v4.app.FragmentActivity;
 import android.support.v4.app.Fragment;
 import android.support.v4.app.FragmentTransaction;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.os.Bundle;
+import android.support.annotation.CallSuper;
 import android.support.v17.leanback.R;
 import android.support.v17.leanback.transition.TransitionHelper;
+import android.support.v17.leanback.transition.TransitionListener;
 import android.support.v17.leanback.widget.BaseOnItemViewClickedListener;
 import android.support.v17.leanback.widget.BaseOnItemViewSelectedListener;
 import android.support.v17.leanback.widget.BrowseFrameLayout;
@@ -41,6 +44,8 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import java.lang.ref.WeakReference;
+
 /**
  * A fragment for creating Leanback details screens.
  *
@@ -79,6 +84,23 @@
     static final String TAG = "DetailsSupportFragment";
     static boolean DEBUG = false;
 
+    /**
+     * Flag for "possibly" having enter transition not finished yet.
+     * @see #mStartAndTransitionFlag
+     */
+    static final int PF_ENTER_TRANSITION_PENDING = 0x1 << 0;
+    /**
+     * Flag for having entrance transition not finished yet.
+     * @see #mStartAndTransitionFlag
+     */
+    static final int PF_ENTRANCE_TRANSITION_PENDING = 0x1 << 1;
+    /**
+     * Flag that onStart() has been called and about to call onSafeStart() when
+     * pending transitions are finished.
+     * @see #mStartAndTransitionFlag
+     */
+    static final int PF_PENDING_START = 0x1 << 2;
+
     private class SetSelectionRunnable implements Runnable {
         int mPosition;
         boolean mSmooth = true;
@@ -95,6 +117,61 @@
         }
     }
 
+    /**
+     * Start this task when first DetailsOverviewRow is created, if there is no entrance transition
+     * started, it will clear PF_ENTRANCE_TRANSITION_PENDING.
+     * @see #mStartAndTransitionFlag
+     */
+    static class WaitEnterTransitionTimeout implements Runnable {
+        static final long WAIT_ENTERTRANSITION_START = 200;
+
+        final WeakReference<DetailsSupportFragment> mRef;
+
+        WaitEnterTransitionTimeout(DetailsSupportFragment f) {
+            mRef = new WeakReference(f);
+            f.getView().postDelayed(this, WAIT_ENTERTRANSITION_START);
+        }
+
+        @Override
+        public void run() {
+            DetailsSupportFragment f = mRef.get();
+            if (f != null) {
+                f.clearPendingEnterTransition();
+            }
+        }
+    }
+
+    /**
+     * @see #mStartAndTransitionFlag
+     */
+    TransitionListener mEnterTransitionListener = new TransitionListener() {
+        @Override
+        public void onTransitionStart(Object transition) {
+            if (mWaitEnterTransitionTimeout != null) {
+                // cancel task of WaitEnterTransitionTimeout, we will clearPendingEnterTransition
+                // when transition finishes.
+                mWaitEnterTransitionTimeout.mRef.clear();
+            }
+        }
+
+        @Override
+        public void onTransitionCancel(Object transition) {
+            clearPendingEnterTransition();
+        }
+
+        @Override
+        public void onTransitionEnd(Object transition) {
+            clearPendingEnterTransition();
+        }
+    };
+
+    TransitionListener mReturnTransitionListener = new TransitionListener() {
+        @Override
+        public void onTransitionStart(Object transition) {
+            onReturnTransitionStart();
+        }
+    };
+
     BrowseFrameLayout mRootView;
     View mBackgroundView;
     Drawable mBackgroundDrawable;
@@ -107,6 +184,25 @@
     BaseOnItemViewClickedListener mOnItemViewClickedListener;
     DetailsSupportFragmentBackgroundController mDetailsBackgroundController;
 
+
+    /**
+     * Flags for enter transition, entrance transition and onStart.  When onStart() is called
+     * and both enter transiton and entrance transition are finished, we could call onSafeStart().
+     * 1. in onCreate:
+     *      if user call prepareEntranceTransition, set PF_ENTRANCE_TRANSITION_PENDING
+     *      if there is enterTransition, set PF_ENTER_TRANSITION_PENDING, but we dont know if
+     *      user will run enterTransition or not.
+     * 2. when user add row, start WaitEnterTransitionTimeout to wait possible enter transition
+     * start. If enter transition onTransitionStart is not invoked with a period, we can assume
+     * there is no enter transition running, then WaitEnterTransitionTimeout will clear
+     * PF_ENTER_TRANSITION_PENDING.
+     * 3. When enterTransition runs (either postponed or not),  we will stop the
+     * WaitEnterTransitionTimeout, and let onTransitionEnd/onTransitionCancel to clear
+     * PF_ENTER_TRANSITION_PENDING.
+     */
+    int mStartAndTransitionFlag = 0;
+    WaitEnterTransitionTimeout mWaitEnterTransitionTimeout;
+
     Object mSceneAfterEntranceTransition;
 
     final SetSelectionRunnable mSetSelectionRunnable = new SetSelectionRunnable();
@@ -184,6 +280,19 @@
         super.onCreate(savedInstanceState);
         mContainerListAlignTop =
             getResources().getDimensionPixelSize(R.dimen.lb_details_rows_align_top);
+
+        FragmentActivity activity = getActivity();
+        if (activity != null) {
+            Object transition = TransitionHelper.getEnterTransition(activity.getWindow());
+            if (transition != null) {
+                mStartAndTransitionFlag |= PF_ENTER_TRANSITION_PENDING;
+                TransitionHelper.addTransitionListener(transition, mEnterTransitionListener);
+            }
+            transition = TransitionHelper.getReturnTransition(activity.getWindow());
+            if (transition != null) {
+                TransitionHelper.addTransitionListener(transition, mReturnTransitionListener);
+            }
+        }
     }
 
     @Override
@@ -372,6 +481,11 @@
         if (adapter != null && adapter.size() > selectedPosition) {
             final VerticalGridView gridView = getVerticalGridView();
             final int count = gridView.getChildCount();
+            if (count > 0 && (mStartAndTransitionFlag & PF_ENTER_TRANSITION_PENDING) != 0) {
+                if (mWaitEnterTransitionTimeout == null) {
+                    mWaitEnterTransitionTimeout = new WaitEnterTransitionTimeout(this);
+                }
+            }
             for (int i = 0; i < count; i++) {
                 ItemBridgeAdapter.ViewHolder bridgeViewHolder = (ItemBridgeAdapter.ViewHolder)
                         gridView.getChildViewHolder(gridView.getChildAt(i));
@@ -384,6 +498,52 @@
         }
     }
 
+    void clearPendingEnterTransition() {
+        if ((mStartAndTransitionFlag & PF_ENTER_TRANSITION_PENDING) != 0) {
+            mStartAndTransitionFlag &= ~PF_ENTER_TRANSITION_PENDING;
+            dispatchOnStartAndTransitionFinished();
+        }
+    }
+
+    void dispatchOnStartAndTransitionFinished() {
+        /**
+         * if onStart() was called and there is no pending enter transition or entrance transition.
+         */
+        if ((mStartAndTransitionFlag & PF_PENDING_START) != 0
+                && (mStartAndTransitionFlag
+                & (PF_ENTER_TRANSITION_PENDING | PF_ENTRANCE_TRANSITION_PENDING)) == 0) {
+            mStartAndTransitionFlag &= ~PF_PENDING_START;
+            onSafeStart();
+        }
+    }
+
+    /**
+     * Called when onStart and enter transition (postponed/none postponed) and entrance transition
+     * are all finished.
+     */
+    @CallSuper
+    void onSafeStart() {
+        if (mDetailsBackgroundController != null) {
+            mDetailsBackgroundController.enablePlaybackHost();
+        }
+    }
+
+    @CallSuper
+    void onReturnTransitionStart() {
+        if (mDetailsBackgroundController != null) {
+            // first disable parallax effect that auto-start PlaybackGlue.
+            boolean isVideoVisible = mDetailsBackgroundController.disableVideoParallax();
+            // if video is not visible we can safely remove VideoSupportFragment,
+            // otherwise let video playing during return transition.
+            if (!isVideoVisible && mVideoSupportFragment != null) {
+                FragmentTransaction ft2 = getChildFragmentManager().beginTransaction();
+                ft2.remove(mVideoSupportFragment);
+                ft2.commit();
+                mVideoSupportFragment = null;
+            }
+        }
+    }
+
     /**
      * Called on every visible row to change view status when current selected row position
      * or selected sub position changed.  Subclass may override.   The default
@@ -442,6 +602,10 @@
     @Override
     public void onStart() {
         super.onStart();
+
+        mStartAndTransitionFlag |= PF_PENDING_START;
+        dispatchOnStartAndTransitionFinished();
+
         setupChildFragmentLayout();
         if (isEntranceTransitionEnabled()) {
             mRowsSupportFragment.setEntranceTransitionState(false);
@@ -465,11 +629,14 @@
 
     @Override
     protected void onEntranceTransitionEnd() {
+        mStartAndTransitionFlag &= ~PF_ENTRANCE_TRANSITION_PENDING;
+        dispatchOnStartAndTransitionFinished();
         mRowsSupportFragment.onTransitionEnd();
     }
 
     @Override
     protected void onEntranceTransitionPrepare() {
+        mStartAndTransitionFlag |= PF_ENTRANCE_TRANSITION_PENDING;
         mRowsSupportFragment.onTransitionPrepare();
     }
 
diff --git a/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragmentBackgroundController.java b/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragmentBackgroundController.java
index e450c3b..5ab42c3 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragmentBackgroundController.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragmentBackgroundController.java
@@ -117,6 +117,7 @@
     private DetailsBackgroundVideoHelper mVideoHelper;
     private Bitmap mCoverBitmap;
     private int mSolidColor;
+    private boolean mCanUseHost = false;
 
     /**
      * Creates a DetailsSupportFragmentBackgroundController for a DetailsSupportFragment. Note that
@@ -211,17 +212,47 @@
     /**
      * Enable video playback and set proper {@link PlaybackGlueHost}. This method by default
      * creates a VideoSupportFragment and VideoSupportFragmentGlueHost to host the PlaybackGlue.
-     * This method must be called after calling Fragment super.onCreate().
+     * This method must be called after calling details Fragment super.onCreate().
      *
      * @param playbackGlue
      * @see #onCreateVideoSupportFragment()
      * @see #onCreateGlueHost().
      */
     public void setupVideoPlayback(@NonNull PlaybackGlue playbackGlue) {
+        if (mPlaybackGlue == playbackGlue) {
+            return;
+        }
         mPlaybackGlue = playbackGlue;
-        mPlaybackGlue.setHost(onCreateGlueHost());
         mVideoHelper = new DetailsBackgroundVideoHelper(mPlaybackGlue,
                 mFragment.getParallax(), mParallaxDrawable.getCoverDrawable());
+        if (mCanUseHost) {
+            mPlaybackGlue.setHost(onCreateGlueHost());
+        }
+    }
+
+    /**
+     * Enable Host for PlaybackGlue. This is delayed until: onStart() is called,
+     * activity transitions are finished.
+     */
+    void enablePlaybackHost() {
+        if (!mCanUseHost) {
+            mCanUseHost = true;
+            if (mPlaybackGlue != null) {
+                mPlaybackGlue.setHost(onCreateGlueHost());
+            }
+        }
+    }
+
+    /**
+     * Disable parallax that would auto-start video playback
+     * @return true if video fragment is visible or false otherwise.
+     */
+    boolean disableVideoParallax() {
+        if (mVideoHelper != null) {
+            mVideoHelper.stopParallax();
+            return mVideoHelper.isVideoVisible();
+        }
+        return false;
     }
 
     /**
@@ -363,15 +394,4 @@
         return mParallaxDrawableMaxOffset;
     }
 
-    void onStart() {
-        if (mPlaybackGlue != null) {
-            mPlaybackGlue.play();
-        }
-    }
-
-    void onStop() {
-        if (mPlaybackGlue != null) {
-            mPlaybackGlue.pause();
-        }
-    }
 }
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 cf9d424..87f8402 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java
@@ -1334,7 +1334,7 @@
             if (DEBUG) Log.v(getTag(), "request Layout from runnable");
             requestLayout();
         }
-    };
+     };
 
     @Override
     public void onMeasure(Recycler recycler, State state, int widthSpec, int heightSpec) {
@@ -1374,18 +1374,18 @@
             processRowSizeSecondary(true);
 
             switch (modeSecondary) {
-                case MeasureSpec.UNSPECIFIED:
-                    measuredSizeSecondary = getSizeSecondary() + paddingSecondary;
-                    break;
-                case MeasureSpec.AT_MOST:
-                    measuredSizeSecondary = Math.min(getSizeSecondary() + paddingSecondary,
-                            mMaxSizeSecondary);
-                    break;
-                case MeasureSpec.EXACTLY:
-                    measuredSizeSecondary = mMaxSizeSecondary;
-                    break;
-                default:
-                    throw new IllegalStateException("wrong spec");
+            case MeasureSpec.UNSPECIFIED:
+                measuredSizeSecondary = getSizeSecondary() + paddingSecondary;
+                break;
+            case MeasureSpec.AT_MOST:
+                measuredSizeSecondary = Math.min(getSizeSecondary() + paddingSecondary,
+                        mMaxSizeSecondary);
+                break;
+            case MeasureSpec.EXACTLY:
+                measuredSizeSecondary = mMaxSizeSecondary;
+                break;
+            default:
+                throw new IllegalStateException("wrong spec");
             }
 
         } else {
@@ -1395,7 +1395,7 @@
                             ? sizeSecondary - paddingSecondary : mRowSizeSecondaryRequested;
                     mNumRows = mNumRowsRequested == 0 ? 1 : mNumRowsRequested;
                     measuredSizeSecondary = mFixedRowSizeSecondary * mNumRows + mSpacingSecondary
-                            * (mNumRows - 1) + paddingSecondary;
+                        * (mNumRows - 1) + paddingSecondary;
                     break;
                 case MeasureSpec.AT_MOST:
                 case MeasureSpec.EXACTLY:
@@ -1405,7 +1405,7 @@
                     } else if (mNumRowsRequested == 0) {
                         mFixedRowSizeSecondary = mRowSizeSecondaryRequested;
                         mNumRows = (sizeSecondary + mSpacingSecondary)
-                                / (mRowSizeSecondaryRequested + mSpacingSecondary);
+                            / (mRowSizeSecondaryRequested + mSpacingSecondary);
                     } else if (mRowSizeSecondaryRequested == 0) {
                         mNumRows = mNumRowsRequested;
                         mFixedRowSizeSecondary = (sizeSecondary - paddingSecondary
@@ -1646,7 +1646,7 @@
         final int verticalGravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
         final int horizontalGravity = (mReverseFlowPrimary || mReverseFlowSecondary)
                 ? Gravity.getAbsoluteGravity(mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK,
-                View.LAYOUT_DIRECTION_RTL)
+                        View.LAYOUT_DIRECTION_RTL)
                 : mGravity & Gravity.HORIZONTAL_GRAVITY_MASK;
         if (mOrientation == HORIZONTAL && verticalGravity == Gravity.TOP
                 || mOrientation == VERTICAL && horizontalGravity == Gravity.LEFT) {
@@ -2442,7 +2442,7 @@
         if (DEBUG) Log.v(getTag(), "onItemsRemoved positionStart "
                 + positionStart + " itemCount " + itemCount);
         if (mFocusPosition != NO_POSITION  && mGrid != null && mGrid.getFirstVisibleIndex() >= 0
-                && mFocusPositionOffset != Integer.MIN_VALUE) {
+            && mFocusPositionOffset != Integer.MIN_VALUE) {
             int pos = mFocusPosition + mFocusPositionOffset;
             if (positionStart <= pos) {
                 if (positionStart + itemCount > pos) {
@@ -2638,12 +2638,12 @@
 
     boolean getScrollPosition(View view, View childView, int[] deltas) {
         switch (mFocusScrollStrategy) {
-            case BaseGridView.FOCUS_SCROLL_ALIGNED:
-            default:
-                return getAlignedPosition(view, childView, deltas);
-            case BaseGridView.FOCUS_SCROLL_ITEM:
-            case BaseGridView.FOCUS_SCROLL_PAGE:
-                return getNoneAlignedPosition(view, deltas);
+        case BaseGridView.FOCUS_SCROLL_ALIGNED:
+        default:
+            return getAlignedPosition(view, childView, deltas);
+        case BaseGridView.FOCUS_SCROLL_ITEM:
+        case BaseGridView.FOCUS_SCROLL_PAGE:
+            return getNoneAlignedPosition(view, deltas);
         }
     }
 
@@ -3083,14 +3083,14 @@
     boolean gridOnRequestFocusInDescendants(RecyclerView recyclerView, int direction,
             Rect previouslyFocusedRect) {
         switch (mFocusScrollStrategy) {
-            case BaseGridView.FOCUS_SCROLL_ALIGNED:
-            default:
-                return gridOnRequestFocusInDescendantsAligned(recyclerView,
-                        direction, previouslyFocusedRect);
-            case BaseGridView.FOCUS_SCROLL_PAGE:
-            case BaseGridView.FOCUS_SCROLL_ITEM:
-                return gridOnRequestFocusInDescendantsUnaligned(recyclerView,
-                        direction, previouslyFocusedRect);
+        case BaseGridView.FOCUS_SCROLL_ALIGNED:
+        default:
+            return gridOnRequestFocusInDescendantsAligned(recyclerView,
+                    direction, previouslyFocusedRect);
+        case BaseGridView.FOCUS_SCROLL_PAGE:
+        case BaseGridView.FOCUS_SCROLL_ITEM:
+            return gridOnRequestFocusInDescendantsUnaligned(recyclerView,
+                    direction, previouslyFocusedRect);
         }
     }
 
@@ -3161,22 +3161,22 @@
                     movement = NEXT_ROW;
                     break;
             }
-        } else if (mOrientation == VERTICAL) {
-            switch(direction) {
-                case View.FOCUS_LEFT:
-                    movement = (!mReverseFlowSecondary) ? PREV_ROW : NEXT_ROW;
-                    break;
-                case View.FOCUS_RIGHT:
-                    movement = (!mReverseFlowSecondary) ? NEXT_ROW : PREV_ROW;
-                    break;
-                case View.FOCUS_UP:
-                    movement = PREV_ITEM;
-                    break;
-                case View.FOCUS_DOWN:
-                    movement = NEXT_ITEM;
-                    break;
-            }
-        }
+         } else if (mOrientation == VERTICAL) {
+             switch(direction) {
+                 case View.FOCUS_LEFT:
+                     movement = (!mReverseFlowSecondary) ? PREV_ROW : NEXT_ROW;
+                     break;
+                 case View.FOCUS_RIGHT:
+                     movement = (!mReverseFlowSecondary) ? NEXT_ROW : PREV_ROW;
+                     break;
+                 case View.FOCUS_UP:
+                     movement = PREV_ITEM;
+                     break;
+                 case View.FOCUS_DOWN:
+                     movement = NEXT_ITEM;
+                     break;
+             }
+         }
 
         return movement;
     }
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/VideoSurfaceView.java b/v17/leanback/src/android/support/v17/leanback/widget/VideoSurfaceView.java
new file mode 100644
index 0000000..29d778c
--- /dev/null
+++ b/v17/leanback/src/android/support/v17/leanback/widget/VideoSurfaceView.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2017 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.content.Context;
+import android.util.AttributeSet;
+import android.view.SurfaceView;
+
+/**
+ * Activity transition will change transitionVisibility multiple times even the view is not
+ * running transition, which causes visual flickering during activity return transition.
+ * This class disables setTransitionVisibility() to avoid the problem.
+ * @hide
+ */
+public class VideoSurfaceView extends SurfaceView {
+
+    public VideoSurfaceView(Context context) {
+        super(context);
+    }
+
+    public VideoSurfaceView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public VideoSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    /**
+     * Overrides hidden method View.setTransitionVisibility() to disable visibility changes
+     * in activity transition.
+     */
+    public void setTransitionVisibility(int visibility) {
+    }
+
+}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/picker/Picker.java b/v17/leanback/src/android/support/v17/leanback/widget/picker/Picker.java
index 1c95194..28d7aeb 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/picker/Picker.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/picker/Picker.java
@@ -197,6 +197,11 @@
             // Width is dynamic, so has fixed size is false.
             columnView.setHasFixedSize(false);
             columnView.setFocusable(isActivated());
+            // Setting cache size to zero in order to rebind item views when picker widget becomes
+            // activated. Rebinding is necessary to update the alphas when the columns are expanded
+            // as a result of the picker getting activated, otherwise the cached views with the
+            // wrong alphas could be laid out.
+            columnView.setItemViewCacheSize(0);
             mColumnViews.add(columnView);
 
             // add view to root
@@ -550,9 +555,6 @@
 
     @Override
     public void setActivated(boolean activated) {
-        if (activated && !isFocusable()) {
-            throw new IllegalStateException("Cannot activate an unfocusable Picker widget.");
-        }
         if (activated == isActivated()) {
             super.setActivated(activated);
             return;
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/widget/DatePickerTest.java b/v17/leanback/tests/java/android/support/v17/leanback/widget/DatePickerTest.java
index fc0df10..9a0b1c5 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/widget/DatePickerTest.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/widget/DatePickerTest.java
@@ -18,6 +18,7 @@
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
 
 import android.content.Context;
 import android.content.Intent;
@@ -314,6 +315,66 @@
                 mDatePickerInnerView.getChildAt(4).hasFocus(), is(true));
     }
 
+    @Test
+    public void testInvisibleColumnsAlpha() throws Throwable {
+        Intent intent = new Intent();
+        intent.putExtra(DatePickerActivity.EXTRA_LAYOUT_RESOURCE_ID,
+                R.layout.datepicker_with_other_widgets);
+        initActivity(intent);
+
+        mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mDatePickerView.updateDate(2017, 2, 21, false);
+            }
+        });
+
+        Thread.sleep(TRANSITION_LENGTH);
+        mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mDatePickerView.updateDate(2017, 2, 20, false);
+            }
+        });
+        Thread.sleep(TRANSITION_LENGTH);
+
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        Thread.sleep(TRANSITION_LENGTH);
+        // Click once to activate
+        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        Thread.sleep(TRANSITION_LENGTH);
+
+        int activeColumn = 0;
+        // For the inactive columns: the alpha for all the rows except the selected row should be
+        // zero: Picker#mInvisibleColumnAlpha (they should all be invisible).
+        for (int i = 0; i < 3; i++) {
+            ViewGroup gridView = (ViewGroup) mDatePickerInnerView.getChildAt(2 * i);
+            int childCount = gridView.getChildCount();
+            int alpha1RowsCount = 0;
+            int alphaNonZeroRowsCount = 0;
+            for (int j = 0; j < childCount; j++) {
+                View pickerItem = gridView.getChildAt(j);
+                if (pickerItem.getAlpha() > 0) {
+                    alphaNonZeroRowsCount++;
+                }
+                if (pickerItem.getAlpha() == 1) {
+                    alpha1RowsCount++;
+                }
+            }
+            if (i == activeColumn) {
+                assertThat("The active column "  + i + " should have only one row with an alpha of "
+                                + "1", alpha1RowsCount, is(1));
+                assertTrue("The active column "  + i + " should have more than one view with alpha "
+                        + "greater than 1", alphaNonZeroRowsCount > 1);
+            } else {
+                assertThat("The inactive column " + i + " should have only one row with an alpha of"
+                        + " 1", alpha1RowsCount, is(1));
+                assertThat("The inactive column " + i + " should have only one row with a non-zero"
+                        + " alpha", alphaNonZeroRowsCount, is(1));
+            }
+        }
+    }
+
     private void sendKeys(int ...keys) {
         for (int i = 0; i < keys.length; i++) {
             InstrumentationRegistry.getInstrumentation().sendKeyDownUpSync(keys[i]);
diff --git a/v7/mediarouter/res/drawable-hdpi/ic_media_stop_dark.png b/v7/mediarouter/res/drawable-hdpi/ic_media_stop_dark.png
new file mode 100644
index 0000000..801d341
--- /dev/null
+++ b/v7/mediarouter/res/drawable-hdpi/ic_media_stop_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-hdpi/ic_media_stop_light.png b/v7/mediarouter/res/drawable-hdpi/ic_media_stop_light.png
new file mode 100644
index 0000000..9d6b65d
--- /dev/null
+++ b/v7/mediarouter/res/drawable-hdpi/ic_media_stop_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-mdpi/ic_media_stop_dark.png b/v7/mediarouter/res/drawable-mdpi/ic_media_stop_dark.png
new file mode 100644
index 0000000..3ad2c9c
--- /dev/null
+++ b/v7/mediarouter/res/drawable-mdpi/ic_media_stop_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-mdpi/ic_media_stop_light.png b/v7/mediarouter/res/drawable-mdpi/ic_media_stop_light.png
new file mode 100644
index 0000000..b002ab7
--- /dev/null
+++ b/v7/mediarouter/res/drawable-mdpi/ic_media_stop_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xhdpi/ic_media_stop_dark.png b/v7/mediarouter/res/drawable-xhdpi/ic_media_stop_dark.png
new file mode 100644
index 0000000..5239336
--- /dev/null
+++ b/v7/mediarouter/res/drawable-xhdpi/ic_media_stop_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xhdpi/ic_media_stop_light.png b/v7/mediarouter/res/drawable-xhdpi/ic_media_stop_light.png
new file mode 100644
index 0000000..5bc5a6c
--- /dev/null
+++ b/v7/mediarouter/res/drawable-xhdpi/ic_media_stop_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xxhdpi/ic_media_stop_dark.png b/v7/mediarouter/res/drawable-xxhdpi/ic_media_stop_dark.png
new file mode 100644
index 0000000..035ca18
--- /dev/null
+++ b/v7/mediarouter/res/drawable-xxhdpi/ic_media_stop_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xxhdpi/ic_media_stop_light.png b/v7/mediarouter/res/drawable-xxhdpi/ic_media_stop_light.png
new file mode 100644
index 0000000..eac183d
--- /dev/null
+++ b/v7/mediarouter/res/drawable-xxhdpi/ic_media_stop_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable/mr_media_stop_dark.xml b/v7/mediarouter/res/drawable/mr_media_stop_dark.xml
new file mode 100644
index 0000000..9757552
--- /dev/null
+++ b/v7/mediarouter/res/drawable/mr_media_stop_dark.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/ic_media_stop_dark" />
+</selector>
diff --git a/v7/mediarouter/res/drawable/mr_media_stop_light.xml b/v7/mediarouter/res/drawable/mr_media_stop_light.xml
new file mode 100644
index 0000000..c7717c7
--- /dev/null
+++ b/v7/mediarouter/res/drawable/mr_media_stop_light.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item>
+        <bitmap
+            android:src="@drawable/ic_media_stop_light"
+            android:alpha="0.87" />
+    </item>
+</selector>
diff --git a/v7/mediarouter/res/layout/mr_playback_control.xml b/v7/mediarouter/res/layout/mr_playback_control.xml
index b441254..9d788f6 100644
--- a/v7/mediarouter/res/layout/mr_playback_control.xml
+++ b/v7/mediarouter/res/layout/mr_playback_control.xml
@@ -20,7 +20,7 @@
                 android:orientation="horizontal"
                 android:paddingLeft="24dp"
                 android:paddingRight="12dp" >
-    <ImageButton android:id="@+id/mr_control_play_pause"
+    <ImageButton android:id="@+id/mr_control_playback_ctrl"
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:layout_marginLeft="12dp"
@@ -33,7 +33,7 @@
                   android:orientation="vertical"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
-                  android:layout_toLeftOf="@id/mr_control_play_pause"
+                  android:layout_toLeftOf="@id/mr_control_playback_ctrl"
                   android:layout_alignParentLeft="true"
                   android:layout_centerVertical="true">
         <TextView android:id="@+id/mr_control_title"
diff --git a/v7/mediarouter/res/values-af/strings.xml b/v7/mediarouter/res/values-af/strings.xml
index 444ffc2..9d311a9 100644
--- a/v7/mediarouter/res/values-af/strings.xml
+++ b/v7/mediarouter/res/values-af/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Saai uit na"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Vind tans toestelle"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Ontkoppel"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Hou op uitsaai"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Hou op uitsaai"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Maak toe"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Speel"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Laat wag"</string>
diff --git a/v7/mediarouter/res/values-am/strings.xml b/v7/mediarouter/res/values-am/strings.xml
index 96a2c09..ef7f3be 100644
--- a/v7/mediarouter/res/values-am/strings.xml
+++ b/v7/mediarouter/res/values-am/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Cast አድርግ ወደ"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"መሣሪያዎችን በማግኘት ላይ"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"ግንኙነት አቋርጥ"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Cast ማድረግ አቁም"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Cast ማድረግ አቁም"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"ዝጋ"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"አጫውት"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"ለአፍታ አቁም"</string>
diff --git a/v7/mediarouter/res/values-ar/strings.xml b/v7/mediarouter/res/values-ar/strings.xml
index 3caf4b6..897460c 100644
--- a/v7/mediarouter/res/values-ar/strings.xml
+++ b/v7/mediarouter/res/values-ar/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"إرسال إلى"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"جارٍ البحث عن أجهزة"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"قطع الاتصال"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"إيقاف الإرسال"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"إيقاف الإرسال"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"إغلاق"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"تشغيل"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"إيقاف مؤقت"</string>
diff --git a/v7/mediarouter/res/values-az/strings.xml b/v7/mediarouter/res/values-az/strings.xml
index 31574c3..a7cc571 100644
--- a/v7/mediarouter/res/values-az/strings.xml
+++ b/v7/mediarouter/res/values-az/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Bura yayımlayın"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Cihazlar axtarılır"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Bağlantını kəsin"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Yayımı dayandırın"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Yayımı dayandırın"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Qapadın"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Oynadın"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Durdurun"</string>
diff --git a/v7/mediarouter/res/values-b+sr+Latn/strings.xml b/v7/mediarouter/res/values-b+sr+Latn/strings.xml
index 4bc9baa..3aeaa7e 100644
--- a/v7/mediarouter/res/values-b+sr+Latn/strings.xml
+++ b/v7/mediarouter/res/values-b+sr+Latn/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Prebacuj na"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Pronalaženje uređaja"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Prekini vezu"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Zaustavi prebacivanje"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Zaustavi prebacivanje"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Zatvori"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Pusti"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Pauziraj"</string>
diff --git a/v7/mediarouter/res/values-be/strings.xml b/v7/mediarouter/res/values-be/strings.xml
index 75c24d5..93ccc1a 100644
--- a/v7/mediarouter/res/values-be/strings.xml
+++ b/v7/mediarouter/res/values-be/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Трансляваць на"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Пошук прылад"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Адлучыць"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Спыніць трансляцыю"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Спыніць трансляцыю"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Закрыць"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Прайграць"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Прыпыніць"</string>
diff --git a/v7/mediarouter/res/values-bg/strings.xml b/v7/mediarouter/res/values-bg/strings.xml
index d756d6c..ef4db0a 100644
--- a/v7/mediarouter/res/values-bg/strings.xml
+++ b/v7/mediarouter/res/values-bg/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Предаване към"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Търсят се устройства"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Прекратяване на връзката"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Спиране на предаването"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Спиране на предаването"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Затваряне"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Пускане"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Поставяне на пауза"</string>
diff --git a/v7/mediarouter/res/values-bn/strings.xml b/v7/mediarouter/res/values-bn/strings.xml
index b94b9af..d542100 100644
--- a/v7/mediarouter/res/values-bn/strings.xml
+++ b/v7/mediarouter/res/values-bn/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"এতে কাস্ট করুন"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"ডিভাইসগুলিকে খোঁজা হচ্ছে"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"সংযোগ বিচ্ছিন্ন করুন"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"কাস্ট করা বন্ধ করুন"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"কাস্ট করা বন্ধ করুন"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"বন্ধ করুন"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"চালান"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"বিরাম দিন"</string>
diff --git a/v7/mediarouter/res/values-bs/strings.xml b/v7/mediarouter/res/values-bs/strings.xml
index df4e3ef..cd8e586 100644
--- a/v7/mediarouter/res/values-bs/strings.xml
+++ b/v7/mediarouter/res/values-bs/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Prebacujte na"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Traženje uređaja"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Prekini vezu"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Zaustavi prebacivanje"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Zaustavi prebacivanje"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Zatvori"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Reproduciraj"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Pauziraj"</string>
diff --git a/v7/mediarouter/res/values-ca/strings.xml b/v7/mediarouter/res/values-ca/strings.xml
index 400d424..875290f 100644
--- a/v7/mediarouter/res/values-ca/strings.xml
+++ b/v7/mediarouter/res/values-ca/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Emet a"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"S\'estan cercant dispositius"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Desconnecta"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Atura l\'emissió"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Atura l\'emissió"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Tanca"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Reprodueix"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Posa en pausa"</string>
diff --git a/v7/mediarouter/res/values-cs/strings.xml b/v7/mediarouter/res/values-cs/strings.xml
index 5a29bac..532612a 100644
--- a/v7/mediarouter/res/values-cs/strings.xml
+++ b/v7/mediarouter/res/values-cs/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Odesílat do"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Hledání zařízení"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Odpojit"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Zastavit odesílání"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Zastavit odesílání"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Zavřít"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Přehrát"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Pozastavit"</string>
diff --git a/v7/mediarouter/res/values-da/strings.xml b/v7/mediarouter/res/values-da/strings.xml
index f33a4ee..55864a0 100644
--- a/v7/mediarouter/res/values-da/strings.xml
+++ b/v7/mediarouter/res/values-da/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Cast til"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Finder enheder"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Afbryd"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Stop med at caste"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Stop med at caste"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Luk"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Afspil"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Sæt på pause"</string>
diff --git a/v7/mediarouter/res/values-de/strings.xml b/v7/mediarouter/res/values-de/strings.xml
index 13686aa..50025de 100644
--- a/v7/mediarouter/res/values-de/strings.xml
+++ b/v7/mediarouter/res/values-de/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Streamen auf"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Geräte werden gesucht."</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Verbindung trennen"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Streaming stoppen"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Streaming stoppen"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Schließen"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Wiedergeben"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Pausieren"</string>
diff --git a/v7/mediarouter/res/values-el/strings.xml b/v7/mediarouter/res/values-el/strings.xml
index 3f45621..fd415cc 100644
--- a/v7/mediarouter/res/values-el/strings.xml
+++ b/v7/mediarouter/res/values-el/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Μετάδοση σε"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Εύρεση συσκευών"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Αποσύνδεση"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Διακοπή μετάδοσης"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Διακοπή μετάδοσης"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Κλείσιμο"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Αναπαραγωγή"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Παύση"</string>
diff --git a/v7/mediarouter/res/values-en-rAU/strings.xml b/v7/mediarouter/res/values-en-rAU/strings.xml
index 9201c1f..7ce2f28 100644
--- a/v7/mediarouter/res/values-en-rAU/strings.xml
+++ b/v7/mediarouter/res/values-en-rAU/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Cast to"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Finding devices"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Disconnect"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Stop casting"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Stop casting"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Close"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Play"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Pause"</string>
diff --git a/v7/mediarouter/res/values-en-rGB/strings.xml b/v7/mediarouter/res/values-en-rGB/strings.xml
index 9201c1f..7ce2f28 100644
--- a/v7/mediarouter/res/values-en-rGB/strings.xml
+++ b/v7/mediarouter/res/values-en-rGB/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Cast to"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Finding devices"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Disconnect"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Stop casting"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Stop casting"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Close"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Play"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Pause"</string>
diff --git a/v7/mediarouter/res/values-en-rIN/strings.xml b/v7/mediarouter/res/values-en-rIN/strings.xml
index 9201c1f..7ce2f28 100644
--- a/v7/mediarouter/res/values-en-rIN/strings.xml
+++ b/v7/mediarouter/res/values-en-rIN/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Cast to"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Finding devices"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Disconnect"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Stop casting"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Stop casting"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Close"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Play"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Pause"</string>
diff --git a/v7/mediarouter/res/values-es-rUS/strings.xml b/v7/mediarouter/res/values-es-rUS/strings.xml
index 90aa823..9b411dd 100644
--- a/v7/mediarouter/res/values-es-rUS/strings.xml
+++ b/v7/mediarouter/res/values-es-rUS/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Transmitir a"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Buscando dispositivos"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Desconectar"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Detener la transmisión"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Detener la transmisión"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Cerrar"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Reproducir"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Pausar"</string>
diff --git a/v7/mediarouter/res/values-es/strings.xml b/v7/mediarouter/res/values-es/strings.xml
index 52a886f..057d3d2 100644
--- a/v7/mediarouter/res/values-es/strings.xml
+++ b/v7/mediarouter/res/values-es/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Enviar a"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Buscando dispositivos"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Desconectar"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Dejar de enviar contenido"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Dejar de enviar contenido"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Cerrar"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Reproducir"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Pausa"</string>
diff --git a/v7/mediarouter/res/values-et/strings.xml b/v7/mediarouter/res/values-et/strings.xml
index ce1847a..8fa0e94 100644
--- a/v7/mediarouter/res/values-et/strings.xml
+++ b/v7/mediarouter/res/values-et/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Ülekandmine seadmesse"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Seadmete otsimine"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Katkesta ühendus"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Peata ülekanne"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Peata ülekanne"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Sulgemine"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Esitamine"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Peatamine"</string>
diff --git a/v7/mediarouter/res/values-eu/strings.xml b/v7/mediarouter/res/values-eu/strings.xml
index c03d73b..d8efeba 100644
--- a/v7/mediarouter/res/values-eu/strings.xml
+++ b/v7/mediarouter/res/values-eu/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Igorri hona"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Gailuak bilatzen"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Deskonektatu"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Utzi igortzeari"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Utzi igortzeari"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Itxi"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Erreproduzitu"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Pausatu"</string>
diff --git a/v7/mediarouter/res/values-fa/strings.xml b/v7/mediarouter/res/values-fa/strings.xml
index 7cc9fbc..8d965d1 100644
--- a/v7/mediarouter/res/values-fa/strings.xml
+++ b/v7/mediarouter/res/values-fa/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"ارسال محتوا به"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"پیدا کردن دستگاه‌ها"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"قطع ارتباط"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"توقف ارسال محتوا"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"توقف ارسال محتوا"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"بستن"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"پخش"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"مکث"</string>
diff --git a/v7/mediarouter/res/values-fi/strings.xml b/v7/mediarouter/res/values-fi/strings.xml
index 2465802..41727ef 100644
--- a/v7/mediarouter/res/values-fi/strings.xml
+++ b/v7/mediarouter/res/values-fi/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Suoratoiston kohde"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Etsitään laitteita"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Katkaise yhteys"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Lopeta suoratoisto"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Lopeta suoratoisto"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Sulje"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Toista"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Keskeytä"</string>
diff --git a/v7/mediarouter/res/values-fr-rCA/strings.xml b/v7/mediarouter/res/values-fr-rCA/strings.xml
index fd1ea8c..9f489f2 100644
--- a/v7/mediarouter/res/values-fr-rCA/strings.xml
+++ b/v7/mediarouter/res/values-fr-rCA/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Diffuser sur"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Recherche d\'appareils"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Se déconnecter"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Arrêter la diffusion"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Arrêter la diffusion"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Fermer"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Lire"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Interrompre"</string>
diff --git a/v7/mediarouter/res/values-fr/strings.xml b/v7/mediarouter/res/values-fr/strings.xml
index 8c96485..86f70bb 100644
--- a/v7/mediarouter/res/values-fr/strings.xml
+++ b/v7/mediarouter/res/values-fr/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Caster sur"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Recherche d\'appareils en cours…"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Déconnecter"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Arrêter de diffuser"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Arrêter de diffuser"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Fermer"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Lecture"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Pause"</string>
diff --git a/v7/mediarouter/res/values-gl/strings.xml b/v7/mediarouter/res/values-gl/strings.xml
index d6d1888..7d250bf 100644
--- a/v7/mediarouter/res/values-gl/strings.xml
+++ b/v7/mediarouter/res/values-gl/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Emitir en"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Buscando dispositivos"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Desconectar"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Deter emisión"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Deter emisión"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Pechar"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Reproduce"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Pausa"</string>
diff --git a/v7/mediarouter/res/values-gu/strings.xml b/v7/mediarouter/res/values-gu/strings.xml
index eb7a9b8..6c2237e 100644
--- a/v7/mediarouter/res/values-gu/strings.xml
+++ b/v7/mediarouter/res/values-gu/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"આના પર કાસ્ટ કરો"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"ઉપકરણો શોધી રહ્યાં છીએ"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"ડિસ્કનેક્ટ કરો"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"કાસ્ટ કરવાનું રોકો"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"કાસ્ટ કરવાનું રોકો"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"બંધ કરો"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"ચલાવો"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"થોભાવો"</string>
diff --git a/v7/mediarouter/res/values-hi/strings.xml b/v7/mediarouter/res/values-hi/strings.xml
index 5b01c7c..04a8f53 100644
--- a/v7/mediarouter/res/values-hi/strings.xml
+++ b/v7/mediarouter/res/values-hi/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"इस पर कास्‍ट करें"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"डिवाइस ढूंढ रहा है"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"डिसकनेक्ट करें"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"कास्ट करना बंद करें"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"कास्ट करना बंद करें"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"बंद करें"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"चलाएं"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"रोकें"</string>
diff --git a/v7/mediarouter/res/values-hr/strings.xml b/v7/mediarouter/res/values-hr/strings.xml
index f50d748..83b2a7a 100644
--- a/v7/mediarouter/res/values-hr/strings.xml
+++ b/v7/mediarouter/res/values-hr/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Emitiranje na"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Traženje uređaja"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Prekini vezu"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Zaustavi emitiranje"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Zaustavi emitiranje"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Zatvaranje"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Reprodukcija"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Pauziranje"</string>
diff --git a/v7/mediarouter/res/values-hu/strings.xml b/v7/mediarouter/res/values-hu/strings.xml
index 6420985..9d4b770 100644
--- a/v7/mediarouter/res/values-hu/strings.xml
+++ b/v7/mediarouter/res/values-hu/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Átküldés ide"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Eszközök keresése"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Leválasztás"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Átküldés leállítása"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Átküldés leállítása"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Bezárás"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Lejátszás"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Szüneteltetés"</string>
diff --git a/v7/mediarouter/res/values-hy/strings.xml b/v7/mediarouter/res/values-hy/strings.xml
index 6e46af8..f1221d1 100644
--- a/v7/mediarouter/res/values-hy/strings.xml
+++ b/v7/mediarouter/res/values-hy/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Ընտրեք սարքը"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Սարքերի որոնում"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Անջատել"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Դադարեցնել հեռարձակումը"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Դադարեցնել հեռարձակումը"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Փակել"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Նվագարկել"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Դադար"</string>
diff --git a/v7/mediarouter/res/values-in/strings.xml b/v7/mediarouter/res/values-in/strings.xml
index 43e0c62..fbe906a 100644
--- a/v7/mediarouter/res/values-in/strings.xml
+++ b/v7/mediarouter/res/values-in/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Transmisikan ke"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Mencari perangkat"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Putuskan sambungan"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Hentikan transmisi"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Hentikan transmisi"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Tutup"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Putar"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Jeda"</string>
diff --git a/v7/mediarouter/res/values-is/strings.xml b/v7/mediarouter/res/values-is/strings.xml
index 53de253..cf5308e 100644
--- a/v7/mediarouter/res/values-is/strings.xml
+++ b/v7/mediarouter/res/values-is/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Senda út í"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Leitað að tækjum"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Aftengjast"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Stöðva útsendingu"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Stöðva útsendingu"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Loka"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Spila"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Hlé"</string>
diff --git a/v7/mediarouter/res/values-it/strings.xml b/v7/mediarouter/res/values-it/strings.xml
index df6bbfe..b8f12a5 100644
--- a/v7/mediarouter/res/values-it/strings.xml
+++ b/v7/mediarouter/res/values-it/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Trasmetti a"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Ricerca di dispositivi in corso"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Scollega"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Interrompi trasmissione"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Interrompi trasmissione"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Chiudi"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Riproduci"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Pausa"</string>
diff --git a/v7/mediarouter/res/values-iw/strings.xml b/v7/mediarouter/res/values-iw/strings.xml
index be705a6..89a136a 100644
--- a/v7/mediarouter/res/values-iw/strings.xml
+++ b/v7/mediarouter/res/values-iw/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"העבר אל"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"מחפש מכשירים"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"נתק"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"עצור העברה"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"עצור העברה"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"סגור"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"הפעל"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"השהה"</string>
diff --git a/v7/mediarouter/res/values-ja/strings.xml b/v7/mediarouter/res/values-ja/strings.xml
index 75d75d6..6b731d2 100644
--- a/v7/mediarouter/res/values-ja/strings.xml
+++ b/v7/mediarouter/res/values-ja/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"キャストするデバイス"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"端末を検索しています"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"接続を解除"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"キャストを停止"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"キャストを停止"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"閉じる"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"再生"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"一時停止"</string>
diff --git a/v7/mediarouter/res/values-ka/strings.xml b/v7/mediarouter/res/values-ka/strings.xml
index 3bcc513..584203f 100644
--- a/v7/mediarouter/res/values-ka/strings.xml
+++ b/v7/mediarouter/res/values-ka/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"ტრანსლირებული"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"მიმდინარეობს მოწყობილობების მოძიება"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"კავშირის გაწყვეტა"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"ტრანსლირების შეჩერება"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"ტრანსლირების შეჩერება"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"დახურვა"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"დაკვრა"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"პაუზა"</string>
diff --git a/v7/mediarouter/res/values-kk/strings.xml b/v7/mediarouter/res/values-kk/strings.xml
index 43e75b7..185fbf9 100644
--- a/v7/mediarouter/res/values-kk/strings.xml
+++ b/v7/mediarouter/res/values-kk/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Келесіге трансляциялау"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Құрылғыларды табу"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Ажырату"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Трансляциялауды тоқтату"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Трансляциялауды тоқтату"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Жабу"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Ойнату"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Кідірту"</string>
diff --git a/v7/mediarouter/res/values-km/strings.xml b/v7/mediarouter/res/values-km/strings.xml
index 44d88f4..7a92a77 100644
--- a/v7/mediarouter/res/values-km/strings.xml
+++ b/v7/mediarouter/res/values-km/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"ខាសទៅ"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"ស្វែងរកឧបករណ៍"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"ផ្ដាច់"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"បញ្ឈប់ការខាស"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"បញ្ឈប់ការខាស"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"បិទ"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"ចាក់"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"ផ្អាក"</string>
diff --git a/v7/mediarouter/res/values-kn/strings.xml b/v7/mediarouter/res/values-kn/strings.xml
index 193d449..a493757 100644
--- a/v7/mediarouter/res/values-kn/strings.xml
+++ b/v7/mediarouter/res/values-kn/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"ಇದಕ್ಕೆ ಬಿತ್ತರಿಸಿ"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"ಸಾಧನಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸು"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"ಬಿತ್ತರಿಸುವಿಕೆ ನಿಲ್ಲಿಸು"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"ಬಿತ್ತರಿಸುವಿಕೆ ನಿಲ್ಲಿಸು"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"ಮುಚ್ಚು"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"ಪ್ಲೇ ಮಾಡಿ"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"ವಿರಾಮ"</string>
diff --git a/v7/mediarouter/res/values-ko/strings.xml b/v7/mediarouter/res/values-ko/strings.xml
index 242560a..8630f4f 100644
--- a/v7/mediarouter/res/values-ko/strings.xml
+++ b/v7/mediarouter/res/values-ko/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"전송할 기기"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"기기를 찾는 중"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"연결 해제"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"전송 중지"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"전송 중지"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"닫기"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"재생"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"일시중지"</string>
diff --git a/v7/mediarouter/res/values-ky/strings.xml b/v7/mediarouter/res/values-ky/strings.xml
index 0898ade..82f64be 100644
--- a/v7/mediarouter/res/values-ky/strings.xml
+++ b/v7/mediarouter/res/values-ky/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Төмөнкүгө чыгаруу"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Түзмөктөр изделүүдө"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Ажыратуу"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Тышк экранга чыгарну токтотуу"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Тышк экранга чыгарну токтотуу"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Жабуу"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Ойнотуу"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Тындыруу"</string>
diff --git a/v7/mediarouter/res/values-lo/strings.xml b/v7/mediarouter/res/values-lo/strings.xml
index 65b3472..8771268 100644
--- a/v7/mediarouter/res/values-lo/strings.xml
+++ b/v7/mediarouter/res/values-lo/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"ຄາ​ສ​ທ໌​ຫາ"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"ກຳລັງ​ຊອກ​ຫາ​ອຸ​ປະ​ກອນ"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"ຕັດການເຊື່ອມຕໍ່"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"ຢຸດການຄາ​ສ​ທ໌"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"ຢຸດການຄາ​ສ​ທ໌"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"ປິດ"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"ຫຼິ້ນ"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"ຢຸດຊົ່ວຄາວ"</string>
diff --git a/v7/mediarouter/res/values-lt/strings.xml b/v7/mediarouter/res/values-lt/strings.xml
index 35931cf..45398f0 100644
--- a/v7/mediarouter/res/values-lt/strings.xml
+++ b/v7/mediarouter/res/values-lt/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Perduoti į"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Randami įrenginiai"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Atjungti"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Sustabdyti perdavimą"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Sustabdyti perdavimą"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Uždaryti"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Leisti"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Pristabdyti"</string>
diff --git a/v7/mediarouter/res/values-lv/strings.xml b/v7/mediarouter/res/values-lv/strings.xml
index c146174..e01705e 100644
--- a/v7/mediarouter/res/values-lv/strings.xml
+++ b/v7/mediarouter/res/values-lv/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Apraidīšana uz ierīci"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Notiek ierīču meklēšana"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Atvienot"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Pārtraukt apraidi"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Pārtraukt apraidi"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Aizvērt"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Atskaņot"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Apturēt"</string>
diff --git a/v7/mediarouter/res/values-mk/strings.xml b/v7/mediarouter/res/values-mk/strings.xml
index 6fd428f..205467e 100644
--- a/v7/mediarouter/res/values-mk/strings.xml
+++ b/v7/mediarouter/res/values-mk/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Емитувај на"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Наоѓање уреди"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Исклучи"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Запри го емитувањето"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Запри го емитувањето"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Затвори"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Репродуцирај"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Паузирај"</string>
diff --git a/v7/mediarouter/res/values-ml/strings.xml b/v7/mediarouter/res/values-ml/strings.xml
index 63a37f8..00fc9dc 100644
--- a/v7/mediarouter/res/values-ml/strings.xml
+++ b/v7/mediarouter/res/values-ml/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"ഇതിലേക്ക് കാസ്റ്റുചെയ്യുക"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"ഉപകരണങ്ങൾ കണ്ടെത്തുന്നു"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"വിച്ഛേദിക്കുക"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"കാസ്റ്റുചെയ്യൽ നിർത്തുക"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"കാസ്റ്റുചെയ്യൽ നിർത്തുക"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"അടയ്‌ക്കുക"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"പ്ലേ ചെയ്യുക"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"തൽക്കാലം നിർത്തൂ"</string>
diff --git a/v7/mediarouter/res/values-mn/strings.xml b/v7/mediarouter/res/values-mn/strings.xml
index 1197bfe..cccf05e 100644
--- a/v7/mediarouter/res/values-mn/strings.xml
+++ b/v7/mediarouter/res/values-mn/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Дамжуулах"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Төхөөрөмж хайж байна"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Салгах"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Дамжуулахыг зогсоох"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Дамжуулахыг зогсоох"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Хаах"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Тоглуулах"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Түр зогсоох"</string>
diff --git a/v7/mediarouter/res/values-mr/strings.xml b/v7/mediarouter/res/values-mr/strings.xml
index 40d7d66..37374b4 100644
--- a/v7/mediarouter/res/values-mr/strings.xml
+++ b/v7/mediarouter/res/values-mr/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"यावर कास्ट करा"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"डिव्हाइसेस शोधत आहे"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"डिस्‍कनेक्‍ट करा"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"कास्ट करणे थांबवा"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"कास्ट करणे थांबवा"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"बंद करा"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"प्ले करा"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"विराम"</string>
diff --git a/v7/mediarouter/res/values-ms/strings.xml b/v7/mediarouter/res/values-ms/strings.xml
index cc32b96..6474884 100644
--- a/v7/mediarouter/res/values-ms/strings.xml
+++ b/v7/mediarouter/res/values-ms/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Hantar ke"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Mencari peranti"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Putuskan sambungan"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Berhenti menghantar"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Berhenti menghantar"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Tutup"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Main"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Jeda"</string>
diff --git a/v7/mediarouter/res/values-my/strings.xml b/v7/mediarouter/res/values-my/strings.xml
index e31cc92..836d137 100644
--- a/v7/mediarouter/res/values-my/strings.xml
+++ b/v7/mediarouter/res/values-my/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"သို့ ကာစ်တ်လုပ်ရန်"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"စက်ပစ္စည်းများ ရှာဖွေခြင်း"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"ဆက်သွယ်မှု ဖြတ်ရန်"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"ကာစ်တ်လုပ်ခြင်း ရပ်တန့်ရန်"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"ကာစ်တ်လုပ်ခြင်း ရပ်တန့်ရန်"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"ပိတ်ရန်"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"ဖွင့်ရန်"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"ခဏရပ်ရန်"</string>
diff --git a/v7/mediarouter/res/values-nb/strings.xml b/v7/mediarouter/res/values-nb/strings.xml
index 97ca73c..172d9d4 100644
--- a/v7/mediarouter/res/values-nb/strings.xml
+++ b/v7/mediarouter/res/values-nb/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Cast til"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Finner enheter"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Koble fra"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Stopp castingen"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Stopp castingen"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Lukk"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Spill av"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Sett på pause"</string>
diff --git a/v7/mediarouter/res/values-ne/strings.xml b/v7/mediarouter/res/values-ne/strings.xml
index 0e48b45..e9e4f03 100644
--- a/v7/mediarouter/res/values-ne/strings.xml
+++ b/v7/mediarouter/res/values-ne/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"यसमा Cast गर्नुहोस्"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"यन्त्रहरू पत्ता लगाउँदै"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"विच्छेद गर्नुहोस्"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"casting रोक्नुहोस्"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"casting रोक्नुहोस्"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"बन्द गर्नुहोस्"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"बजाउनुहोस्"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"रोक्नुहोस्"</string>
diff --git a/v7/mediarouter/res/values-nl/strings.xml b/v7/mediarouter/res/values-nl/strings.xml
index 5c899fd..21364e7 100644
--- a/v7/mediarouter/res/values-nl/strings.xml
+++ b/v7/mediarouter/res/values-nl/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Casten naar"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Apparaten zoeken"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Loskoppelen"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Casten stoppen"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Casten stoppen"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Sluiten"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Afspelen"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Onderbreken"</string>
diff --git a/v7/mediarouter/res/values-pa/strings.xml b/v7/mediarouter/res/values-pa/strings.xml
index c207246..906903f 100644
--- a/v7/mediarouter/res/values-pa/strings.xml
+++ b/v7/mediarouter/res/values-pa/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"ਇਸ ਨਾਲ ਕਾਸਟ ਕਰੋ"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"ਡਿਵਾਈਸਾਂ ਲੱਭ ਰਿਹਾ ਹੈ"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"ਡਿਸਕਨੈਕਟ ਕਰੋ"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"ਕਾਸਟ ਕਰਨਾ ਰੋਕੋ"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"ਕਾਸਟ ਕਰਨਾ ਰੋਕੋ"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"ਬੰਦ ਕਰੋ"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"ਪਲੇ ਕਰੋ"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"ਰੋਕੋ"</string>
diff --git a/v7/mediarouter/res/values-pl/strings.xml b/v7/mediarouter/res/values-pl/strings.xml
index 0320550..db0934d 100644
--- a/v7/mediarouter/res/values-pl/strings.xml
+++ b/v7/mediarouter/res/values-pl/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Przesyłaj na"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Znajdowanie urządzeń"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Odłącz"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Zatrzymaj przesyłanie"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Zatrzymaj przesyłanie"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Zamknij"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Odtwórz"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Wstrzymaj"</string>
diff --git a/v7/mediarouter/res/values-pt-rBR/strings.xml b/v7/mediarouter/res/values-pt-rBR/strings.xml
index 2fd84b1..b424082 100644
--- a/v7/mediarouter/res/values-pt-rBR/strings.xml
+++ b/v7/mediarouter/res/values-pt-rBR/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Transmitir para"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Localizando dispositivos"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Desconectar"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Interromper transmissão"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Interromper transmissão"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Fechar"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Reproduzir"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Pausar"</string>
diff --git a/v7/mediarouter/res/values-pt-rPT/strings.xml b/v7/mediarouter/res/values-pt-rPT/strings.xml
index b62f363..c6c52f9 100644
--- a/v7/mediarouter/res/values-pt-rPT/strings.xml
+++ b/v7/mediarouter/res/values-pt-rPT/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Transmitir para"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"A localizar dispositivos"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Desassociar"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Interromper a transmissão"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Interromper a transmissão"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Fechar"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Reproduzir"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Interromper"</string>
diff --git a/v7/mediarouter/res/values-pt/strings.xml b/v7/mediarouter/res/values-pt/strings.xml
index 2fd84b1..b424082 100644
--- a/v7/mediarouter/res/values-pt/strings.xml
+++ b/v7/mediarouter/res/values-pt/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Transmitir para"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Localizando dispositivos"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Desconectar"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Interromper transmissão"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Interromper transmissão"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Fechar"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Reproduzir"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Pausar"</string>
diff --git a/v7/mediarouter/res/values-ro/strings.xml b/v7/mediarouter/res/values-ro/strings.xml
index 769a0ac..ab2fd61 100644
--- a/v7/mediarouter/res/values-ro/strings.xml
+++ b/v7/mediarouter/res/values-ro/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Proiectați pe"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Se caută dispozitive"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Deconectați-vă"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Opriți proiecția"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Opriți proiecția"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Închideți"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Redați"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Întrerupeți"</string>
diff --git a/v7/mediarouter/res/values-ru/strings.xml b/v7/mediarouter/res/values-ru/strings.xml
index 9bd2170..768f300 100644
--- a/v7/mediarouter/res/values-ru/strings.xml
+++ b/v7/mediarouter/res/values-ru/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Выберите устройство"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Поиск устройств…"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Отключить"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Остановить трансляцию"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Остановить трансляцию"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Закрыть"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Воспроизвести"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Приостановить"</string>
diff --git a/v7/mediarouter/res/values-si/strings.xml b/v7/mediarouter/res/values-si/strings.xml
index baeac3e..e26a087 100644
--- a/v7/mediarouter/res/values-si/strings.xml
+++ b/v7/mediarouter/res/values-si/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"විකාශය"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"උපාංග සෙවීම"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"විසන්ධි කරන්න"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"විකාශ කිරීම නවත්වන්න"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"විකාශ කිරීම නවත්වන්න"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"වසන්න"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"ධාවනය කරන්න"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"විරාම ගන්වන්න"</string>
diff --git a/v7/mediarouter/res/values-sk/strings.xml b/v7/mediarouter/res/values-sk/strings.xml
index 4a0f4bf..92c7307 100644
--- a/v7/mediarouter/res/values-sk/strings.xml
+++ b/v7/mediarouter/res/values-sk/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Prenos do"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Vyhľadávanie zariadení"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Odpojiť"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Zastaviť prenos"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Zastaviť prenos"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Zavrieť"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Prehrať"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Pozastaviť"</string>
diff --git a/v7/mediarouter/res/values-sl/strings.xml b/v7/mediarouter/res/values-sl/strings.xml
index 4ca2bdc..ba5609e 100644
--- a/v7/mediarouter/res/values-sl/strings.xml
+++ b/v7/mediarouter/res/values-sl/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Predvajanje prek:"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Iskanje naprav"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Prekini povezavo"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Ustavi predvajanje"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Ustavi predvajanje"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Zapri"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Predvajanje"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Zaustavi"</string>
diff --git a/v7/mediarouter/res/values-sq/strings.xml b/v7/mediarouter/res/values-sq/strings.xml
index 45e3a34..5ebfbab 100644
--- a/v7/mediarouter/res/values-sq/strings.xml
+++ b/v7/mediarouter/res/values-sq/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Transmeto te"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Gjetja e pajisjeve"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Shkëpute"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Ndalo transmetimin"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Ndalo transmetimin"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Mbyll"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Luaj"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Pauzë"</string>
diff --git a/v7/mediarouter/res/values-sr/strings.xml b/v7/mediarouter/res/values-sr/strings.xml
index ef1b2b1..2b5e9fd 100644
--- a/v7/mediarouter/res/values-sr/strings.xml
+++ b/v7/mediarouter/res/values-sr/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Пребацуј на"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Проналажење уређаја"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Прекини везу"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Заустави пребацивање"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Заустави пребацивање"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Затвори"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Пусти"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Паузирај"</string>
diff --git a/v7/mediarouter/res/values-sv/strings.xml b/v7/mediarouter/res/values-sv/strings.xml
index 9597bf9..9be5f57 100644
--- a/v7/mediarouter/res/values-sv/strings.xml
+++ b/v7/mediarouter/res/values-sv/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Casta till"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Letar efter enheter"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Koppla från"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Sluta casta"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Sluta casta"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Stäng"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Spela upp"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Pausa"</string>
diff --git a/v7/mediarouter/res/values-sw/strings.xml b/v7/mediarouter/res/values-sw/strings.xml
index f7ae8f5..989f420 100644
--- a/v7/mediarouter/res/values-sw/strings.xml
+++ b/v7/mediarouter/res/values-sw/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Tuma kwenye"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Inatafuta vifaa"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Ondoa"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Acha kutuma"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Acha kutuma"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Funga"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Cheza"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Sitisha"</string>
diff --git a/v7/mediarouter/res/values-ta/strings.xml b/v7/mediarouter/res/values-ta/strings.xml
index 0ef3fc3..decdebd 100644
--- a/v7/mediarouter/res/values-ta/strings.xml
+++ b/v7/mediarouter/res/values-ta/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"இதில் திரையிடு"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"சாதனங்களைத் தேடுகிறது"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"தொடர்பைத் துண்டி"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"அனுப்புவதை நிறுத்து"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"அனுப்புவதை நிறுத்து"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"மூடும்"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"இயக்கும்"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"இடைநிறுத்தும்"</string>
diff --git a/v7/mediarouter/res/values-te/strings.xml b/v7/mediarouter/res/values-te/strings.xml
index c7ae34f..7412980 100644
--- a/v7/mediarouter/res/values-te/strings.xml
+++ b/v7/mediarouter/res/values-te/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"దీనికి ప్రసారం చేయండి"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"పరికరాలను కనుగొంటోంది"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"డిస్‌కనెక్ట్ చేయి"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"ప్రసారాన్ని ఆపివేయి"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"ప్రసారాన్ని ఆపివేయి"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"మూసివేస్తుంది"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"ప్లే చేస్తుంది"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"పాజ్ చేస్తుంది"</string>
diff --git a/v7/mediarouter/res/values-th/strings.xml b/v7/mediarouter/res/values-th/strings.xml
index 219374c..231aa2e 100644
--- a/v7/mediarouter/res/values-th/strings.xml
+++ b/v7/mediarouter/res/values-th/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"แคสต์ไปยัง"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"กำลังค้นหาอุปกรณ์"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"ยกเลิกการเชื่อมต่อ"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"หยุดการแคสต์"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"หยุดการแคสต์"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"ปิด"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"เล่น"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"หยุดชั่วคราว"</string>
diff --git a/v7/mediarouter/res/values-tl/strings.xml b/v7/mediarouter/res/values-tl/strings.xml
index e2bb7c7..c128aba 100644
--- a/v7/mediarouter/res/values-tl/strings.xml
+++ b/v7/mediarouter/res/values-tl/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"I-cast sa"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Naghahanap ng mga device"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Idiskonekta"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Itigil ang pagca-cast"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Itigil ang pagca-cast"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Isara"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"I-play"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"I-pause"</string>
diff --git a/v7/mediarouter/res/values-tr/strings.xml b/v7/mediarouter/res/values-tr/strings.xml
index 187682f..6bc7072 100644
--- a/v7/mediarouter/res/values-tr/strings.xml
+++ b/v7/mediarouter/res/values-tr/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Şuraya yayınla:"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Cihazlar bulunuyor"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Bağlantıyı kes"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Yayını durdur"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Yayını durdur"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Kapat"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Oynat"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Duraklat"</string>
diff --git a/v7/mediarouter/res/values-uk/strings.xml b/v7/mediarouter/res/values-uk/strings.xml
index 8c2a16a..1f9104e 100644
--- a/v7/mediarouter/res/values-uk/strings.xml
+++ b/v7/mediarouter/res/values-uk/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Транслювати на"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Пошук пристроїв"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Відключити"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Припинити трансляцію"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Припинити трансляцію"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Закрити"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Відтворити"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Призупинити"</string>
diff --git a/v7/mediarouter/res/values-ur/strings.xml b/v7/mediarouter/res/values-ur/strings.xml
index 053373f..667fddc 100644
--- a/v7/mediarouter/res/values-ur/strings.xml
+++ b/v7/mediarouter/res/values-ur/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"اس میں کاسٹ کریں"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"آلات تلاش ہو رہے ہیں"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"غیر منسلک کریں"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"کاسٹ کرنا بند کریں"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"کاسٹ کرنا بند کریں"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"بند کریں"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"چلائیں"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"موقوف کریں"</string>
diff --git a/v7/mediarouter/res/values-uz/strings.xml b/v7/mediarouter/res/values-uz/strings.xml
index 9d1e455..91b5e49 100644
--- a/v7/mediarouter/res/values-uz/strings.xml
+++ b/v7/mediarouter/res/values-uz/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Quyidagiga translatsiya qilish:"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Qurilmalarni topish"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Ulanishni uzish"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Translatsiyani to‘xtatish"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Translatsiyani to‘xtatish"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Yopish"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Boshlash"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"To‘xtatib turish"</string>
diff --git a/v7/mediarouter/res/values-vi/strings.xml b/v7/mediarouter/res/values-vi/strings.xml
index 488b9f0..44e7a6a 100644
--- a/v7/mediarouter/res/values-vi/strings.xml
+++ b/v7/mediarouter/res/values-vi/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Truyền tới"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Tìm thiết bị"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Ngắt kết nối"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Dừng truyền"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Dừng truyền"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Đóng"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Phát"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Tạm dừng"</string>
diff --git a/v7/mediarouter/res/values-zh-rCN/strings.xml b/v7/mediarouter/res/values-zh-rCN/strings.xml
index 30c7dcc..a8e8f92 100644
--- a/v7/mediarouter/res/values-zh-rCN/strings.xml
+++ b/v7/mediarouter/res/values-zh-rCN/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"投射到"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"正在查找设备"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"断开连接"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"停止投射"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"停止投射"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"关闭"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"播放"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"暂停"</string>
diff --git a/v7/mediarouter/res/values-zh-rHK/strings.xml b/v7/mediarouter/res/values-zh-rHK/strings.xml
index d17469b..0aebac0 100644
--- a/v7/mediarouter/res/values-zh-rHK/strings.xml
+++ b/v7/mediarouter/res/values-zh-rHK/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"投放至"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"正在尋找裝置"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"中斷連線"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"停止投放"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"停止投放"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"關閉"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"播放"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"暫停"</string>
diff --git a/v7/mediarouter/res/values-zh-rTW/strings.xml b/v7/mediarouter/res/values-zh-rTW/strings.xml
index 1a71c84..aa9c75b 100644
--- a/v7/mediarouter/res/values-zh-rTW/strings.xml
+++ b/v7/mediarouter/res/values-zh-rTW/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"投放到"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"正在尋找裝置"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"中斷連線"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"停止投放"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"停止投放"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"關閉"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"播放"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"暫停"</string>
diff --git a/v7/mediarouter/res/values-zu/strings.xml b/v7/mediarouter/res/values-zu/strings.xml
index 860aa09..db82ffa 100644
--- a/v7/mediarouter/res/values-zu/strings.xml
+++ b/v7/mediarouter/res/values-zu/strings.xml
@@ -25,7 +25,7 @@
     <string name="mr_chooser_title" msgid="414301941546135990">"Sakaza ku-"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Ithola amadivayisi"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Nqamula"</string>
-    <string name="mr_controller_stop" msgid="4570331844078181931">"Misa ukusakaza"</string>
+    <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Misa ukusakaza"</string>
     <string name="mr_controller_close_description" msgid="7333862312480583260">"Vala"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"Dlala"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"Misa isikhashana"</string>
diff --git a/v7/mediarouter/res/values/attrs.xml b/v7/mediarouter/res/values/attrs.xml
index cf6a7b5..68511c8 100644
--- a/v7/mediarouter/res/values/attrs.xml
+++ b/v7/mediarouter/res/values/attrs.xml
@@ -32,6 +32,7 @@
     <attr name="mediaRouteCloseDrawable" format="reference" />
     <attr name="mediaRoutePlayDrawable" format="reference" />
     <attr name="mediaRoutePauseDrawable" format="reference" />
+    <attr name="mediaRouteStopDrawable" format="reference" />
     <attr name="mediaRouteAudioTrackDrawable" format="reference" />
     <attr name="mediaRouteDefaultIconDrawable" format="reference" />
     <attr name="mediaRouteTvIconDrawable" format="reference" />
diff --git a/v7/mediarouter/res/values/strings.xml b/v7/mediarouter/res/values/strings.xml
index bff7176..630a482 100644
--- a/v7/mediarouter/res/values/strings.xml
+++ b/v7/mediarouter/res/values/strings.xml
@@ -47,7 +47,7 @@
     <string name="mr_controller_disconnect">Disconnect</string>
 
     <!-- Button to stop playback and disconnect from a media route. [CHAR LIMIT=30] -->
-    <string name="mr_controller_stop">Stop casting</string>
+    <string name="mr_controller_stop_casting">Stop casting</string>
 
     <!-- Content description for accessibility (not shown on the screen): dialog close button. [CHAR LIMIT=NONE] -->
     <string name="mr_controller_close_description">Close</string>
@@ -58,6 +58,9 @@
     <!-- Content description for accessibility (not shown on the screen): media pause button. [CHAR LIMIT=NONE] -->
     <string name="mr_controller_pause">Pause</string>
 
+    <!-- Content description for accessibility (not shown on the screen): media stop button. [CHAR LIMIT=NONE] -->
+    <string name="mr_controller_stop">Stop</string>
+
     <!-- Content description for accessibility (not shown on the screen): group expand button. Pressing button shows group members of a selected route group. [CHAR LIMIT=NONE] -->
     <string name="mr_controller_expand_group">Expand</string>
 
diff --git a/v7/mediarouter/res/values/themes.xml b/v7/mediarouter/res/values/themes.xml
index 1eb4bfd..8c6e97a 100644
--- a/v7/mediarouter/res/values/themes.xml
+++ b/v7/mediarouter/res/values/themes.xml
@@ -23,6 +23,7 @@
         <item name="mediaRouteCloseDrawable">@drawable/mr_dialog_close_dark</item>
         <item name="mediaRoutePlayDrawable">@drawable/mr_media_play_dark</item>
         <item name="mediaRoutePauseDrawable">@drawable/mr_media_pause_dark</item>
+        <item name="mediaRouteStopDrawable">@drawable/mr_media_stop_dark</item>
         <item name="mediaRouteAudioTrackDrawable">@drawable/mr_vol_type_audiotrack_dark</item>
         <item name="mediaRouteDefaultIconDrawable">@drawable/ic_mr_button_disconnected_dark</item>
         <item name="mediaRouteTvIconDrawable">@drawable/ic_vol_type_tv_dark</item>
@@ -43,6 +44,7 @@
         <item name="mediaRouteCloseDrawable">@drawable/mr_dialog_close_light</item>
         <item name="mediaRoutePlayDrawable">@drawable/mr_media_play_light</item>
         <item name="mediaRoutePauseDrawable">@drawable/mr_media_pause_light</item>
+        <item name="mediaRouteStopDrawable">@drawable/mr_media_stop_light</item>
         <item name="mediaRouteAudioTrackDrawable">@drawable/mr_vol_type_audiotrack_light</item>
         <item name="mediaRouteDefaultIconDrawable">@drawable/ic_mr_button_grey</item>
         <item name="mediaRouteTvIconDrawable">@drawable/ic_vol_type_tv_light</item>
@@ -59,12 +61,14 @@
     <style name="ThemeOverlay.MediaRouter.Dark" parent="ThemeOverlay.AppCompat.Dark">
         <item name="mediaRoutePlayDrawable">@drawable/mr_media_play_dark</item>
         <item name="mediaRoutePauseDrawable">@drawable/mr_media_pause_dark</item>
+        <item name="mediaRouteStopDrawable">@drawable/mr_media_stop_dark</item>
         <item name="mediaRouteAudioTrackDrawable">@drawable/mr_vol_type_audiotrack_dark</item>
 
     </style>
     <style name="ThemeOverlay.MediaRouter.Light" parent="ThemeOverlay.AppCompat.Light">
         <item name="mediaRoutePlayDrawable">@drawable/mr_media_play_light</item>
         <item name="mediaRoutePauseDrawable">@drawable/mr_media_pause_light</item>
+        <item name="mediaRouteStopDrawable">@drawable/mr_media_stop_light</item>
         <item name="mediaRouteAudioTrackDrawable">@drawable/mr_vol_type_audiotrack_light</item>
     </style>
 
diff --git a/v7/mediarouter/src/android/support/v7/app/MediaRouteControllerDialog.java b/v7/mediarouter/src/android/support/v7/app/MediaRouteControllerDialog.java
index 961e37e..4d40610 100644
--- a/v7/mediarouter/src/android/support/v7/app/MediaRouteControllerDialog.java
+++ b/v7/mediarouter/src/android/support/v7/app/MediaRouteControllerDialog.java
@@ -16,6 +16,11 @@
 
 package android.support.v7.app;
 
+import static android.support.v4.media.session.PlaybackStateCompat.ACTION_PAUSE;
+import static android.support.v4.media.session.PlaybackStateCompat.ACTION_PLAY;
+import static android.support.v4.media.session.PlaybackStateCompat.ACTION_PLAY_PAUSE;
+import static android.support.v4.media.session.PlaybackStateCompat.ACTION_STOP;
+
 import android.app.PendingIntent;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -67,7 +72,6 @@
 import android.widget.RelativeLayout;
 import android.widget.SeekBar;
 import android.widget.TextView;
-
 import java.io.BufferedInputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -119,7 +123,7 @@
 
     private Button mDisconnectButton;
     private Button mStopCastingButton;
-    private ImageButton mPlayPauseButton;
+    private ImageButton mPlaybackControlButton;
     private ImageButton mCloseButton;
     private MediaRouteExpandCollapseButton mGroupExpandCollapseButton;
 
@@ -351,7 +355,7 @@
         mDisconnectButton.setOnClickListener(listener);
 
         mStopCastingButton = (Button) findViewById(BUTTON_STOP_RES_ID);
-        mStopCastingButton.setText(R.string.mr_controller_stop);
+        mStopCastingButton.setText(R.string.mr_controller_stop_casting);
         mStopCastingButton.setTextColor(color);
         mStopCastingButton.setOnClickListener(listener);
 
@@ -388,8 +392,8 @@
         mPlaybackControlLayout = (RelativeLayout) findViewById(R.id.mr_playback_control);
         mTitleView = (TextView) findViewById(R.id.mr_control_title);
         mSubtitleView = (TextView) findViewById(R.id.mr_control_subtitle);
-        mPlayPauseButton = (ImageButton) findViewById(R.id.mr_control_play_pause);
-        mPlayPauseButton.setOnClickListener(listener);
+        mPlaybackControlButton = (ImageButton) findViewById(R.id.mr_control_playback_ctrl);
+        mPlaybackControlButton.setOnClickListener(listener);
 
         mVolumeControlLayout = (LinearLayout) findViewById(R.id.mr_volume_control);
         mVolumeControlLayout.setVisibility(View.GONE);
@@ -1006,30 +1010,47 @@
             if (mState != null) {
                 boolean isPlaying = mState.getState() == PlaybackStateCompat.STATE_BUFFERING
                         || mState.getState() == PlaybackStateCompat.STATE_PLAYING;
-                boolean supportsPlay = (mState.getActions() & (PlaybackStateCompat.ACTION_PLAY
-                        | PlaybackStateCompat.ACTION_PLAY_PAUSE)) != 0;
-                boolean supportsPause = (mState.getActions() & (PlaybackStateCompat.ACTION_PAUSE
-                        | PlaybackStateCompat.ACTION_PLAY_PAUSE)) != 0;
-                Context playPauseButtonContext = mPlayPauseButton.getContext();
-                if (isPlaying && supportsPause) {
-                    mPlayPauseButton.setVisibility(View.VISIBLE);
-                    mPlayPauseButton.setImageResource(MediaRouterThemeHelper.getThemeResource(
-                            playPauseButtonContext, R.attr.mediaRoutePauseDrawable));
-                    mPlayPauseButton.setContentDescription(playPauseButtonContext.getResources()
-                            .getText(R.string.mr_controller_pause));
-                } else if (!isPlaying && supportsPlay) {
-                    mPlayPauseButton.setVisibility(View.VISIBLE);
-                    mPlayPauseButton.setImageResource(MediaRouterThemeHelper.getThemeResource(
-                            playPauseButtonContext, R.attr.mediaRoutePlayDrawable));
-                    mPlayPauseButton.setContentDescription(playPauseButtonContext.getResources()
-                            .getText(R.string.mr_controller_play));
+                Context playbackControlButtonContext = mPlaybackControlButton.getContext();
+                boolean visible = true;
+                int iconDrawableAttr = 0;
+                int iconDescResId = 0;
+                if (isPlaying && isPauseActionSupported()) {
+                    iconDrawableAttr = R.attr.mediaRoutePauseDrawable;
+                    iconDescResId = R.string.mr_controller_pause;
+                } else if (isPlaying && isStopActionSupported()) {
+                    iconDrawableAttr = R.attr.mediaRouteStopDrawable;
+                    iconDescResId = R.string.mr_controller_stop;
+                } else if (!isPlaying && isPlayActionSupported()) {
+                    iconDrawableAttr = R.attr.mediaRoutePlayDrawable;
+                    iconDescResId = R.string.mr_controller_play;
                 } else {
-                    mPlayPauseButton.setVisibility(View.GONE);
+                    visible = false;
+                }
+                mPlaybackControlButton.setVisibility(visible ? View.VISIBLE : View.GONE);
+                if (visible) {
+                    mPlaybackControlButton.setImageResource(
+                            MediaRouterThemeHelper.getThemeResource(
+                                    playbackControlButtonContext, iconDrawableAttr));
+                    mPlaybackControlButton.setContentDescription(
+                            playbackControlButtonContext.getResources()
+                                    .getText(iconDescResId));
                 }
             }
         }
     }
 
+    private boolean isPlayActionSupported() {
+        return (mState.getActions() & (ACTION_PLAY | ACTION_PLAY_PAUSE)) != 0;
+    }
+
+    private boolean isPauseActionSupported() {
+        return (mState.getActions() & (ACTION_PAUSE | ACTION_PLAY_PAUSE)) != 0;
+    }
+
+    private boolean isStopActionSupported() {
+        return (mState.getActions() & ACTION_STOP) != 0;
+    }
+
     boolean isVolumeControlAvailable(MediaRouter.RouteInfo route) {
         return mVolumeControlEnabled && route.getVolumeHandling()
                 == MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE;
@@ -1172,23 +1193,28 @@
                             MediaRouter.UNSELECT_REASON_DISCONNECTED);
                 }
                 dismiss();
-            } else if (id == R.id.mr_control_play_pause) {
+            } else if (id == R.id.mr_control_playback_ctrl) {
                 if (mMediaController != null && mState != null) {
                     boolean isPlaying = mState.getState() == PlaybackStateCompat.STATE_PLAYING;
-                    if (isPlaying) {
+                    int actionDescResId = 0;
+                    if (isPlaying && isPauseActionSupported()) {
                         mMediaController.getTransportControls().pause();
-                    } else {
+                        actionDescResId = R.string.mr_controller_pause;
+                    } else if (isPlaying && isStopActionSupported()) {
+                        mMediaController.getTransportControls().stop();
+                        actionDescResId = R.string.mr_controller_stop;
+                    } else if (!isPlaying && isPlayActionSupported()){
                         mMediaController.getTransportControls().play();
+                        actionDescResId = R.string.mr_controller_play;
                     }
                     // Announce the action for accessibility.
-                    if (mAccessibilityManager != null && mAccessibilityManager.isEnabled()) {
+                    if (mAccessibilityManager != null && mAccessibilityManager.isEnabled()
+                            && actionDescResId != 0) {
                         AccessibilityEvent event = AccessibilityEvent.obtain(
                                 AccessibilityEventCompat.TYPE_ANNOUNCEMENT);
                         event.setPackageName(mContext.getPackageName());
                         event.setClassName(getClass().getName());
-                        int resId = isPlaying ?
-                                R.string.mr_controller_pause : R.string.mr_controller_play;
-                        event.getText().add(mContext.getString(resId));
+                        event.getText().add(mContext.getString(actionDescResId));
                         mAccessibilityManager.sendAccessibilityEvent(event);
                     }
                 }
diff --git a/v7/mediarouter/src/android/support/v7/media/MediaRouter.java b/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
index 3c8e64d..fe16de8 100644
--- a/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
+++ b/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
@@ -18,7 +18,6 @@
 
 import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
 
-import android.annotation.TargetApi;
 import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -2089,11 +2088,6 @@
                 throw new IllegalStateException("There is no currently selected route.  "
                         + "The media router has not yet been fully initialized.");
             }
-            // A workaround for making this method work properly.
-            if (android.os.Build.VERSION.SDK_INT >= 16 && android.os.Build.VERSION.SDK_INT < 25
-                    && RouteInfo.isSystemMediaRouteProvider(mSelectedRoute)) {
-                syncSystemRoutes();
-            }
             return mSelectedRoute;
         }
 
@@ -2110,12 +2104,6 @@
                 Log.w(TAG, "Ignoring attempt to select disabled route: " + route);
                 return;
             }
-
-            // A workaround for making this method work properly.
-            if (android.os.Build.VERSION.SDK_INT >= 16 && android.os.Build.VERSION.SDK_INT < 25
-                    && RouteInfo.isSystemMediaRouteProvider(route)) {
-                syncSystemRoutes();
-            }
             setSelectedRouteInternal(route, unselectReason);
         }
 
@@ -2250,25 +2238,6 @@
             }
         }
 
-        @TargetApi(16)
-        void syncSystemRoutes() {
-            Object routerObj = MediaRouterJellybean.getMediaRouter(mApplicationContext);
-            boolean routedToBluetooth = MediaRouterJellybean.checkRoutedToBluetooth(
-                mApplicationContext);
-            Object selectedRouteObj = MediaRouterJellybean.getSelectedRoute(
-                    routerObj, MediaRouterJellybean.ALL_ROUTE_TYPES);
-            Object defaultRouteObj = mSystemProvider.getDefaultRoute();
-            Object bluetoothRouteObj = mSystemProvider.getSystemRoute(mBluetoothRoute);
-
-            if (routedToBluetooth && selectedRouteObj == defaultRouteObj) {
-                MediaRouterJellybean.selectRoute(routerObj,
-                    MediaRouterJellybean.ALL_ROUTE_TYPES, bluetoothRouteObj);
-            } else if (!routedToBluetooth && selectedRouteObj == bluetoothRouteObj) {
-                MediaRouterJellybean.selectRoute(routerObj,
-                        MediaRouterJellybean.ALL_ROUTE_TYPES, defaultRouteObj);
-            }
-        }
-
         void updateProviderDescriptor(MediaRouteProvider providerInstance,
                 MediaRouteProviderDescriptor descriptor) {
             int index = findProviderInfo(providerInstance);
diff --git a/v7/recyclerview/src/android/support/v7/widget/GridLayoutManager.java b/v7/recyclerview/src/android/support/v7/widget/GridLayoutManager.java
index 60f601c..fad3448 100644
--- a/v7/recyclerview/src/android/support/v7/widget/GridLayoutManager.java
+++ b/v7/recyclerview/src/android/support/v7/widget/GridLayoutManager.java
@@ -1017,98 +1017,47 @@
             limit = getChildCount();
         }
         final boolean preferLastSpan = mOrientation == VERTICAL && isLayoutRTL();
+        View weakCandidate = null; // somewhat matches but not strong
+        int weakCandidateSpanIndex = -1;
+        int weakCandidateOverlap = 0; // how many spans overlap
 
-        // The focusable candidate to be picked if no perfect focusable candidate is found.
-        // The best focusable candidate is the one with the highest amount of span overlap with
-        // the currently focused view.
-        View focusableWeakCandidate = null; // somewhat matches but not strong
-        int focusableWeakCandidateSpanIndex = -1;
-        int focusableWeakCandidateOverlap = 0; // how many spans overlap
-
-        // The unfocusable candidate to become visible on the screen next, if no perfect or
-        // weak focusable candidates are found to receive focus next.
-        // We are only interested in partially visible unfocusable views. These are views that are
-        // not fully visible, that is either partially overlapping, or out-of-bounds and right below
-        // or above RV's padded bounded area. The best unfocusable candidate is the one with the
-        // highest amount of span overlap with the currently focused view.
-        View unfocusableWeakCandidate = null; // somewhat matches but not strong
-        int unfocusableWeakCandidateSpanIndex = -1;
-        int unfocusableWeakCandidateOverlap = 0; // how many spans overlap
-
-        // The span group index of the start child. This indicates the span group index of the
-        // next focusable item to receive focus, if a focusable item within the same span group
-        // exists. Any focusable item beyond this group index are not relevant since they
-        // were already stored in the layout before onFocusSearchFailed call and were not picked
-        // by the focusSearch algorithm.
-        int focusableSpanGroupIndex = getSpanGroupIndex(recycler, state, start);
         for (int i = start; i != limit; i += inc) {
-            int spanGroupIndex = getSpanGroupIndex(recycler, state, i);
             View candidate = getChildAt(i);
             if (candidate == prevFocusedChild) {
                 break;
             }
-
-            if (candidate.isFocusable() && spanGroupIndex != focusableSpanGroupIndex) {
-                // We are past the allowable span group index for the next focusable item.
-                // The search only continues if no focusable weak candidates have been found up
-                // until this point, in order to find the best unfocusable candidate to become
-                // visible on the screen next.
-                if (focusableWeakCandidate != null) {
-                    break;
-                }
+            if (!candidate.isFocusable()) {
                 continue;
             }
-
             final LayoutParams candidateLp = (LayoutParams) candidate.getLayoutParams();
             final int candidateStart = candidateLp.mSpanIndex;
             final int candidateEnd = candidateLp.mSpanIndex + candidateLp.mSpanSize;
-            if (candidate.isFocusable() && candidateStart == prevSpanStart
-                    && candidateEnd == prevSpanEnd) {
+            if (candidateStart == prevSpanStart && candidateEnd == prevSpanEnd) {
                 return candidate; // perfect match
             }
             boolean assignAsWeek = false;
-            if ((candidate.isFocusable() && focusableWeakCandidate == null)
-                    || (!candidate.isFocusable() && unfocusableWeakCandidate == null)) {
+            if (weakCandidate == null) {
                 assignAsWeek = true;
             } else {
                 int maxStart = Math.max(candidateStart, prevSpanStart);
                 int minEnd = Math.min(candidateEnd, prevSpanEnd);
                 int overlap = minEnd - maxStart;
-                if (candidate.isFocusable()) {
-                    if (overlap > focusableWeakCandidateOverlap) {
-                        assignAsWeek = true;
-                    } else if (overlap == focusableWeakCandidateOverlap
-                            && preferLastSpan == (candidateStart
-                            > focusableWeakCandidateSpanIndex)) {
-                        assignAsWeek = true;
-                    }
-                } else if (focusableWeakCandidate == null
-                        && isViewPartiallyVisible(candidate, false, true)) {
-                    if (overlap > unfocusableWeakCandidateOverlap) {
-                        assignAsWeek = true;
-                    } else if (overlap == unfocusableWeakCandidateOverlap
-                            && preferLastSpan == (candidateStart
-                                    > unfocusableWeakCandidateSpanIndex)) {
-                        assignAsWeek = true;
-                    }
+                if (overlap > weakCandidateOverlap) {
+                    assignAsWeek = true;
+                } else if (overlap == weakCandidateOverlap &&
+                        preferLastSpan == (candidateStart > weakCandidateSpanIndex)) {
+                    assignAsWeek = true;
                 }
             }
 
             if (assignAsWeek) {
-                if (candidate.isFocusable()) {
-                    focusableWeakCandidate = candidate;
-                    focusableWeakCandidateSpanIndex = candidateLp.mSpanIndex;
-                    focusableWeakCandidateOverlap = Math.min(candidateEnd, prevSpanEnd)
-                            - Math.max(candidateStart, prevSpanStart);
-                } else {
-                    unfocusableWeakCandidate = candidate;
-                    unfocusableWeakCandidateSpanIndex = candidateLp.mSpanIndex;
-                    unfocusableWeakCandidateOverlap = Math.min(candidateEnd, prevSpanEnd)
-                            - Math.max(candidateStart, prevSpanStart);
-                }
+                weakCandidate = candidate;
+                weakCandidateSpanIndex = candidateLp.mSpanIndex;
+                weakCandidateOverlap = Math.min(candidateEnd, prevSpanEnd) -
+                        Math.max(candidateStart, prevSpanStart);
             }
         }
-        return (focusableWeakCandidate != null) ? focusableWeakCandidate : unfocusableWeakCandidate;
+        return weakCandidate;
     }
 
     @Override
diff --git a/v7/recyclerview/src/android/support/v7/widget/LinearLayoutManager.java b/v7/recyclerview/src/android/support/v7/widget/LinearLayoutManager.java
index 65a2045..2436a4c 100644
--- a/v7/recyclerview/src/android/support/v7/widget/LinearLayoutManager.java
+++ b/v7/recyclerview/src/android/support/v7/widget/LinearLayoutManager.java
@@ -676,8 +676,7 @@
      * If necessary, layouts new items for predictive animations
      */
     private void layoutForPredictiveAnimations(RecyclerView.Recycler recycler,
-            RecyclerView.State state, int startOffset,
-            int endOffset) {
+            RecyclerView.State state, int startOffset,  int endOffset) {
         // If there are scrap children that we did not layout, we need to find where they did go
         // and layout them accordingly so that animations can work as expected.
         // This case may happen if new views are added or an existing view expands and pushes
@@ -857,7 +856,7 @@
                 }
                 anchorInfo.mCoordinate = anchorInfo.mLayoutFromEnd
                         ? (mOrientationHelper.getDecoratedEnd(child) + mOrientationHelper
-                        .getTotalSpaceChange())
+                                .getTotalSpaceChange())
                         : mOrientationHelper.getDecoratedStart(child);
             } else { // item is not visible.
                 if (getChildCount() > 0) {
@@ -1794,32 +1793,6 @@
         return outOfBoundsMatch != null ? outOfBoundsMatch : invalidMatch;
     }
 
-    // returns the out-of-bound child view closest to RV's end bounds. An out-of-bound child is
-    // defined as a child that's either partially or fully invisible (outside RV's padding area).
-    private View findPartiallyOrCompletelyInvisibleChildClosestToEnd(RecyclerView.Recycler recycler,
-            RecyclerView.State state) {
-        return mShouldReverseLayout ? findFirstPartiallyOrCompletelyInvisibleChild(recycler, state)
-                : findLastPartiallyOrCompletelyInvisibleChild(recycler, state);
-    }
-
-    // returns the out-of-bound child view closest to RV's starting bounds. An out-of-bound child is
-    // defined as a child that's either partially or fully invisible (outside RV's padding area).
-    private View findPartiallyOrCompletelyInvisibleChildClosestToStart(
-            RecyclerView.Recycler recycler, RecyclerView.State state) {
-        return mShouldReverseLayout ? findLastPartiallyOrCompletelyInvisibleChild(recycler, state) :
-                findFirstPartiallyOrCompletelyInvisibleChild(recycler, state);
-    }
-
-    private View findFirstPartiallyOrCompletelyInvisibleChild(RecyclerView.Recycler recycler,
-            RecyclerView.State state) {
-        return findOnePartiallyOrCompletelyInvisibleChild(0, getChildCount());
-    }
-
-    private View findLastPartiallyOrCompletelyInvisibleChild(RecyclerView.Recycler recycler,
-            RecyclerView.State state) {
-        return findOnePartiallyOrCompletelyInvisibleChild(getChildCount() - 1, -1);
-    }
-
     /**
      * Returns the adapter position of the first visible view. This position does not include
      * adapter changes that were dispatched after the last layout pass.
@@ -1903,52 +1876,27 @@
     View findOneVisibleChild(int fromIndex, int toIndex, boolean completelyVisible,
             boolean acceptPartiallyVisible) {
         ensureLayoutState();
-        @ViewBoundsCheck.ViewBounds int preferredBoundsFlag = 0;
-        @ViewBoundsCheck.ViewBounds int acceptableBoundsFlag = 0;
-        if (completelyVisible) {
-            preferredBoundsFlag = (ViewBoundsCheck.FLAG_CVS_GT_PVS | ViewBoundsCheck.FLAG_CVS_EQ_PVS
-                    | ViewBoundsCheck.FLAG_CVE_LT_PVE | ViewBoundsCheck.FLAG_CVE_EQ_PVE);
-        } else {
-            preferredBoundsFlag = (ViewBoundsCheck.FLAG_CVS_LT_PVE | ViewBoundsCheck.FLAG_CVS_EQ_PVE
-                    | ViewBoundsCheck.FLAG_CVE_GT_PVS | ViewBoundsCheck.FLAG_CVE_EQ_PVS);
+        final int start = mOrientationHelper.getStartAfterPadding();
+        final int end = mOrientationHelper.getEndAfterPadding();
+        final int next = toIndex > fromIndex ? 1 : -1;
+        View partiallyVisible = null;
+        for (int i = fromIndex; i != toIndex; i+=next) {
+            final View child = getChildAt(i);
+            final int childStart = mOrientationHelper.getDecoratedStart(child);
+            final int childEnd = mOrientationHelper.getDecoratedEnd(child);
+            if (childStart < end && childEnd > start) {
+                if (completelyVisible) {
+                    if (childStart >= start && childEnd <= end) {
+                        return child;
+                    } else if (acceptPartiallyVisible && partiallyVisible == null) {
+                        partiallyVisible = child;
+                    }
+                } else {
+                    return child;
+                }
+            }
         }
-        if (acceptPartiallyVisible) {
-            acceptableBoundsFlag = (ViewBoundsCheck.FLAG_CVS_LT_PVE
-                    | ViewBoundsCheck.FLAG_CVS_EQ_PVE | ViewBoundsCheck.FLAG_CVE_GT_PVS
-                    | ViewBoundsCheck.FLAG_CVE_EQ_PVS);
-        }
-        return (mOrientation == HORIZONTAL) ? mHorizontalBoundCheck
-                .findOneViewWithinBoundFlags(fromIndex, toIndex, preferredBoundsFlag,
-                        acceptableBoundsFlag) : mVerticalBoundCheck
-                .findOneViewWithinBoundFlags(fromIndex, toIndex, preferredBoundsFlag,
-                        acceptableBoundsFlag);
-    }
-
-    View findOnePartiallyOrCompletelyInvisibleChild(int fromIndex, int toIndex) {
-        ensureLayoutState();
-        final int next = toIndex > fromIndex ? 1 : (toIndex < fromIndex ? -1 : 0);
-        if (next == 0) {
-            return getChildAt(fromIndex);
-        }
-        @ViewBoundsCheck.ViewBounds int preferredBoundsFlag = 0;
-        @ViewBoundsCheck.ViewBounds int acceptableBoundsFlag = 0;
-        if (mOrientationHelper.getDecoratedStart(getChildAt(fromIndex))
-                < mOrientationHelper.getStartAfterPadding()) {
-            preferredBoundsFlag = (ViewBoundsCheck.FLAG_CVS_LT_PVS | ViewBoundsCheck.FLAG_CVE_LT_PVE
-                    | ViewBoundsCheck.FLAG_CVE_GT_PVS);
-            acceptableBoundsFlag = (ViewBoundsCheck.FLAG_CVS_LT_PVS
-                    | ViewBoundsCheck.FLAG_CVE_LT_PVE);
-        } else {
-            preferredBoundsFlag = (ViewBoundsCheck.FLAG_CVE_GT_PVE | ViewBoundsCheck.FLAG_CVS_GT_PVS
-                    | ViewBoundsCheck.FLAG_CVS_LT_PVE);
-            acceptableBoundsFlag = (ViewBoundsCheck.FLAG_CVE_GT_PVE
-                    | ViewBoundsCheck.FLAG_CVS_GT_PVS);
-        }
-        return (mOrientation == HORIZONTAL) ? mHorizontalBoundCheck
-                .findOneViewWithinBoundFlags(fromIndex, toIndex, preferredBoundsFlag,
-                        acceptableBoundsFlag) : mVerticalBoundCheck
-                .findOneViewWithinBoundFlags(fromIndex, toIndex, preferredBoundsFlag,
-                        acceptableBoundsFlag);
+        return partiallyVisible;
     }
 
     @Override
@@ -1964,38 +1912,35 @@
             return null;
         }
         ensureLayoutState();
+        final View referenceChild;
+        if (layoutDir == LayoutState.LAYOUT_START) {
+            referenceChild = findReferenceChildClosestToStart(recycler, state);
+        } else {
+            referenceChild = findReferenceChildClosestToEnd(recycler, state);
+        }
+        if (referenceChild == null) {
+            if (DEBUG) {
+                Log.d(TAG,
+                        "Cannot find a child with a valid position to be used for focus search.");
+            }
+            return null;
+        }
         ensureLayoutState();
         final int maxScroll = (int) (MAX_SCROLL_FACTOR * mOrientationHelper.getTotalSpace());
         updateLayoutState(layoutDir, maxScroll, false, state);
         mLayoutState.mScrollingOffset = LayoutState.SCROLLING_OFFSET_NaN;
         mLayoutState.mRecycle = false;
         fill(recycler, mLayoutState, state, true);
-
-        // nextCandidate is the first child view in the layout direction that's partially
-        // within RV's bounds, i.e. part of it is visible or it's completely invisible but still
-        // touching RV's bounds. This will be the unfocusable candidate view to become visible onto
-        // the screen if no focusable views are found in the given layout direction.
-        final View nextCandidate;
-        if (layoutDir == LayoutState.LAYOUT_START) {
-            nextCandidate = findPartiallyOrCompletelyInvisibleChildClosestToStart(recycler, state);
-        } else {
-            nextCandidate = findPartiallyOrCompletelyInvisibleChildClosestToEnd(recycler, state);
-        }
-        // nextFocus is meaningful only if it refers to a focusable child, in which case it
-        // indicates the next view to gain focus.
         final View nextFocus;
         if (layoutDir == LayoutState.LAYOUT_START) {
             nextFocus = getChildClosestToStart();
         } else {
             nextFocus = getChildClosestToEnd();
         }
-        if (nextFocus.isFocusable()) {
-            if (nextCandidate == null) {
-                return null;
-            }
-            return nextFocus;
+        if (nextFocus == referenceChild || !nextFocus.isFocusable()) {
+            return null;
         }
-        return nextCandidate;
+        return nextFocus;
     }
 
     /**
@@ -2083,9 +2028,9 @@
         if (mShouldReverseLayout) {
             if (dropDirection == LayoutState.ITEM_DIRECTION_TAIL) {
                 scrollToPositionWithOffset(targetPos,
-                        mOrientationHelper.getEndAfterPadding()
-                                - (mOrientationHelper.getDecoratedStart(target)
-                                + mOrientationHelper.getDecoratedMeasurement(view)));
+                        mOrientationHelper.getEndAfterPadding() -
+                                (mOrientationHelper.getDecoratedStart(target) +
+                                mOrientationHelper.getDecoratedMeasurement(view)));
             } else {
                 scrollToPositionWithOffset(targetPos,
                         mOrientationHelper.getEndAfterPadding()
diff --git a/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java b/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java
index ba01513..2a74928 100644
--- a/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java
+++ b/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java
@@ -507,39 +507,38 @@
      */
     private final ViewInfoStore.ProcessCallback mViewInfoProcessCallback =
             new ViewInfoStore.ProcessCallback() {
-                @Override
-                public void processDisappeared(ViewHolder viewHolder, @NonNull ItemHolderInfo info,
-                        @Nullable ItemHolderInfo postInfo) {
-                    mRecycler.unscrapView(viewHolder);
-                    animateDisappearance(viewHolder, info, postInfo);
-                }
-                @Override
-                public void processAppeared(ViewHolder viewHolder,
-                        ItemHolderInfo preInfo, ItemHolderInfo info) {
-                    animateAppearance(viewHolder, preInfo, info);
-                }
+        @Override
+        public void processDisappeared(ViewHolder viewHolder, @NonNull ItemHolderInfo info,
+                @Nullable ItemHolderInfo postInfo) {
+            mRecycler.unscrapView(viewHolder);
+            animateDisappearance(viewHolder, info, postInfo);
+        }
+        @Override
+        public void processAppeared(ViewHolder viewHolder,
+                ItemHolderInfo preInfo, ItemHolderInfo info) {
+            animateAppearance(viewHolder, preInfo, info);
+        }
 
-                @Override
-                public void processPersistent(ViewHolder viewHolder,
-                        @NonNull ItemHolderInfo preInfo, @NonNull ItemHolderInfo postInfo) {
-                    viewHolder.setIsRecyclable(false);
-                    if (mDataSetHasChangedAfterLayout) {
-                        // since it was rebound, use change instead as we'll be mapping them from
-                        // stable ids. If stable ids were false, we would not be running any
-                        // animations
-                        if (mItemAnimator.animateChange(viewHolder, viewHolder, preInfo,
-                                postInfo)) {
-                            postAnimationRunner();
-                        }
-                    } else if (mItemAnimator.animatePersistence(viewHolder, preInfo, postInfo)) {
-                        postAnimationRunner();
-                    }
+        @Override
+        public void processPersistent(ViewHolder viewHolder,
+                @NonNull ItemHolderInfo preInfo, @NonNull ItemHolderInfo postInfo) {
+            viewHolder.setIsRecyclable(false);
+            if (mDataSetHasChangedAfterLayout) {
+                // since it was rebound, use change instead as we'll be mapping them from
+                // stable ids. If stable ids were false, we would not be running any
+                // animations
+                if (mItemAnimator.animateChange(viewHolder, viewHolder, preInfo, postInfo)) {
+                    postAnimationRunner();
                 }
-                @Override
-                public void unused(ViewHolder viewHolder) {
-                    mLayout.removeAndRecycleView(viewHolder.itemView, mRecycler);
-                }
-            };
+            } else if (mItemAnimator.animatePersistence(viewHolder, preInfo, postInfo)) {
+                postAnimationRunner();
+            }
+        }
+        @Override
+        public void unused(ViewHolder viewHolder) {
+            mLayout.removeAndRecycleView(viewHolder.itemView, mRecycler);
+        }
+    };
 
     public RecyclerView(Context context) {
         this(context, null);
@@ -2333,13 +2332,6 @@
                 resumeRequestLayout(false);
             }
         }
-        if (result != null && !result.hasFocusable()) {
-            // If the next view returned by onFocusSearchFailed in layout manager has no focusable
-            // views, we still scroll to that view in order to make it visible on the screen.
-            // If it's focusable, framework already calls RV's requestChildFocus which handles
-            // bringing this newly focused item onto the screen.
-            requestChildOnScreen(result, null);
-        }
         return isPreferredNextFocus(focused, result, direction)
                 ? result : super.focusSearch(focused, direction);
     }
@@ -2410,46 +2402,29 @@
     @Override
     public void requestChildFocus(View child, View focused) {
         if (!mLayout.onRequestChildFocus(this, mState, child, focused) && focused != null) {
-            requestChildOnScreen(child, focused);
-        }
-        super.requestChildFocus(child, focused);
-    }
+            mTempRect.set(0, 0, focused.getWidth(), focused.getHeight());
 
-    /**
-     * Requests that the given child of the RecyclerView be positioned onto the screen. This method
-     * can be called for both unfocusable and focusable child views. For unfocusable child views,
-     * the {@param focused} parameter passed is null, whereas for a focusable child, this parameter
-     * indicates the actual descendant view within this child view that holds the focus.
-     * @param child The child view of this RecyclerView that wants to come onto the screen.
-     * @param focused The descendant view that actually has the focus if child is focusable, null
-     *                otherwise.
-     */
-    private void requestChildOnScreen(@NonNull View child, @Nullable View focused) {
-        View rectView = (focused != null) ? focused : child;
-        mTempRect.set(0, 0, rectView.getWidth(), rectView.getHeight());
-
-        // get item decor offsets w/o refreshing. If they are invalid, there will be another
-        // layout pass to fix them, then it is LayoutManager's responsibility to keep focused
-        // View in viewport.
-        final ViewGroup.LayoutParams focusedLayoutParams = rectView.getLayoutParams();
-        if (focusedLayoutParams instanceof LayoutParams) {
-            // if focused child has item decors, use them. Otherwise, ignore.
-            final LayoutParams lp = (LayoutParams) focusedLayoutParams;
-            if (!lp.mInsetsDirty) {
-                final Rect insets = lp.mDecorInsets;
-                mTempRect.left -= insets.left;
-                mTempRect.right += insets.right;
-                mTempRect.top -= insets.top;
-                mTempRect.bottom += insets.bottom;
+            // get item decor offsets w/o refreshing. If they are invalid, there will be another
+            // layout pass to fix them, then it is LayoutManager's responsibility to keep focused
+            // View in viewport.
+            final ViewGroup.LayoutParams focusedLayoutParams = focused.getLayoutParams();
+            if (focusedLayoutParams instanceof LayoutParams) {
+                // if focused child has item decors, use them. Otherwise, ignore.
+                final LayoutParams lp = (LayoutParams) focusedLayoutParams;
+                if (!lp.mInsetsDirty) {
+                    final Rect insets = lp.mDecorInsets;
+                    mTempRect.left -= insets.left;
+                    mTempRect.right += insets.right;
+                    mTempRect.top -= insets.top;
+                    mTempRect.bottom += insets.bottom;
+                }
             }
-        }
 
-        if (focused != null) {
             offsetDescendantRectToMyCoords(focused, mTempRect);
             offsetRectIntoDescendantCoords(child, mTempRect);
+            requestChildRectangleOnScreen(child, mTempRect, !mFirstLayoutComplete);
         }
-        mLayout.requestChildRectangleOnScreen(this, child, mTempRect, !mFirstLayoutComplete,
-                (focused == null));
+        super.requestChildFocus(child, focused);
     }
 
     @Override
@@ -2572,11 +2547,10 @@
             throw new IllegalStateException(message);
         }
         if (mDispatchScrollCounter > 0) {
-            Log.w(TAG, "Cannot call this method in a scroll callback. Scroll callbacks might"
-                            + "be run during a measure & layout pass where you cannot change the"
-                            + "RecyclerView data. Any method call that might change the structure"
-                            + "of the RecyclerView or the adapter contents should be postponed to"
-                            + "the next frame.",
+            Log.w(TAG, "Cannot call this method in a scroll callback. Scroll callbacks might be run"
+                    + " during a measure & layout pass where you cannot change the RecyclerView"
+                    + " data. Any method call that might change the structure of the RecyclerView"
+                    + " or the adapter contents should be postponed to the next frame.",
                     new IllegalStateException(""));
         }
     }
@@ -3251,10 +3225,10 @@
         mState.mRunSimpleAnimations = mFirstLayoutComplete
                 && mItemAnimator != null
                 && (mDataSetHasChangedAfterLayout
-                || animationTypeSupported
-                || mLayout.mRequestedSimpleAnimations)
+                        || animationTypeSupported
+                        || mLayout.mRequestedSimpleAnimations)
                 && (!mDataSetHasChangedAfterLayout
-                || mAdapter.hasStableIds());
+                        || mAdapter.hasStableIds());
         mState.mRunPredictiveAnimations = mState.mRunSimpleAnimations
                 && animationTypeSupported
                 && !mDataSetHasChangedAfterLayout
@@ -5752,9 +5726,9 @@
             if (forceRecycle || holder.isRecyclable()) {
                 if (mViewCacheMax > 0
                         && !holder.hasAnyOfTheFlags(ViewHolder.FLAG_INVALID
-                        | ViewHolder.FLAG_REMOVED
-                        | ViewHolder.FLAG_UPDATE
-                        | ViewHolder.FLAG_ADAPTER_POSITION_UNKNOWN)) {
+                                | ViewHolder.FLAG_REMOVED
+                                | ViewHolder.FLAG_UPDATE
+                                | ViewHolder.FLAG_ADAPTER_POSITION_UNKNOWN)) {
                     // Retire oldest cached view
                     int cachedViewSize = mCachedViews.size();
                     if (cachedViewSize >= mViewCacheMax && cachedViewSize > 0) {
@@ -6856,109 +6830,6 @@
         ChildHelper mChildHelper;
         RecyclerView mRecyclerView;
 
-        /**
-         * The callback used for retrieving information about a RecyclerView and its children in the
-         * horizontal direction.
-         */
-        private final ViewBoundsCheck.Callback mHorizontalBoundCheckCallback =
-                new ViewBoundsCheck.Callback() {
-                    @Override
-                    public int getChildCount() {
-                        return LayoutManager.this.getChildCount();
-                    }
-
-                    @Override
-                    public View getParent() {
-                        return mRecyclerView;
-                    }
-
-                    @Override
-                    public View getChildAt(int index) {
-                        return LayoutManager.this.getChildAt(index);
-                    }
-
-                    @Override
-                    public int getParentStart() {
-                        return LayoutManager.this.getPaddingLeft();
-                    }
-
-                    @Override
-                    public int getParentEnd() {
-                        return LayoutManager.this.getWidth() - LayoutManager.this.getPaddingRight();
-                    }
-
-                    @Override
-                    public int getChildStart(View view) {
-                        final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
-                                view.getLayoutParams();
-                        return LayoutManager.this.getDecoratedLeft(view) - params.leftMargin;
-                    }
-
-                    @Override
-                    public int getChildEnd(View view) {
-                        final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
-                                view.getLayoutParams();
-                        return LayoutManager.this.getDecoratedRight(view) + params.rightMargin;
-                    }
-                };
-
-        /**
-         * The callback used for retrieving information about a RecyclerView and its children in the
-         * vertical direction.
-         */
-        private final ViewBoundsCheck.Callback mVerticalBoundCheckCallback =
-                new ViewBoundsCheck.Callback() {
-                    @Override
-                    public int getChildCount() {
-                        return LayoutManager.this.getChildCount();
-                    }
-
-                    @Override
-                    public View getParent() {
-                        return mRecyclerView;
-                    }
-
-                    @Override
-                    public View getChildAt(int index) {
-                        return LayoutManager.this.getChildAt(index);
-                    }
-
-                    @Override
-                    public int getParentStart() {
-                        return LayoutManager.this.getPaddingTop();
-                    }
-
-                    @Override
-                    public int getParentEnd() {
-                        return LayoutManager.this.getHeight()
-                                - LayoutManager.this.getPaddingBottom();
-                    }
-
-                    @Override
-                    public int getChildStart(View view) {
-                        final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
-                                view.getLayoutParams();
-                        return LayoutManager.this.getDecoratedTop(view) - params.topMargin;
-                    }
-
-                    @Override
-                    public int getChildEnd(View view) {
-                        final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
-                                view.getLayoutParams();
-                        return LayoutManager.this.getDecoratedBottom(view) + params.bottomMargin;
-                    }
-                };
-
-        /**
-         * Utility objects used to check the boundaries of children against their parent
-         * RecyclerView.
-         * @see #isViewPartiallyVisible(View, boolean, boolean),
-         * {@link LinearLayoutManager#findOneVisibleChild(int, int, boolean, boolean)},
-         * and {@link LinearLayoutManager#findOnePartiallyOrCompletelyInvisibleChild(int, int)}.
-         */
-        ViewBoundsCheck mHorizontalBoundCheck = new ViewBoundsCheck(mHorizontalBoundCheckCallback);
-        ViewBoundsCheck mVerticalBoundCheck = new ViewBoundsCheck(mVerticalBoundCheckCallback);
-
         @Nullable
         SmoothScroller mSmoothScroller;
 
@@ -9025,11 +8896,7 @@
          *
          * <p>This is the LayoutManager's opportunity to populate views in the given direction
          * to fulfill the request if it can. The LayoutManager should attach and return
-         * the view to be focused, if a focusable view in the given direction is found.
-         * Otherwise, if all the existing (or the newly populated views) are unfocusable, it returns
-         * the next unfocusable view to become visible on the screen. This unfocusable view is
-         * typically the first view that's either partially or fully out of RV's padded bounded
-         * area in the given direction. The default implementation returns null.</p>
+         * the view to be focused. The default implementation returns null.</p>
          *
          * @param focused   The currently focused view
          * @param direction One of {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
@@ -9038,8 +8905,7 @@
          *                  or 0 for not applicable
          * @param recycler  The recycler to use for obtaining views for currently offscreen items
          * @param state     Transient state of RecyclerView
-         * @return The chosen view to be focused if a focusable view is found, otherwise an
-         * unfocusable view to become visible onto the screen, else null.
+         * @return The chosen view to be focused
          */
         @Nullable
         public View onFocusSearchFailed(View focused, int direction, Recycler recycler,
@@ -9068,20 +8934,22 @@
         }
 
         /**
-         * Returns the scroll amount that brings the given rect in child's coordinate system within
-         * the padded area of RecyclerView.
-         * @param parent The parent RecyclerView.
+         * Called when a child of the RecyclerView wants a particular rectangle to be positioned
+         * onto the screen. See {@link ViewParent#requestChildRectangleOnScreen(android.view.View,
+         * android.graphics.Rect, boolean)} for more details.
+         *
+         * <p>The base implementation will attempt to perform a standard programmatic scroll
+         * to bring the given rect into view, within the padded area of the RecyclerView.</p>
+         *
          * @param child The direct child making the request.
-         * @param rect The rectangle in the child's coordinates the child
-         *             wishes to be on the screen.
+         * @param rect  The rectangle in the child's coordinates the child
+         *              wishes to be on the screen.
          * @param immediate True to forbid animated or delayed scrolling,
          *                  false otherwise
-         * @return The array containing the scroll amount in x and y directions that brings the
-         * given rect into RV's padded area.
+         * @return Whether the group scrolled to handle the operation
          */
-        private int[] getChildRectangleOnScreenScrollAmount(RecyclerView parent, View child,
-                Rect rect, boolean immediate) {
-            int[] out = new int[2];
+        public boolean requestChildRectangleOnScreen(RecyclerView parent, View child, Rect rect,
+                boolean immediate) {
             final int parentLeft = getPaddingLeft();
             final int parentTop = getPaddingTop();
             final int parentRight = getWidth() - getPaddingRight();
@@ -9112,122 +8980,19 @@
             // we should scroll to make bottom visible, make sure top does not go out of bounds.
             final int dy = offScreenTop != 0 ? offScreenTop
                     : Math.min(childTop - parentTop, offScreenBottom);
-            out[0] = dx;
-            out[1] = dy;
-            return out;
-        }
-        /**
-         * Called when a child of the RecyclerView wants a particular rectangle to be positioned
-         * onto the screen. See {@link ViewParent#requestChildRectangleOnScreen(android.view.View,
-         * android.graphics.Rect, boolean)} for more details.
-         *
-         * <p>The base implementation will attempt to perform a standard programmatic scroll
-         * to bring the given rect into view, within the padded area of the RecyclerView.</p>
-         *
-         * @param child The direct child making the request.
-         * @param rect  The rectangle in the child's coordinates the child
-         *              wishes to be on the screen.
-         * @param immediate True to forbid animated or delayed scrolling,
-         *                  false otherwise
-         * @return Whether the group scrolled to handle the operation
-         */
-        public boolean requestChildRectangleOnScreen(RecyclerView parent, View child, Rect rect,
-                boolean immediate) {
-            return requestChildRectangleOnScreen(parent, child, rect, immediate, false);
-        }
 
-        /**
-         * Requests that the given child of the RecyclerView be positioned onto the screen. This
-         * method can be called for both unfocusable and focusable child views. For unfocusable
-         * child views, focusedChildVisible is typically true in which case, layout manager
-         * makes the child view visible only if the currently focused child stays in-bounds of RV.
-         * @param parent The parent RecyclerView.
-         * @param child The direct child making the request.
-         * @param rect The rectangle in the child's coordinates the child
-         *              wishes to be on the screen.
-         * @param immediate True to forbid animated or delayed scrolling,
-         *                  false otherwise
-         * @param focusedChildVisible Whether the currently focused view must stay visible.
-         * @return Whether the group scrolled to handle the operation
-         */
-        public boolean requestChildRectangleOnScreen(RecyclerView parent, View child, Rect rect,
-                boolean immediate,
-                boolean focusedChildVisible) {
-            int[] scrollAmount = getChildRectangleOnScreenScrollAmount(parent, child, rect,
-                    immediate);
-            int dx = scrollAmount[0];
-            int dy = scrollAmount[1];
-            if (!focusedChildVisible || isFocusedChildVisibleAfterScrolling(parent, dx, dy)) {
-                if (dx != 0 || dy != 0) {
-                    if (immediate) {
-                        parent.scrollBy(dx, dy);
-                    } else {
-                        parent.smoothScrollBy(dx, dy);
-                    }
-                    return true;
+            if (dx != 0 || dy != 0) {
+                if (immediate) {
+                    parent.scrollBy(dx, dy);
+                } else {
+                    parent.smoothScrollBy(dx, dy);
                 }
+                return true;
             }
             return false;
         }
 
         /**
-         * Returns whether the given child view is partially or fully visible within the padded
-         * bounded area of RecyclerView, depending on the input parameters.
-         * A view is partially visible if it has non-zero overlap with RV's padded bounded area.
-         * If acceptEndPointInclusion flag is set to true, it's also considered partially
-         * visible if it's located outside RV's bounds and it's hitting either RV's start or end
-         * bounds.
-         *
-         * @param child The child view to be examined.
-         * @param completelyVisible If true, the method returns true iff the child is completely
-         *                          visible. If false, the method returns true iff the child is only
-         *                          partially visible (that is it will return false if the child is
-         *                          either completely visible or out of RV's bounds).
-         * @param acceptEndPointInclusion If the view's endpoint intersection with RV's start of end
-         *                                bounds is enough to consider it partially visible,
-         *                                false otherwise.
-         * @return True if the given child is partially or fully visible, false otherwise.
-         */
-        public boolean isViewPartiallyVisible(@NonNull View child, boolean completelyVisible,
-                boolean acceptEndPointInclusion) {
-            int boundsFlag = (ViewBoundsCheck.FLAG_CVS_GT_PVS | ViewBoundsCheck.FLAG_CVS_EQ_PVS
-                    | ViewBoundsCheck.FLAG_CVE_LT_PVE | ViewBoundsCheck.FLAG_CVE_EQ_PVE);
-            boolean isViewFullyVisible = mHorizontalBoundCheck.isViewWithinBoundFlags(child,
-                    boundsFlag)
-                    && mVerticalBoundCheck.isViewWithinBoundFlags(child, boundsFlag);
-            if (completelyVisible) {
-                return isViewFullyVisible;
-            } else {
-                return !isViewFullyVisible;
-            }
-        }
-
-        /**
-         * Returns whether the currently focused child stays within RV's bounds with the given
-         * amount of scrolling.
-         * @param parent The parent RecyclerView.
-         * @param dx The scrolling in x-axis direction to be performed.
-         * @param dy The scrolling in y-axis direction to be performed.
-         * @return Whether after the given scrolling, the currently focused item in still visible
-         * (within RV's bounds).
-         */
-        private boolean isFocusedChildVisibleAfterScrolling(RecyclerView parent, int dx, int dy) {
-            final View focusedChild = parent.getFocusedChild();
-            final int parentLeft = getPaddingLeft();
-            final int parentTop = getPaddingTop();
-            final int parentRight = getWidth() - getPaddingRight();
-            final int parentBottom = getHeight() - getPaddingBottom();
-            final Rect bounds = mRecyclerView.mTempRect;
-            getDecoratedBoundsWithMargins(focusedChild, bounds);
-
-            if (bounds.left - dx >= parentRight || bounds.right - dx <= parentLeft
-                    || bounds.top - dy >= parentBottom || bounds.bottom - dy <= parentTop) {
-                return false;
-            }
-            return true;
-        }
-
-        /**
          * @deprecated Use {@link #onRequestChildFocus(RecyclerView, State, View, View)}
          */
         @Deprecated
diff --git a/v7/recyclerview/src/android/support/v7/widget/StaggeredGridLayoutManager.java b/v7/recyclerview/src/android/support/v7/widget/StaggeredGridLayoutManager.java
index 6a058af..f6c8fa3 100644
--- a/v7/recyclerview/src/android/support/v7/widget/StaggeredGridLayoutManager.java
+++ b/v7/recyclerview/src/android/support/v7/widget/StaggeredGridLayoutManager.java
@@ -2285,7 +2285,6 @@
                 return view;
             }
         }
-
         // either could not find from the desired span or prev view is full span.
         // traverse all spans
         if (preferLastSpan(layoutDir)) {
@@ -2303,44 +2302,6 @@
                 }
             }
         }
-
-        // Could not find any focusable views from any of the existing spans. Now start the search
-        // to find the best unfocusable candidate to become visible on the screen next. The search
-        // is done in the same fashion: first, check the views in the desired span and if no
-        // candidate is found, traverse the views in all the remaining spans.
-        boolean shouldSearchFromStart = !mReverseLayout == (layoutDir == LayoutState.LAYOUT_START);
-        View unfocusableCandidate = null;
-        if (!prevFocusFullSpan) {
-            unfocusableCandidate = findViewByPosition(shouldSearchFromStart
-                    ? prevFocusSpan.findFirstPartiallyVisibleItemPosition() :
-                    prevFocusSpan.findLastPartiallyVisibleItemPosition());
-            if (unfocusableCandidate != null && unfocusableCandidate != directChild) {
-                return unfocusableCandidate;
-            }
-        }
-
-        if (preferLastSpan(layoutDir)) {
-            for (int i = mSpanCount - 1; i >= 0; i--) {
-                if (i == prevFocusSpan.mIndex) {
-                    continue;
-                }
-                unfocusableCandidate = findViewByPosition(shouldSearchFromStart
-                        ? mSpans[i].findFirstPartiallyVisibleItemPosition() :
-                        mSpans[i].findLastPartiallyVisibleItemPosition());
-                if (unfocusableCandidate != null && unfocusableCandidate != directChild) {
-                    return unfocusableCandidate;
-                }
-            }
-        } else {
-            for (int i = 0; i < mSpanCount; i++) {
-                unfocusableCandidate = findViewByPosition(shouldSearchFromStart
-                        ? mSpans[i].findFirstPartiallyVisibleItemPosition() :
-                        mSpans[i].findLastPartiallyVisibleItemPosition());
-                if (unfocusableCandidate != null && unfocusableCandidate != directChild) {
-                    return unfocusableCandidate;
-                }
-            }
-        }
         return null;
     }
 
@@ -2662,12 +2623,6 @@
                     : findOneVisibleChild(0, mViews.size(), false);
         }
 
-        public int findFirstPartiallyVisibleItemPosition() {
-            return mReverseLayout
-                    ? findOnePartiallyVisibleChild(mViews.size() - 1, -1, true)
-                    : findOnePartiallyVisibleChild(0, mViews.size(), true);
-        }
-
         public int findFirstCompletelyVisibleItemPosition() {
             return mReverseLayout
                     ? findOneVisibleChild(mViews.size() - 1, -1, true)
@@ -2680,45 +2635,13 @@
                     : findOneVisibleChild(mViews.size() - 1, -1, false);
         }
 
-        public int findLastPartiallyVisibleItemPosition() {
-            return mReverseLayout
-                    ? findOnePartiallyVisibleChild(0, mViews.size(), true)
-                    : findOnePartiallyVisibleChild(mViews.size() - 1, -1, true);
-        }
-
         public int findLastCompletelyVisibleItemPosition() {
             return mReverseLayout
                     ? findOneVisibleChild(0, mViews.size(), true)
                     : findOneVisibleChild(mViews.size() - 1, -1, true);
         }
 
-        /**
-         * Returns the first view within this span that is partially or fully visible. Partially
-         * visible refers to a view that overlaps but is not fully contained within RV's padded
-         * bounded area. This view returned can be defined to have an area of overlap strictly
-         * greater than zero if acceptEndPointInclusion is false. If true, the view's endpoint
-         * inclusion is enough to consider it partially visible. The latter case can then refer to
-         * an out-of-bounds view positioned right at the top (or bottom) boundaries of RV's padded
-         * area. This is used e.g. inside
-         * {@link #onFocusSearchFailed(View, int, RecyclerView.Recycler, RecyclerView.State)} for
-         * calculating the next unfocusable child to become visible on the screen.
-         * @param fromIndex The child position index to start the search from.
-         * @param toIndex The child position index to end the search at.
-         * @param completelyVisible True if we have to only consider completely visible views,
-         *                          false otherwise.
-         * @param acceptCompletelyVisible True if we can consider both partially or fully visible
-         *                                views, false, if only a partially visible child should be
-         *                                returned.
-         * @param acceptEndPointInclusion If the view's endpoint intersection with RV's padded
-         *                                bounded area is enough to consider it partially visible,
-         *                                false otherwise
-         * @return The adapter position of the first view that's either partially or fully visible.
-         * {@link RecyclerView#NO_POSITION} if no such view is found.
-         */
-        int findOnePartiallyOrCompletelyVisibleChild(int fromIndex, int toIndex,
-                boolean completelyVisible,
-                boolean acceptCompletelyVisible,
-                boolean acceptEndPointInclusion) {
+        int findOneVisibleChild(int fromIndex, int toIndex, boolean completelyVisible) {
             final int start = mPrimaryOrientation.getStartAfterPadding();
             final int end = mPrimaryOrientation.getEndAfterPadding();
             final int next = toIndex > fromIndex ? 1 : -1;
@@ -2726,22 +2649,12 @@
                 final View child = mViews.get(i);
                 final int childStart = mPrimaryOrientation.getDecoratedStart(child);
                 final int childEnd = mPrimaryOrientation.getDecoratedEnd(child);
-                boolean childStartInclusion = acceptEndPointInclusion ? (childStart <= end)
-                        : (childStart < end);
-                boolean childEndInclusion = acceptEndPointInclusion ? (childEnd >= start)
-                        : (childEnd > start);
-                if (childStartInclusion && childEndInclusion) {
-                    if (completelyVisible && acceptCompletelyVisible) {
-                        // the child has to be completely visible to be returned.
+                if (childStart < end && childEnd > start) {
+                    if (completelyVisible) {
                         if (childStart >= start && childEnd <= end) {
                             return getPosition(child);
                         }
-                    } else if (acceptCompletelyVisible) {
-                        // can return either a partially or completely visible child.
-                        return getPosition(child);
-                    } else if (childStart < start || childEnd > end) {
-                        // should return a partially visible child if exists and a completely
-                        // visible child is not acceptable in this case.
+                    } else {
                         return getPosition(child);
                     }
                 }
@@ -2749,17 +2662,6 @@
             return NO_POSITION;
         }
 
-        int findOneVisibleChild(int fromIndex, int toIndex, boolean completelyVisible) {
-            return findOnePartiallyOrCompletelyVisibleChild(fromIndex, toIndex, completelyVisible,
-                    true, false);
-        }
-
-        int findOnePartiallyVisibleChild(int fromIndex, int toIndex,
-                boolean acceptEndPointInclusion) {
-            return findOnePartiallyOrCompletelyVisibleChild(fromIndex, toIndex, false, false,
-                    acceptEndPointInclusion);
-        }
-
         /**
          * Depending on the layout direction, returns the View that is after the given position.
          */
@@ -2769,11 +2671,8 @@
                 final int limit = mViews.size();
                 for (int i = 0; i < limit; i++) {
                     final View view = mViews.get(i);
-                    if ((mReverseLayout && getPosition(view) <= referenceChildPosition)
-                            || (!mReverseLayout && getPosition(view) >= referenceChildPosition)) {
-                        break;
-                    }
-                    if (view.isFocusable()) {
+                    if (view.isFocusable() &&
+                            (getPosition(view) > referenceChildPosition == mReverseLayout) ) {
                         candidate = view;
                     } else {
                         break;
@@ -2782,11 +2681,8 @@
             } else {
                 for (int i = mViews.size() - 1; i >= 0; i--) {
                     final View view = mViews.get(i);
-                    if ((mReverseLayout && getPosition(view) >= referenceChildPosition)
-                            || (!mReverseLayout && getPosition(view) <= referenceChildPosition)) {
-                        break;
-                    }
-                    if (view.isFocusable()) {
+                    if (view.isFocusable() &&
+                            (getPosition(view) > referenceChildPosition == !mReverseLayout)) {
                         candidate = view;
                     } else {
                         break;
diff --git a/v7/recyclerview/src/android/support/v7/widget/ViewBoundsCheck.java b/v7/recyclerview/src/android/support/v7/widget/ViewBoundsCheck.java
deleted file mode 100644
index 8a4f89c..0000000
--- a/v7/recyclerview/src/android/support/v7/widget/ViewBoundsCheck.java
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * Copyright (C) 2017 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.v7.widget;
-
-import android.support.annotation.IntDef;
-import android.view.View;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * A utility class used to check the boundaries of a given view within its parent view based on
- * a set of boundary flags.
- */
-class ViewBoundsCheck {
-
-    static final int GT = 1 << 0;
-    static final int EQ = 1 << 1;
-    static final int LT = 1 << 2;
-
-
-    static final int CVS_PVS_POS = 0;
-    /**
-     * The child view's start should be strictly greater than parent view's start.
-     */
-    static final int FLAG_CVS_GT_PVS = GT << CVS_PVS_POS;
-
-    /**
-     * The child view's start can be equal to its parent view's start. This flag follows with GT
-     * or LT indicating greater (less) than or equal relation.
-     */
-    static final int FLAG_CVS_EQ_PVS = EQ << CVS_PVS_POS;
-
-    /**
-     * The child view's start should be strictly less than parent view's start.
-     */
-    static final int FLAG_CVS_LT_PVS = LT << CVS_PVS_POS;
-
-
-    static final int CVS_PVE_POS = 4;
-    /**
-     * The child view's start should be strictly greater than parent view's end.
-     */
-    static final int FLAG_CVS_GT_PVE = GT << CVS_PVE_POS;
-
-    /**
-     * The child view's start can be equal to its parent view's end. This flag follows with GT
-     * or LT indicating greater (less) than or equal relation.
-     */
-    static final int FLAG_CVS_EQ_PVE = EQ << CVS_PVE_POS;
-
-    /**
-     * The child view's start should be strictly less than parent view's end.
-     */
-    static final int FLAG_CVS_LT_PVE = LT << CVS_PVE_POS;
-
-
-    static final int CVE_PVS_POS = 8;
-    /**
-     * The child view's end should be strictly greater than parent view's start.
-     */
-    static final int FLAG_CVE_GT_PVS = GT << CVE_PVS_POS;
-
-    /**
-     * The child view's end can be equal to its parent view's start. This flag follows with GT
-     * or LT indicating greater (less) than or equal relation.
-     */
-    static final int FLAG_CVE_EQ_PVS = EQ << CVE_PVS_POS;
-
-    /**
-     * The child view's end should be strictly less than parent view's start.
-     */
-    static final int FLAG_CVE_LT_PVS = LT << CVE_PVS_POS;
-
-
-    static final int CVE_PVE_POS = 12;
-    /**
-     * The child view's end should be strictly greater than parent view's end.
-     */
-    static final int FLAG_CVE_GT_PVE = GT << CVE_PVE_POS;
-
-    /**
-     * The child view's end can be equal to its parent view's end. This flag follows with GT
-     * or LT indicating greater (less) than or equal relation.
-     */
-    static final int FLAG_CVE_EQ_PVE = EQ << CVE_PVE_POS;
-
-    /**
-     * The child view's end should be strictly less than parent view's end.
-     */
-    static final int FLAG_CVE_LT_PVE = LT << CVE_PVE_POS;
-
-    static final int MASK = GT | EQ | LT;
-
-    final Callback mCallback;
-    BoundFlags mBoundFlags;
-    /**
-     * The set of flags that can be passed for checking the view boundary conditions.
-     * CVS in the flag name indicates the child view, and PV indicates the parent view.\
-     * The following S, E indicate a view's start and end points, respectively.
-     * GT and LT indicate a strictly greater and less than relationship.
-     * Greater than or equal (or less than or equal) can be specified by setting both GT and EQ (or
-     * LT and EQ) flags.
-     * For instance, setting both {@link #FLAG_CVS_GT_PVS} and {@link #FLAG_CVS_EQ_PVS} indicate the
-     * child view's start should be greater than or equal to its parent start.
-     */
-    @IntDef(flag = true, value = {
-            FLAG_CVS_GT_PVS, FLAG_CVS_EQ_PVS, FLAG_CVS_LT_PVS,
-            FLAG_CVS_GT_PVE, FLAG_CVS_EQ_PVE, FLAG_CVS_LT_PVE,
-            FLAG_CVE_GT_PVS, FLAG_CVE_EQ_PVS, FLAG_CVE_LT_PVS,
-            FLAG_CVE_EQ_PVE, FLAG_CVE_EQ_PVE, FLAG_CVE_LT_PVE
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface ViewBounds {}
-
-    ViewBoundsCheck(Callback callback) {
-        mCallback = callback;
-        mBoundFlags = new BoundFlags();
-    }
-
-    static class BoundFlags {
-        int mBoundFlags = 0;
-        int mRvStart, mRvEnd, mChildStart, mChildEnd;
-
-        void setBounds(int rvStart, int rvEnd, int childStart, int childEnd) {
-            mRvStart = rvStart;
-            mRvEnd = rvEnd;
-            mChildStart = childStart;
-            mChildEnd = childEnd;
-        }
-
-        void setFlags(@ViewBounds int flags, int mask) {
-            mBoundFlags = (mBoundFlags & ~mask) | (flags & mask);
-        }
-
-        void addFlags(@ViewBounds int flags) {
-            mBoundFlags |= flags;
-        }
-
-        void resetFlags() {
-            mBoundFlags = 0;
-        }
-
-        int compare(int x, int y) {
-            if (x > y) {
-                return GT;
-            }
-            if (x == y) {
-                return EQ;
-            }
-            return LT;
-        }
-
-        boolean boundsMatch() {
-            if ((mBoundFlags & (MASK << CVS_PVS_POS)) != 0) {
-                if ((mBoundFlags & (compare(mChildStart, mRvStart) << CVS_PVS_POS)) == 0) {
-                    return false;
-                }
-            }
-
-            if ((mBoundFlags & (MASK << CVS_PVE_POS)) != 0) {
-                if ((mBoundFlags & (compare(mChildStart, mRvEnd) << CVS_PVE_POS)) == 0) {
-                    return false;
-                }
-            }
-
-            if ((mBoundFlags & (MASK << CVE_PVS_POS)) != 0) {
-                if ((mBoundFlags & (compare(mChildEnd, mRvStart) << CVE_PVS_POS)) == 0) {
-                    return false;
-                }
-            }
-
-            if ((mBoundFlags & (MASK << CVE_PVE_POS)) != 0) {
-                if ((mBoundFlags & (compare(mChildEnd, mRvEnd) << CVE_PVE_POS)) == 0) {
-                    return false;
-                }
-            }
-            return true;
-        }
-    };
-
-    /**
-     * Returns the first view starting from fromIndex to toIndex in views whose bounds lie within
-     * its parent bounds based on the provided preferredBoundFlags. If no match is found based on
-     * the preferred flags, and a nonzero acceptableBoundFlags is specified, the last view whose
-     * bounds lie within its parent view based on the acceptableBoundFlags is returned. If no such
-     * view is found based on either of these two flags, null is returned.
-     * @param fromIndex The view position index to start the search from.
-     * @param toIndex The view position index to end the search at.
-     * @param preferredBoundFlags The flags indicating the preferred match. Once a match is found
-     *                            based on this flag, that view is returned instantly.
-     * @param acceptableBoundFlags The flags indicating the acceptable match if no preferred match
-     *                             is found. If so, and if acceptableBoundFlags is non-zero, the
-     *                             last matching acceptable view is returned. Otherwise, null is
-     *                             returned.
-     * @return The first view that satisfies acceptableBoundFlags or the last view satisfying
-     * acceptableBoundFlags boundary conditions.
-     */
-    View findOneViewWithinBoundFlags(int fromIndex, int toIndex,
-            @ViewBounds int preferredBoundFlags,
-            @ViewBounds int acceptableBoundFlags) {
-        final int start = mCallback.getParentStart();
-        final int end = mCallback.getParentEnd();
-        final int next = toIndex > fromIndex ? 1 : -1;
-        View acceptableMatch = null;
-        for (int i = fromIndex; i != toIndex; i += next) {
-            final View child = mCallback.getChildAt(i);
-            final int childStart = mCallback.getChildStart(child);
-            final int childEnd = mCallback.getChildEnd(child);
-            mBoundFlags.setBounds(start, end, childStart, childEnd);
-            if (preferredBoundFlags != 0) {
-                mBoundFlags.resetFlags();
-                mBoundFlags.addFlags(preferredBoundFlags);
-                if (mBoundFlags.boundsMatch()) {
-                    // found a perfect match
-                    return child;
-                }
-            }
-            if (acceptableBoundFlags != 0) {
-                mBoundFlags.resetFlags();
-                mBoundFlags.addFlags(acceptableBoundFlags);
-                if (mBoundFlags.boundsMatch()) {
-                    acceptableMatch = child;
-                }
-            }
-        }
-        return acceptableMatch;
-    }
-
-    /**
-     * Returns whether the specified view lies within the boundary condition of its parent view.
-     * @param child The child view to be checked.
-     * @param boundsFlags The flag against which the child view and parent view are matched.
-     * @return True if the view meets the boundsFlag, false otherwise.
-     */
-    boolean isViewWithinBoundFlags(View child, @ViewBounds int boundsFlags) {
-        mBoundFlags.setBounds(mCallback.getParentStart(), mCallback.getParentEnd(),
-                mCallback.getChildStart(child), mCallback.getChildEnd(child));
-        if (boundsFlags != 0) {
-            mBoundFlags.resetFlags();
-            mBoundFlags.addFlags(boundsFlags);
-            return mBoundFlags.boundsMatch();
-        }
-        return false;
-    }
-
-    /**
-     * Callback provided by the user of this class in order to retrieve information about child and
-     * parent boundaries.
-     */
-    interface Callback {
-        int getChildCount();
-        View getParent();
-        View getChildAt(int index);
-        int getParentStart();
-        int getParentEnd();
-        int getChildStart(View view);
-        int getChildEnd(View view);
-    }
-}
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/BaseRecyclerViewInstrumentationTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/BaseRecyclerViewInstrumentationTest.java
index 5f7bf48..7185cbc 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/BaseRecyclerViewInstrumentationTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/BaseRecyclerViewInstrumentationTest.java
@@ -150,11 +150,7 @@
         });
     }
 
-    public View focusSearch(final View focused, final int direction) throws Throwable {
-        return focusSearch(focused, direction, false);
-    }
-
-    public View focusSearch(final View focused, final int direction, boolean waitForScroll)
+    public View focusSearch(final View focused, final int direction)
             throws Throwable {
         final View[] result = new View[1];
         mActivityRule.runOnUiThread(new Runnable() {
@@ -167,9 +163,6 @@
                 result[0] = view;
             }
         });
-        if (waitForScroll && (result[0] != null)) {
-            waitForIdleScroll(mRecyclerView);
-        }
         return result[0];
     }
 
@@ -487,7 +480,7 @@
         });
         getInstrumentation().waitForIdleSync();
         assertThat("should be able to scroll in 10 seconds", !assertArrival ||
-                        viewAdded.await(10, TimeUnit.SECONDS),
+                viewAdded.await(10, TimeUnit.SECONDS),
                 CoreMatchers.is(true));
         waitForIdleScroll(mRecyclerView);
         if (mDebug) {
@@ -555,7 +548,6 @@
             }
         }
     }
-
     public class TestLayoutManager extends RecyclerView.LayoutManager {
         int mScrollVerticallyAmount;
         int mScrollHorizontallyAmount;
@@ -1191,60 +1183,4 @@
             validateRemaining(recyclerView);
         }
     }
-
-    /**
-     * Returns whether a child of RecyclerView is partially in bound. A child is
-     * partially in-bounds if it's either fully or partially visible on the screen.
-     * @param parent The RecyclerView holding the child.
-     * @param child The child view to be checked whether is partially (or fully) within RV's bounds.
-     * @return True if the child view is partially (or fully) visible; false otherwise.
-     */
-    public static boolean isViewPartiallyInBound(RecyclerView parent, View child) {
-        if (child == null) {
-            return false;
-        }
-        final int parentLeft = parent.getPaddingLeft();
-        final int parentTop = parent.getPaddingTop();
-        final int parentRight = parent.getWidth() - parent.getPaddingRight();
-        final int parentBottom = parent.getHeight() - parent.getPaddingBottom();
-
-        final int childLeft = child.getLeft() - child.getScrollX();
-        final int childTop = child.getTop() - child.getScrollY();
-        final int childRight = child.getRight() - child.getScrollX();
-        final int childBottom = child.getBottom() - child.getScrollY();
-
-        if (childLeft >= parentRight || childRight <= parentLeft
-                || childTop >= parentBottom || childBottom <= parentTop) {
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Returns whether a child of RecyclerView is fully in-bounds, that is it's fully visible
-     * on the screen.
-     * @param parent The RecyclerView holding the child.
-     * @param child The child view to be checked whether is fully within RV's bounds.
-     * @return True if the child view is fully visible; false otherwise.
-     */
-    public boolean isViewFullyInBound(RecyclerView parent, View child) {
-        if (child == null) {
-            return false;
-        }
-        final int parentLeft = parent.getPaddingLeft();
-        final int parentTop = parent.getPaddingTop();
-        final int parentRight = parent.getWidth() - parent.getPaddingRight();
-        final int parentBottom = parent.getHeight() - parent.getPaddingBottom();
-
-        final int childLeft = child.getLeft() - child.getScrollX();
-        final int childTop = child.getTop() - child.getScrollY();
-        final int childRight = child.getRight() - child.getScrollX();
-        final int childBottom = child.getBottom() - child.getScrollY();
-
-        if (childLeft >= parentLeft && childRight <= parentRight
-                && childTop >= parentTop && childBottom <= parentBottom) {
-            return true;
-        }
-        return false;
-    }
 }
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/BaseStaggeredGridLayoutManagerTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/BaseStaggeredGridLayoutManagerTest.java
index 776b10d..fff64b3 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/BaseStaggeredGridLayoutManagerTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/BaseStaggeredGridLayoutManagerTest.java
@@ -14,13 +14,9 @@
 
 import static java.util.concurrent.TimeUnit.SECONDS;
 
-import android.graphics.Color;
 import android.graphics.Rect;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.StateListDrawable;
 import android.support.annotation.Nullable;
 import android.util.Log;
-import android.util.StateSet;
 import android.view.View;
 import android.view.ViewGroup;
 
@@ -911,13 +907,7 @@
                 lp.rightMargin = 7;
                 lp.bottomMargin = 9;
             }
-            // Good to have colors for debugging
-            StateListDrawable stl = new StateListDrawable();
-            stl.addState(new int[]{android.R.attr.state_focused},
-                    new ColorDrawable(Color.RED));
-            stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
-            //noinspection deprecation using this for kitkat tests
-            holder.itemView.setBackgroundDrawable(stl);
+
             if (mOnBindCallback != null) {
                 mOnBindCallback.onBoundItem(holder, position);
             }
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/GridLayoutManagerTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/GridLayoutManagerTest.java
index 5ebebfe..5c2692a 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/GridLayoutManagerTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/GridLayoutManagerTest.java
@@ -19,7 +19,6 @@
 import static android.support.v7.widget.LinearLayoutManager.HORIZONTAL;
 import static android.support.v7.widget.LinearLayoutManager.VERTICAL;
 
-import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -168,367 +167,6 @@
         }
     }
 
-
-    @Test
-    public void topUnfocusableViewsVisibility() throws Throwable {
-        // The maximum number of rows that can be fully in-bounds of RV.
-        final int visibleRowCount = 5;
-        final int spanCount = 3;
-        final int consecutiveFocusableRowsCount = 4;
-        final int consecutiveUnFocusableRowsCount = 8;
-        final int itemCount = (consecutiveFocusableRowsCount + consecutiveUnFocusableRowsCount)
-                * spanCount;
-
-        final RecyclerView recyclerView = setupBasic(new Config(spanCount, itemCount)
-                        .reverseLayout(true),
-                new GridTestAdapter(itemCount, 1) {
-                    RecyclerView mAttachedRv;
-
-                    @Override
-                    public TestViewHolder onCreateViewHolder(ViewGroup parent,
-                            int viewType) {
-                        TestViewHolder testViewHolder = super.onCreateViewHolder(parent, viewType);
-                        // Good to have colors for debugging
-                        StateListDrawable stl = new StateListDrawable();
-                        stl.addState(new int[]{android.R.attr.state_focused},
-                                new ColorDrawable(Color.RED));
-                        stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
-                        //noinspection deprecation using this for kitkat tests
-                        testViewHolder.itemView.setBackgroundDrawable(stl);
-                        return testViewHolder;
-                    }
-
-                    @Override
-                    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
-                        mAttachedRv = recyclerView;
-                    }
-
-                    @Override
-                    public void onBindViewHolder(TestViewHolder holder,
-                            int position) {
-                        super.onBindViewHolder(holder, position);
-                        if (position < spanCount * consecutiveFocusableRowsCount) {
-                            holder.itemView.setFocusable(true);
-                            holder.itemView.setFocusableInTouchMode(true);
-                        } else {
-                            holder.itemView.setFocusable(false);
-                            holder.itemView.setFocusableInTouchMode(false);
-                        }
-                        holder.itemView.setMinimumHeight(mAttachedRv.getHeight() / visibleRowCount);
-                    }
-                });
-        waitForFirstLayout(recyclerView);
-
-        // adapter position of the currently focused item.
-        int focusIndex = 1;
-        RecyclerView.ViewHolder toFocus = recyclerView.findViewHolderForAdapterPosition(focusIndex);
-        View viewToFocus = toFocus.itemView;
-        assertTrue(requestFocus(viewToFocus, true));
-        assertSame(viewToFocus, recyclerView.getFocusedChild());
-
-        // adapter position of the item (whether focusable or not) that just becomes fully
-        // visible after focusSearch.
-        int visibleIndex = focusIndex;
-        // The VH of the above adapter position
-        RecyclerView.ViewHolder toVisible = null;
-
-        int maxFocusIndex = (consecutiveFocusableRowsCount - 1) * spanCount + focusIndex;
-        int maxVisibleIndex = (consecutiveFocusableRowsCount + visibleRowCount - 2)
-                * spanCount + visibleIndex;
-
-        // Navigate up through the focusable and unfocusable rows. The focusable rows should
-        // become focused one by one until hitting the last focusable row, at which point,
-        // unfocusable rows should become visible on the screen until the currently focused row
-        // stays on the screen.
-        int pos = focusIndex + spanCount;
-        while (pos < itemCount) {
-            focusSearch(recyclerView.getFocusedChild(), View.FOCUS_UP, true);
-            waitForIdleScroll(recyclerView);
-            focusIndex = Math.min(maxFocusIndex, (focusIndex + spanCount));
-            toFocus = recyclerView.findViewHolderForAdapterPosition(focusIndex);
-            visibleIndex = Math.min(maxVisibleIndex, (visibleIndex + spanCount));
-            toVisible = recyclerView.findViewHolderForAdapterPosition(visibleIndex);
-
-            assertThat("Child at position " + focusIndex + " should be focused",
-                    toFocus.itemView.hasFocus(), is(true));
-            assertTrue("Focused child should be at least partially visible.",
-                    isViewPartiallyInBound(recyclerView, toFocus.itemView));
-            assertTrue("Child view at adapter pos " + visibleIndex + " should be fully visible.",
-                    isViewFullyInBound(recyclerView, toVisible.itemView));
-            pos += spanCount;
-        }
-    }
-
-    @Test
-    public void bottomUnfocusableViewsVisibility() throws Throwable {
-        // The maximum number of rows that can be fully in-bounds of RV.
-        final int visibleRowCount = 5;
-        final int spanCount = 3;
-        final int consecutiveFocusableRowsCount = 4;
-        final int consecutiveUnFocusableRowsCount = 8;
-        final int itemCount = (consecutiveFocusableRowsCount + consecutiveUnFocusableRowsCount)
-                * spanCount;
-
-        final RecyclerView recyclerView = setupBasic(new Config(spanCount, itemCount)
-                        .reverseLayout(false),
-                new GridTestAdapter(itemCount, 1) {
-                    RecyclerView mAttachedRv;
-
-                    @Override
-                    public TestViewHolder onCreateViewHolder(ViewGroup parent,
-                            int viewType) {
-                        TestViewHolder testViewHolder = super.onCreateViewHolder(parent, viewType);
-                        // Good to have colors for debugging
-                        StateListDrawable stl = new StateListDrawable();
-                        stl.addState(new int[]{android.R.attr.state_focused},
-                                new ColorDrawable(Color.RED));
-                        stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
-                        //noinspection deprecation using this for kitkat tests
-                        testViewHolder.itemView.setBackgroundDrawable(stl);
-                        return testViewHolder;
-                    }
-
-                    @Override
-                    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
-                        mAttachedRv = recyclerView;
-                    }
-
-                    @Override
-                    public void onBindViewHolder(TestViewHolder holder,
-                            int position) {
-                        super.onBindViewHolder(holder, position);
-                        if (position < spanCount * consecutiveFocusableRowsCount) {
-                            holder.itemView.setFocusable(true);
-                            holder.itemView.setFocusableInTouchMode(true);
-                        } else {
-                            holder.itemView.setFocusable(false);
-                            holder.itemView.setFocusableInTouchMode(false);
-                        }
-                        holder.itemView.setMinimumHeight(mAttachedRv.getHeight() / visibleRowCount);
-                    }
-                });
-        waitForFirstLayout(recyclerView);
-
-        // adapter position of the currently focused item.
-        int focusIndex = 1;
-        RecyclerView.ViewHolder toFocus = recyclerView.findViewHolderForAdapterPosition(focusIndex);
-        View viewToFocus = toFocus.itemView;
-        assertTrue(requestFocus(viewToFocus, true));
-        assertSame(viewToFocus, recyclerView.getFocusedChild());
-
-        // adapter position of the item (whether focusable or not) that just becomes fully
-        // visible after focusSearch.
-        int visibleIndex = focusIndex;
-        // The VH of the above adapter position
-        RecyclerView.ViewHolder toVisible = null;
-
-        int maxFocusIndex = (consecutiveFocusableRowsCount - 1) * spanCount + focusIndex;
-        int maxVisibleIndex = (consecutiveFocusableRowsCount + visibleRowCount - 2)
-                * spanCount + visibleIndex;
-
-        // Navigate down through the focusable and unfocusable rows. The focusable rows should
-        // become focused one by one until hitting the last focusable row, at which point,
-        // unfocusable rows should become visible on the screen until the currently focused row
-        // stays on the screen.
-        int pos = focusIndex + spanCount;
-        while (pos < itemCount) {
-            focusSearch(recyclerView.getFocusedChild(), View.FOCUS_DOWN, true);
-            waitForIdleScroll(recyclerView);
-            focusIndex = Math.min(maxFocusIndex, (focusIndex + spanCount));
-            toFocus = recyclerView.findViewHolderForAdapterPosition(focusIndex);
-            visibleIndex = Math.min(maxVisibleIndex, (visibleIndex + spanCount));
-            toVisible = recyclerView.findViewHolderForAdapterPosition(visibleIndex);
-
-            assertThat("Child at position " + focusIndex + " should be focused",
-                    toFocus.itemView.hasFocus(), is(true));
-            assertTrue("Focused child should be at least partially visible.",
-                    isViewPartiallyInBound(recyclerView, toFocus.itemView));
-            assertTrue("Child view at adapter pos " + visibleIndex + " should be fully visible.",
-                    isViewFullyInBound(recyclerView, toVisible.itemView));
-            pos += spanCount;
-        }
-    }
-
-    @Test
-    public void leftUnfocusableViewsVisibility() throws Throwable {
-        // The maximum number of columns that can be fully in-bounds of RV.
-        final int visibleColCount = 5;
-        final int spanCount = 3;
-        final int consecutiveFocusableColsCount = 4;
-        final int consecutiveUnFocusableColsCount = 8;
-        final int itemCount = (consecutiveFocusableColsCount + consecutiveUnFocusableColsCount)
-                * spanCount;
-
-        final RecyclerView recyclerView = setupBasic(new Config(spanCount, itemCount)
-                        .orientation(HORIZONTAL).reverseLayout(true),
-                new GridTestAdapter(itemCount, 1) {
-                    RecyclerView mAttachedRv;
-
-                    @Override
-                    public TestViewHolder onCreateViewHolder(ViewGroup parent,
-                            int viewType) {
-                        TestViewHolder testViewHolder = super.onCreateViewHolder(parent, viewType);
-                        // Good to have colors for debugging
-                        StateListDrawable stl = new StateListDrawable();
-                        stl.addState(new int[]{android.R.attr.state_focused},
-                                new ColorDrawable(Color.RED));
-                        stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
-                        //noinspection deprecation using this for kitkat tests
-                        testViewHolder.itemView.setBackgroundDrawable(stl);
-                        return testViewHolder;
-                    }
-
-                    @Override
-                    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
-                        mAttachedRv = recyclerView;
-                    }
-
-                    @Override
-                    public void onBindViewHolder(TestViewHolder holder,
-                            int position) {
-                        super.onBindViewHolder(holder, position);
-                        if (position < spanCount * consecutiveFocusableColsCount) {
-                            holder.itemView.setFocusable(true);
-                            holder.itemView.setFocusableInTouchMode(true);
-                        } else {
-                            holder.itemView.setFocusable(false);
-                            holder.itemView.setFocusableInTouchMode(false);
-                        }
-                        holder.itemView.setMinimumWidth(mAttachedRv.getWidth() / visibleColCount);
-                    }
-                });
-        waitForFirstLayout(recyclerView);
-
-        // adapter position of the currently focused item.
-        int focusIndex = 1;
-        RecyclerView.ViewHolder toFocus = recyclerView.findViewHolderForAdapterPosition(focusIndex);
-        View viewToFocus = toFocus.itemView;
-        assertTrue(requestFocus(viewToFocus, true));
-        assertSame(viewToFocus, recyclerView.getFocusedChild());
-
-        // adapter position of the item (whether focusable or not) that just becomes fully
-        // visible after focusSearch.
-        int visibleIndex = focusIndex;
-        // The VH of the above adapter position
-        RecyclerView.ViewHolder toVisible = null;
-
-        int maxFocusIndex = (consecutiveFocusableColsCount - 1) * spanCount + focusIndex;
-        int maxVisibleIndex = (consecutiveFocusableColsCount + visibleColCount - 2)
-                * spanCount + visibleIndex;
-
-        // Navigate left through the focusable and unfocusable columns. The focusable columns should
-        // become focused one by one until hitting the last focusable column, at which point,
-        // unfocusable columns should become visible on the screen until the currently focused
-        // column stays on the screen.
-        int pos = focusIndex + spanCount;
-        while (pos < itemCount) {
-            focusSearch(recyclerView.getFocusedChild(), View.FOCUS_LEFT, true);
-            waitForIdleScroll(recyclerView);
-            focusIndex = Math.min(maxFocusIndex, (focusIndex + spanCount));
-            toFocus = recyclerView.findViewHolderForAdapterPosition(focusIndex);
-            visibleIndex = Math.min(maxVisibleIndex, (visibleIndex + spanCount));
-            toVisible = recyclerView.findViewHolderForAdapterPosition(visibleIndex);
-
-            assertThat("Child at position " + focusIndex + " should be focused",
-                    toFocus.itemView.hasFocus(), is(true));
-            assertTrue("Focused child should be at least partially visible.",
-                    isViewPartiallyInBound(recyclerView, toFocus.itemView));
-            assertTrue("Child view at adapter pos " + visibleIndex + " should be fully visible.",
-                    isViewFullyInBound(recyclerView, toVisible.itemView));
-            pos += spanCount;
-        }
-    }
-
-    @Test
-    public void rightUnfocusableViewsVisibility() throws Throwable {
-        // The maximum number of columns that can be fully in-bounds of RV.
-        final int visibleColCount = 5;
-        final int spanCount = 3;
-        final int consecutiveFocusableColsCount = 4;
-        final int consecutiveUnFocusableColsCount = 8;
-        final int itemCount = (consecutiveFocusableColsCount + consecutiveUnFocusableColsCount)
-                * spanCount;
-
-        final RecyclerView recyclerView = setupBasic(new Config(spanCount, itemCount)
-                        .orientation(HORIZONTAL).reverseLayout(false),
-                new GridTestAdapter(itemCount, 1) {
-                    RecyclerView mAttachedRv;
-
-                    @Override
-                    public TestViewHolder onCreateViewHolder(ViewGroup parent,
-                            int viewType) {
-                        TestViewHolder testViewHolder = super.onCreateViewHolder(parent, viewType);
-                        // Good to have colors for debugging
-                        StateListDrawable stl = new StateListDrawable();
-                        stl.addState(new int[]{android.R.attr.state_focused},
-                                new ColorDrawable(Color.RED));
-                        stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
-                        //noinspection deprecation using this for kitkat tests
-                        testViewHolder.itemView.setBackgroundDrawable(stl);
-                        return testViewHolder;
-                    }
-
-                    @Override
-                    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
-                        mAttachedRv = recyclerView;
-                    }
-
-                    @Override
-                    public void onBindViewHolder(TestViewHolder holder,
-                            int position) {
-                        super.onBindViewHolder(holder, position);
-                        if (position < spanCount * consecutiveFocusableColsCount) {
-                            holder.itemView.setFocusable(true);
-                            holder.itemView.setFocusableInTouchMode(true);
-                        } else {
-                            holder.itemView.setFocusable(false);
-                            holder.itemView.setFocusableInTouchMode(false);
-                        }
-                        holder.itemView.setMinimumWidth(mAttachedRv.getWidth() / visibleColCount);
-                    }
-                });
-        waitForFirstLayout(recyclerView);
-
-        // adapter position of the currently focused item.
-        int focusIndex = 1;
-        RecyclerView.ViewHolder toFocus = recyclerView.findViewHolderForAdapterPosition(focusIndex);
-        View viewToFocus = toFocus.itemView;
-        assertTrue(requestFocus(viewToFocus, true));
-        assertSame(viewToFocus, recyclerView.getFocusedChild());
-
-        // adapter position of the item (whether focusable or not) that just becomes fully
-        // visible after focusSearch.
-        int visibleIndex = focusIndex;
-        // The VH of the above adapter position
-        RecyclerView.ViewHolder toVisible = null;
-
-        int maxFocusIndex = (consecutiveFocusableColsCount - 1) * spanCount + focusIndex;
-        int maxVisibleIndex = (consecutiveFocusableColsCount + visibleColCount - 2)
-                * spanCount + visibleIndex;
-
-        // Navigate right through the focusable and unfocusable columns. The focusable columns
-        // should become focused one by one until hitting the last focusable column, at which point,
-        // unfocusable columns should become visible on the screen until the currently focused
-        // column stays on the screen.
-        int pos = focusIndex + spanCount;
-        while (pos < itemCount) {
-            focusSearch(recyclerView.getFocusedChild(), View.FOCUS_RIGHT, true);
-            waitForIdleScroll(recyclerView);
-            focusIndex = Math.min(maxFocusIndex, (focusIndex + spanCount));
-            toFocus = recyclerView.findViewHolderForAdapterPosition(focusIndex);
-            visibleIndex = Math.min(maxVisibleIndex, (visibleIndex + spanCount));
-            toVisible = recyclerView.findViewHolderForAdapterPosition(visibleIndex);
-
-            assertThat("Child at position " + focusIndex + " should be focused",
-                    toFocus.itemView.hasFocus(), is(true));
-            assertTrue("Focused child should be at least partially visible.",
-                    isViewPartiallyInBound(recyclerView, toFocus.itemView));
-            assertTrue("Child view at adapter pos " + visibleIndex + " should be fully visible.",
-                    isViewFullyInBound(recyclerView, toVisible.itemView));
-            pos += spanCount;
-        }
-    }
-
     @UiThreadTest
     @Test
     public void scrollWithoutLayout() throws Throwable {
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/LinearLayoutManagerTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/LinearLayoutManagerTest.java
index 067689c..5f61ea7 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/LinearLayoutManagerTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/LinearLayoutManagerTest.java
@@ -19,22 +19,16 @@
 import static android.support.v7.widget.LinearLayoutManager.HORIZONTAL;
 import static android.support.v7.widget.LinearLayoutManager.VERTICAL;
 
-import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 
-import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.StateListDrawable;
-import android.support.test.filters.LargeTest;
+import android.support.test.filters.MediumTest;
 import android.support.v4.view.AccessibilityDelegateCompat;
 import android.support.v4.view.accessibility.AccessibilityEventCompat;
 import android.support.v4.view.accessibility.AccessibilityRecordCompat;
 import android.util.Log;
-import android.util.StateSet;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
@@ -45,7 +39,6 @@
 import java.util.List;
 import java.util.concurrent.atomic.AtomicInteger;
 
-
 /**
  * Includes tests for {@link LinearLayoutManager}.
  * <p>
@@ -53,352 +46,10 @@
  * and stability of LinearLayoutManager in response to different events (state change, scrolling
  * etc) where it is very hard to do manual testing.
  */
-@LargeTest
+@MediumTest
 public class LinearLayoutManagerTest extends BaseLinearLayoutManagerTest {
 
     @Test
-    public void topUnfocusableViewsVisibility() throws Throwable {
-        // The maximum number of child views that can be visible at any time.
-        final int visibleChildCount = 5;
-        final int consecutiveFocusablesCount = 2;
-        final int consecutiveUnFocusablesCount = 18;
-        final TestAdapter adapter = new TestAdapter(
-                consecutiveFocusablesCount + consecutiveUnFocusablesCount) {
-            RecyclerView mAttachedRv;
-
-            @Override
-            public TestViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
-                TestViewHolder testViewHolder = super.onCreateViewHolder(parent, viewType);
-                // Good to have colors for debugging
-                StateListDrawable stl = new StateListDrawable();
-                stl.addState(new int[]{android.R.attr.state_focused},
-                        new ColorDrawable(Color.RED));
-                stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
-                //noinspection deprecation used to support kitkat tests
-                testViewHolder.itemView.setBackgroundDrawable(stl);
-                return testViewHolder;
-            }
-
-            @Override
-            public void onAttachedToRecyclerView(RecyclerView recyclerView) {
-                mAttachedRv = recyclerView;
-            }
-
-            @Override
-            public void onBindViewHolder(TestViewHolder holder,
-                    int position) {
-                super.onBindViewHolder(holder, position);
-                if (position < consecutiveFocusablesCount) {
-                    holder.itemView.setFocusable(true);
-                    holder.itemView.setFocusableInTouchMode(true);
-                } else {
-                    holder.itemView.setFocusable(false);
-                    holder.itemView.setFocusableInTouchMode(false);
-                }
-                // This height ensures that some portion of #visibleChildCount'th child is
-                // off-bounds, creating more interesting test scenario.
-                holder.itemView.setMinimumHeight((mAttachedRv.getHeight()
-                        + mAttachedRv.getHeight() / (2 * visibleChildCount)) / visibleChildCount);
-            }
-        };
-        setupByConfig(new Config(VERTICAL, false, false).adapter(adapter).reverseLayout(true),
-                false);
-        waitForFirstLayout();
-
-        // adapter position of the currently focused item.
-        int focusIndex = 0;
-        View newFocused = mRecyclerView.getChildAt(focusIndex);
-        requestFocus(newFocused, true);
-        RecyclerView.ViewHolder toFocus = mRecyclerView.findViewHolderForAdapterPosition(
-                focusIndex);
-        assertThat("Child at position " + focusIndex + " should be focused",
-                toFocus.itemView.hasFocus(), is(true));
-
-        // adapter position of the item (whether focusable or not) that just becomes fully
-        // visible after focusSearch.
-        int visibleIndex = 0;
-        // The VH of the above adapter position
-        RecyclerView.ViewHolder toVisible = null;
-
-        // Navigate up through the focusable and unfocusable chunks. The focusable items should
-        // become focused one by one until hitting the last focusable item, at which point,
-        // unfocusable items should become visible on the screen until the currently focused item
-        // stays on the screen.
-        for (int i = 0; i < adapter.getItemCount(); i++) {
-            focusSearch(mRecyclerView.getFocusedChild(), View.FOCUS_UP, true);
-            // adapter position of the currently focused item.
-            focusIndex = Math.min(consecutiveFocusablesCount - 1, (focusIndex + 1));
-            toFocus = mRecyclerView.findViewHolderForAdapterPosition(focusIndex);
-            visibleIndex = Math.min(consecutiveFocusablesCount + visibleChildCount - 2,
-                    (visibleIndex + 1));
-            toVisible = mRecyclerView.findViewHolderForAdapterPosition(visibleIndex);
-
-            assertThat("Child at position " + focusIndex + " should be focused",
-                    toFocus.itemView.hasFocus(), is(true));
-            assertTrue("Focused child should be at least partially visible.",
-                    isViewPartiallyInBound(mRecyclerView, toFocus.itemView));
-            assertTrue("Child view at adapter pos " + visibleIndex + " should be fully visible.",
-                    isViewFullyInBound(mRecyclerView, toVisible.itemView));
-        }
-    }
-
-    @Test
-    public void bottomUnfocusableViewsVisibility() throws Throwable {
-        // The maximum number of child views that can be visible at any time.
-        final int visibleChildCount = 5;
-        final int consecutiveFocusablesCount = 2;
-        final int consecutiveUnFocusablesCount = 18;
-        final TestAdapter adapter = new TestAdapter(
-                consecutiveFocusablesCount + consecutiveUnFocusablesCount) {
-            RecyclerView mAttachedRv;
-
-            @Override
-            public TestViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
-                TestViewHolder testViewHolder = super.onCreateViewHolder(parent, viewType);
-                // Good to have colors for debugging
-                StateListDrawable stl = new StateListDrawable();
-                stl.addState(new int[]{android.R.attr.state_focused},
-                        new ColorDrawable(Color.RED));
-                stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
-                //noinspection deprecation used to support kitkat tests
-                testViewHolder.itemView.setBackgroundDrawable(stl);
-                return testViewHolder;
-            }
-
-            @Override
-            public void onAttachedToRecyclerView(RecyclerView recyclerView) {
-                mAttachedRv = recyclerView;
-            }
-
-            @Override
-            public void onBindViewHolder(TestViewHolder holder,
-                    int position) {
-                super.onBindViewHolder(holder, position);
-                if (position < consecutiveFocusablesCount) {
-                    holder.itemView.setFocusable(true);
-                    holder.itemView.setFocusableInTouchMode(true);
-                } else {
-                    holder.itemView.setFocusable(false);
-                    holder.itemView.setFocusableInTouchMode(false);
-                }
-                // This height ensures that some portion of #visibleChildCount'th child is
-                // off-bounds, creating more interesting test scenario.
-                holder.itemView.setMinimumHeight((mAttachedRv.getHeight()
-                        + mAttachedRv.getHeight() / (2 * visibleChildCount)) / visibleChildCount);
-            }
-        };
-        setupByConfig(new Config(VERTICAL, false, false).adapter(adapter), false);
-        waitForFirstLayout();
-
-        // adapter position of the currently focused item.
-        int focusIndex = 0;
-        View newFocused = mRecyclerView.getChildAt(focusIndex);
-        requestFocus(newFocused, true);
-        RecyclerView.ViewHolder toFocus = mRecyclerView.findViewHolderForAdapterPosition(
-                focusIndex);
-        assertThat("Child at position " + focusIndex + " should be focused",
-                toFocus.itemView.hasFocus(), is(true));
-
-        // adapter position of the item (whether focusable or not) that just becomes fully
-        // visible after focusSearch.
-        int visibleIndex = 0;
-        // The VH of the above adapter position
-        RecyclerView.ViewHolder toVisible = null;
-
-        // Navigate down through the focusable and unfocusable chunks. The focusable items should
-        // become focused one by one until hitting the last focusable item, at which point,
-        // unfocusable items should become visible on the screen until the currently focused item
-        // stays on the screen.
-        for (int i = 0; i < adapter.getItemCount(); i++) {
-            focusSearch(mRecyclerView.getFocusedChild(), View.FOCUS_DOWN, true);
-            // adapter position of the currently focused item.
-            focusIndex = Math.min(consecutiveFocusablesCount - 1, (focusIndex + 1));
-            toFocus = mRecyclerView.findViewHolderForAdapterPosition(focusIndex);
-            visibleIndex = Math.min(consecutiveFocusablesCount + visibleChildCount - 2,
-                    (visibleIndex + 1));
-            toVisible = mRecyclerView.findViewHolderForAdapterPosition(visibleIndex);
-
-            assertThat("Child at position " + focusIndex + " should be focused",
-                    toFocus.itemView.hasFocus(), is(true));
-            assertTrue("Focused child should be at least partially visible.",
-                    isViewPartiallyInBound(mRecyclerView, toFocus.itemView));
-            assertTrue("Child view at adapter pos " + visibleIndex + " should be fully visible.",
-                    isViewFullyInBound(mRecyclerView, toVisible.itemView));
-        }
-    }
-
-    @Test
-    public void leftUnfocusableViewsVisibility() throws Throwable {
-        // The maximum number of child views that can be visible at any time.
-        final int visibleChildCount = 5;
-        final int consecutiveFocusablesCount = 2;
-        final int consecutiveUnFocusablesCount = 18;
-        final TestAdapter adapter = new TestAdapter(
-                consecutiveFocusablesCount + consecutiveUnFocusablesCount) {
-            RecyclerView mAttachedRv;
-
-            @Override
-            public TestViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
-                TestViewHolder testViewHolder = super.onCreateViewHolder(parent, viewType);
-                // Good to have colors for debugging
-                StateListDrawable stl = new StateListDrawable();
-                stl.addState(new int[]{android.R.attr.state_focused},
-                        new ColorDrawable(Color.RED));
-                stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
-                //noinspection deprecation used to support kitkat tests
-                testViewHolder.itemView.setBackgroundDrawable(stl);
-                return testViewHolder;
-            }
-
-            @Override
-            public void onAttachedToRecyclerView(RecyclerView recyclerView) {
-                mAttachedRv = recyclerView;
-            }
-
-            @Override
-            public void onBindViewHolder(TestViewHolder holder,
-                    int position) {
-                super.onBindViewHolder(holder, position);
-                if (position < consecutiveFocusablesCount) {
-                    holder.itemView.setFocusable(true);
-                    holder.itemView.setFocusableInTouchMode(true);
-                } else {
-                    holder.itemView.setFocusable(false);
-                    holder.itemView.setFocusableInTouchMode(false);
-                }
-                // This width ensures that some portion of #visibleChildCount'th child is
-                // off-bounds, creating more interesting test scenario.
-                holder.itemView.setMinimumWidth((mAttachedRv.getWidth()
-                        + mAttachedRv.getWidth() / (2 * visibleChildCount)) / visibleChildCount);
-            }
-        };
-        setupByConfig(new Config(HORIZONTAL, false, false).adapter(adapter).reverseLayout(true),
-                false);
-        waitForFirstLayout();
-
-        // adapter position of the currently focused item.
-        int focusIndex = 0;
-        View newFocused = mRecyclerView.getChildAt(focusIndex);
-        requestFocus(newFocused, true);
-        RecyclerView.ViewHolder toFocus = mRecyclerView.findViewHolderForAdapterPosition(
-                focusIndex);
-        assertThat("Child at position " + focusIndex + " should be focused",
-                toFocus.itemView.hasFocus(), is(true));
-
-        // adapter position of the item (whether focusable or not) that just becomes fully
-        // visible after focusSearch.
-        int visibleIndex = 0;
-        // The VH of the above adapter position
-        RecyclerView.ViewHolder toVisible = null;
-
-        // Navigate left through the focusable and unfocusable chunks. The focusable items should
-        // become focused one by one until hitting the last focusable item, at which point,
-        // unfocusable items should become visible on the screen until the currently focused item
-        // stays on the screen.
-        for (int i = 0; i < adapter.getItemCount(); i++) {
-            focusSearch(mRecyclerView.getFocusedChild(), View.FOCUS_LEFT, true);
-            // adapter position of the currently focused item.
-            focusIndex = Math.min(consecutiveFocusablesCount - 1, (focusIndex + 1));
-            toFocus = mRecyclerView.findViewHolderForAdapterPosition(focusIndex);
-            visibleIndex = Math.min(consecutiveFocusablesCount + visibleChildCount - 2,
-                    (visibleIndex + 1));
-            toVisible = mRecyclerView.findViewHolderForAdapterPosition(visibleIndex);
-
-            assertThat("Child at position " + focusIndex + " should be focused",
-                    toFocus.itemView.hasFocus(), is(true));
-            assertTrue("Focused child should be at least partially visible.",
-                    isViewPartiallyInBound(mRecyclerView, toFocus.itemView));
-            assertTrue("Child view at adapter pos " + visibleIndex + " should be fully visible.",
-                    isViewFullyInBound(mRecyclerView, toVisible.itemView));
-        }
-    }
-
-    @Test
-    public void rightUnfocusableViewsVisibility() throws Throwable {
-        // The maximum number of child views that can be visible at any time.
-        final int visibleChildCount = 5;
-        final int consecutiveFocusablesCount = 2;
-        final int consecutiveUnFocusablesCount = 18;
-        final TestAdapter adapter = new TestAdapter(
-                consecutiveFocusablesCount + consecutiveUnFocusablesCount) {
-            RecyclerView mAttachedRv;
-
-            @Override
-            public TestViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
-                TestViewHolder testViewHolder = super.onCreateViewHolder(parent, viewType);
-                // Good to have colors for debugging
-                StateListDrawable stl = new StateListDrawable();
-                stl.addState(new int[]{android.R.attr.state_focused},
-                        new ColorDrawable(Color.RED));
-                stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
-                //noinspection deprecation used to support kitkat tests
-                testViewHolder.itemView.setBackgroundDrawable(stl);
-                return testViewHolder;
-            }
-
-            @Override
-            public void onAttachedToRecyclerView(RecyclerView recyclerView) {
-                mAttachedRv = recyclerView;
-            }
-
-            @Override
-            public void onBindViewHolder(TestViewHolder holder,
-                    int position) {
-                super.onBindViewHolder(holder, position);
-                if (position < consecutiveFocusablesCount) {
-                    holder.itemView.setFocusable(true);
-                    holder.itemView.setFocusableInTouchMode(true);
-                } else {
-                    holder.itemView.setFocusable(false);
-                    holder.itemView.setFocusableInTouchMode(false);
-                }
-                // This width ensures that some portion of #visibleChildCount'th child is
-                // off-bounds, creating more interesting test scenario.
-                holder.itemView.setMinimumWidth((mAttachedRv.getWidth()
-                        + mAttachedRv.getWidth() / (2 * visibleChildCount)) / visibleChildCount);
-            }
-        };
-        setupByConfig(new Config(HORIZONTAL, false, false).adapter(adapter), false);
-        waitForFirstLayout();
-
-        // adapter position of the currently focused item.
-        int focusIndex = 0;
-        View newFocused = mRecyclerView.getChildAt(focusIndex);
-        requestFocus(newFocused, true);
-        RecyclerView.ViewHolder toFocus = mRecyclerView.findViewHolderForAdapterPosition(
-                focusIndex);
-        assertThat("Child at position " + focusIndex + " should be focused",
-                toFocus.itemView.hasFocus(), is(true));
-
-        // adapter position of the item (whether focusable or not) that just becomes fully
-        // visible after focusSearch.
-        int visibleIndex = 0;
-        // The VH of the above adapter position
-        RecyclerView.ViewHolder toVisible = null;
-
-        // Navigate right through the focusable and unfocusable chunks. The focusable items should
-        // become focused one by one until hitting the last focusable item, at which point,
-        // unfocusable items should become visible on the screen until the currently focused item
-        // stays on the screen.
-        for (int i = 0; i < adapter.getItemCount(); i++) {
-            focusSearch(mRecyclerView.getFocusedChild(), View.FOCUS_RIGHT, true);
-            // adapter position of the currently focused item.
-            focusIndex = Math.min(consecutiveFocusablesCount - 1, (focusIndex + 1));
-            toFocus = mRecyclerView.findViewHolderForAdapterPosition(focusIndex);
-            visibleIndex = Math.min(consecutiveFocusablesCount + visibleChildCount - 2,
-                    (visibleIndex + 1));
-            toVisible = mRecyclerView.findViewHolderForAdapterPosition(visibleIndex);
-
-            assertThat("Child at position " + focusIndex + " should be focused",
-                    toFocus.itemView.hasFocus(), is(true));
-            assertTrue("Focused child should be at least partially visible.",
-                    isViewPartiallyInBound(mRecyclerView, toFocus.itemView));
-            assertTrue("Child view at adapter pos " + visibleIndex + " should be fully visible.",
-                    isViewFullyInBound(mRecyclerView, toVisible.itemView));
-        }
-    }
-
-    @Test
     public void removeAnchorItem() throws Throwable {
         removeAnchorItemTest(
                 new Config().orientation(VERTICAL).stackFromBottom(false).reverseLayout(
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewLayoutTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewLayoutTest.java
index 786df47..79479ef 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewLayoutTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewLayoutTest.java
@@ -326,7 +326,7 @@
                 holder.itemView.setFocusableInTouchMode(true);
                 holder.itemView.setLayoutParams(
                         new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
-                                ViewGroup.LayoutParams.WRAP_CONTENT));
+                        ViewGroup.LayoutParams.WRAP_CONTENT));
             }
         });
         TestLayoutManager tlm = new TestLayoutManager() {
@@ -355,7 +355,7 @@
 
             @Override
             public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler,
-                    RecyclerView.State state) {
+                                            RecyclerView.State state) {
                 super.scrollHorizontallyBy(dx, recycler, state);
                 // offset by -dx because the views translate opposite of the scrolling direction
                 mRecyclerView.offsetChildrenHorizontal(-dx);
@@ -364,7 +364,7 @@
 
             @Override
             public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler,
-                    RecyclerView.State state) {
+                                          RecyclerView.State state) {
                 super.scrollVerticallyBy(dy, recycler, state);
                 // offset by -dy because the views translate opposite of the scrolling direction
                 mRecyclerView.offsetChildrenVertical(-dy);
@@ -604,7 +604,7 @@
 
             @Override
             public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler,
-                    RecyclerView.State state) {
+                                          RecyclerView.State state) {
                 // Access views in the state (that might have been deleted).
                 for (int  i = 10; i < state.getItemCount(); i++) {
                     recycler.getViewForPosition(i);
@@ -728,8 +728,8 @@
             @Nullable
             @Override
             public View onFocusSearchFailed(View focused, int direction,
-                    RecyclerView.Recycler recycler,
-                    RecyclerView.State state) {
+                                            RecyclerView.Recycler recycler,
+                                            RecyclerView.State state) {
                 try {
                     recycler.getViewForPosition(state.getItemCount() - 1);
                 } catch (Throwable t) {
@@ -4246,7 +4246,7 @@
 
                             @Override
                             protected void onTargetFound(View targetView, RecyclerView.State state,
-                                    Action action) {
+                                                         Action action) {
                                 super.onTargetFound(targetView, state, action);
                                 mTargetFound.set(true);
                             }
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/StaggeredGridLayoutManagerTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/StaggeredGridLayoutManagerTest.java
index 89db393..3528b7c 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/StaggeredGridLayoutManagerTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/StaggeredGridLayoutManagerTest.java
@@ -80,7 +80,7 @@
         smoothScrollToPosition(100);
         mLayoutManager.expectLayouts(1);
         mAdapter.deleteAndNotify(0, 2);
-        mLayoutManager.waitForLayout(2000);
+        mLayoutManager.waitForLayout(2);
         smoothScrollToPosition(0);
         assertFalse("all starts should not be the same", mLayoutManager.areAllStartsEqual());
     }
@@ -277,16 +277,6 @@
                         holder.mBoundItem = item;
                         ((EditText) ((FrameLayout) holder.itemView).getChildAt(0)).setText(
                                 item.mText + " (" + item.mId + ")");
-                        // Good to have colors for debugging
-                        StateListDrawable stl = new StateListDrawable();
-                        stl.addState(new int[]{android.R.attr.state_focused},
-                                new ColorDrawable(Color.RED));
-                        stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
-                        //noinspection deprecation using this for kitkat tests
-                        holder.itemView.setBackgroundDrawable(stl);
-                        if (mOnBindCallback != null) {
-                            mOnBindCallback.onBoundItem(holder, position);
-                        }
                     }
                 });
         mLayoutManager.expectLayouts(1);
@@ -404,449 +394,6 @@
         waitForIdleScroll(mRecyclerView);
     }
 
-    @Test
-    public void topUnfocusableViewsVisibility() throws Throwable {
-        // The maximum number of rows that can be fully in-bounds of RV.
-        final int visibleRowCount = 5;
-        final int spanCount = 3;
-        final int lastFocusableIndex = 6;
-
-        setupByConfig(new Config(VERTICAL, true, spanCount, GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS),
-                new GridTestAdapter(18, 1) {
-                    RecyclerView mAttachedRv;
-
-                    @Override
-                    public TestViewHolder onCreateViewHolder(ViewGroup parent,
-                            int viewType) {
-                        TestViewHolder testViewHolder = super.onCreateViewHolder(parent, viewType);
-                        testViewHolder.itemView.setFocusable(true);
-                        testViewHolder.itemView.setFocusableInTouchMode(true);
-                        // Good to have colors for debugging
-                        StateListDrawable stl = new StateListDrawable();
-                        stl.addState(new int[]{android.R.attr.state_focused},
-                                new ColorDrawable(Color.RED));
-                        stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
-                        //noinspection deprecation used to support kitkat tests
-                        testViewHolder.itemView.setBackgroundDrawable(stl);
-                        return testViewHolder;
-                    }
-
-                    @Override
-                    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
-                        mAttachedRv = recyclerView;
-                    }
-
-                    @Override
-                    public void onBindViewHolder(TestViewHolder holder,
-                            int position) {
-                        super.onBindViewHolder(holder, position);
-                        RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) holder.itemView
-                                .getLayoutParams();
-                        if (position <= lastFocusableIndex) {
-                            holder.itemView.setFocusable(true);
-                            holder.itemView.setFocusableInTouchMode(true);
-                        } else {
-                            holder.itemView.setFocusable(false);
-                            holder.itemView.setFocusableInTouchMode(false);
-                        }
-                        holder.itemView.setMinimumHeight(mAttachedRv.getHeight() / visibleRowCount);
-                        lp.topMargin = 0;
-                        lp.leftMargin = 0;
-                        lp.rightMargin = 0;
-                        lp.bottomMargin = 0;
-                        if (position == 11) {
-                            lp.bottomMargin = 9;
-                        }
-                    }
-                });
-
-        /**
-         *
-         * 15 16 17
-         * 12 13 14
-         * 11 11 11
-         * 9 10
-         * 8 8 8
-         * 7
-         * 6 6 6
-         * 3 4 5
-         * 0 1 2
-         */
-        mAdapter.mFullSpanItems.add(6);
-        mAdapter.mFullSpanItems.add(8);
-        mAdapter.mFullSpanItems.add(11);
-        waitFirstLayout();
-
-
-        // adapter position of the currently focused item.
-        int focusIndex = 1;
-        RecyclerView.ViewHolder toFocus = mRecyclerView.findViewHolderForAdapterPosition(
-                focusIndex);
-        View viewToFocus = toFocus.itemView;
-        assertTrue(requestFocus(viewToFocus, true));
-        assertSame(viewToFocus, mRecyclerView.getFocusedChild());
-
-        // The VH of the unfocusable item that just became fully visible after focusSearch.
-        RecyclerView.ViewHolder toVisible = null;
-
-        View focusedView = viewToFocus;
-        int actualFocusIndex = -1;
-        // First, scroll until the last focusable row.
-        for (int i : new int[]{4, 6}) {
-            focusSearchAndWaitForScroll(focusedView, View.FOCUS_UP);
-            focusedView = mRecyclerView.getFocusedChild();
-            actualFocusIndex = mRecyclerView.getChildViewHolder(focusedView).getAdapterPosition();
-            assertEquals("Focused view should be at adapter position " + i + " whereas it's at "
-                    + actualFocusIndex, i, actualFocusIndex);
-        }
-
-        // Further scroll up in order to make the unfocusable rows visible. This process should
-        // continue until the currently focused item is still visible. The focused item should not
-        // change in this loop.
-        for (int i : new int[]{9, 11, 11, 11}) {
-            focusSearchAndWaitForScroll(focusedView, View.FOCUS_UP);
-            focusedView = mRecyclerView.getFocusedChild();
-            actualFocusIndex = mRecyclerView.getChildViewHolder(focusedView).getAdapterPosition();
-            toVisible = mRecyclerView.findViewHolderForAdapterPosition(i);
-
-            assertEquals("Focused view should not be changed, whereas it's now at "
-                    + actualFocusIndex, 6, actualFocusIndex);
-            assertTrue("Focused child should be at least partially visible.",
-                    isViewPartiallyInBound(mRecyclerView, focusedView));
-            assertTrue("Child view at adapter pos " + i + " should be fully visible.",
-                    isViewFullyInBound(mRecyclerView, toVisible.itemView));
-        }
-    }
-
-    @Test
-    public void bottomUnfocusableViewsVisibility() throws Throwable {
-        // The maximum number of rows that can be fully in-bounds of RV.
-        final int visibleRowCount = 5;
-        final int spanCount = 3;
-        final int lastFocusableIndex = 6;
-
-        setupByConfig(new Config(VERTICAL, false, spanCount, GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS),
-                new GridTestAdapter(18, 1) {
-                    RecyclerView mAttachedRv;
-
-                    @Override
-                    public TestViewHolder onCreateViewHolder(ViewGroup parent,
-                            int viewType) {
-                        TestViewHolder testViewHolder = super.onCreateViewHolder(parent, viewType);
-                        testViewHolder.itemView.setFocusable(true);
-                        testViewHolder.itemView.setFocusableInTouchMode(true);
-                        // Good to have colors for debugging
-                        StateListDrawable stl = new StateListDrawable();
-                        stl.addState(new int[]{android.R.attr.state_focused},
-                                new ColorDrawable(Color.RED));
-                        stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
-                        //noinspection deprecation used to support kitkat tests
-                        testViewHolder.itemView.setBackgroundDrawable(stl);
-                        return testViewHolder;
-                    }
-
-                    @Override
-                    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
-                        mAttachedRv = recyclerView;
-                    }
-
-                    @Override
-                    public void onBindViewHolder(TestViewHolder holder,
-                            int position) {
-                        super.onBindViewHolder(holder, position);
-                        RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) holder.itemView
-                                .getLayoutParams();
-                        if (position <= lastFocusableIndex) {
-                            holder.itemView.setFocusable(true);
-                            holder.itemView.setFocusableInTouchMode(true);
-                        } else {
-                            holder.itemView.setFocusable(false);
-                            holder.itemView.setFocusableInTouchMode(false);
-                        }
-                        holder.itemView.setMinimumHeight(mAttachedRv.getHeight() / visibleRowCount);
-                        lp.topMargin = 0;
-                        lp.leftMargin = 0;
-                        lp.rightMargin = 0;
-                        lp.bottomMargin = 0;
-                        if (position == 11) {
-                            lp.topMargin = 9;
-                        }
-                    }
-                });
-
-        /**
-         * 0 1 2
-         * 3 4 5
-         * 6 6 6
-         * 7
-         * 8 8 8
-         * 9 10
-         * 11 11 11
-         * 12 13 14
-         * 15 16 17
-         */
-        mAdapter.mFullSpanItems.add(6);
-        mAdapter.mFullSpanItems.add(8);
-        mAdapter.mFullSpanItems.add(11);
-        waitFirstLayout();
-
-
-        // adapter position of the currently focused item.
-        int focusIndex = 1;
-        RecyclerView.ViewHolder toFocus = mRecyclerView.findViewHolderForAdapterPosition(
-                focusIndex);
-        View viewToFocus = toFocus.itemView;
-        assertTrue(requestFocus(viewToFocus, true));
-        assertSame(viewToFocus, mRecyclerView.getFocusedChild());
-
-        // The VH of the unfocusable item that just became fully visible after focusSearch.
-        RecyclerView.ViewHolder toVisible = null;
-
-        View focusedView = viewToFocus;
-        int actualFocusIndex = -1;
-        // First, scroll until the last focusable row.
-        for (int i : new int[]{4, 6}) {
-            focusSearchAndWaitForScroll(focusedView, View.FOCUS_DOWN);
-            focusedView = mRecyclerView.getFocusedChild();
-            actualFocusIndex = mRecyclerView.getChildViewHolder(focusedView).getAdapterPosition();
-            assertEquals("Focused view should be at adapter position " + i + " whereas it's at "
-                    + actualFocusIndex, i, actualFocusIndex);
-        }
-
-        // Further scroll down in order to make the unfocusable rows visible. This process should
-        // continue until the currently focused item is still visible. The focused item should not
-        // change in this loop.
-        for (int i : new int[]{9, 11, 11, 11}) {
-            focusSearchAndWaitForScroll(focusedView, View.FOCUS_DOWN);
-            focusedView = mRecyclerView.getFocusedChild();
-            actualFocusIndex = mRecyclerView.getChildViewHolder(focusedView).getAdapterPosition();
-            toVisible = mRecyclerView.findViewHolderForAdapterPosition(i);
-
-            assertEquals("Focused view should not be changed, whereas it's now at "
-                    + actualFocusIndex, 6, actualFocusIndex);
-            assertTrue("Focused child should be at least partially visible.",
-                    isViewPartiallyInBound(mRecyclerView, focusedView));
-            assertTrue("Child view at adapter pos " + i + " should be fully visible.",
-                    isViewFullyInBound(mRecyclerView, toVisible.itemView));
-        }
-    }
-
-    @Test
-    public void leftUnfocusableViewsVisibility() throws Throwable {
-        // The maximum number of columns that can be fully in-bounds of RV.
-        final int visibleColCount = 5;
-        final int spanCount = 3;
-        final int lastFocusableIndex = 6;
-
-        // Reverse layout so that views are placed from right to left.
-        setupByConfig(new Config(HORIZONTAL, true, spanCount,
-                        GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS),
-                new GridTestAdapter(18, 1) {
-                    RecyclerView mAttachedRv;
-
-                    @Override
-                    public TestViewHolder onCreateViewHolder(ViewGroup parent,
-                            int viewType) {
-                        TestViewHolder testViewHolder = super.onCreateViewHolder(parent, viewType);
-                        testViewHolder.itemView.setFocusable(true);
-                        testViewHolder.itemView.setFocusableInTouchMode(true);
-                        // Good to have colors for debugging
-                        StateListDrawable stl = new StateListDrawable();
-                        stl.addState(new int[]{android.R.attr.state_focused},
-                                new ColorDrawable(Color.RED));
-                        stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
-                        //noinspection deprecation used to support kitkat tests
-                        testViewHolder.itemView.setBackgroundDrawable(stl);
-                        return testViewHolder;
-                    }
-
-                    @Override
-                    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
-                        mAttachedRv = recyclerView;
-                    }
-
-                    @Override
-                    public void onBindViewHolder(TestViewHolder holder,
-                            int position) {
-                        super.onBindViewHolder(holder, position);
-                        RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) holder.itemView
-                                .getLayoutParams();
-                        if (position <= lastFocusableIndex) {
-                            holder.itemView.setFocusable(true);
-                            holder.itemView.setFocusableInTouchMode(true);
-                        } else {
-                            holder.itemView.setFocusable(false);
-                            holder.itemView.setFocusableInTouchMode(false);
-                        }
-                        holder.itemView.setMinimumWidth(mAttachedRv.getWidth() / visibleColCount);
-                        lp.topMargin = 0;
-                        lp.leftMargin = 0;
-                        lp.rightMargin = 0;
-                        lp.bottomMargin = 0;
-                        if (position == 11) {
-                            lp.rightMargin = 9;
-                        }
-                    }
-                });
-
-        /**
-         * 15 12 11 9  8 7 6 3 0
-         * 16 13 11 10 8   6 4 1
-         * 17 14 11    8   6 5 2
-         */
-        mAdapter.mFullSpanItems.add(6);
-        mAdapter.mFullSpanItems.add(8);
-        mAdapter.mFullSpanItems.add(11);
-        waitFirstLayout();
-
-
-        // adapter position of the currently focused item.
-        int focusIndex = 1;
-        RecyclerView.ViewHolder toFocus = mRecyclerView.findViewHolderForAdapterPosition(
-                focusIndex);
-        View viewToFocus = toFocus.itemView;
-        assertTrue(requestFocus(viewToFocus, true));
-        assertSame(viewToFocus, mRecyclerView.getFocusedChild());
-
-        // The VH of the unfocusable item that just became fully visible after focusSearch.
-        RecyclerView.ViewHolder toVisible = null;
-
-        View focusedView = viewToFocus;
-        int actualFocusIndex = -1;
-        // First, scroll until the last focusable column.
-        for (int i : new int[]{4, 6}) {
-            focusSearchAndWaitForScroll(focusedView, View.FOCUS_LEFT);
-            focusedView = mRecyclerView.getFocusedChild();
-            actualFocusIndex = mRecyclerView.getChildViewHolder(focusedView).getAdapterPosition();
-            assertEquals("Focused view should be at adapter position " + i + " whereas it's at "
-                    + actualFocusIndex, i, actualFocusIndex);
-        }
-
-        // Further scroll left in order to make the unfocusable columns visible. This process should
-        // continue until the currently focused item is still visible. The focused item should not
-        // change in this loop.
-        for (int i : new int[]{9, 11, 11, 11}) {
-            focusSearchAndWaitForScroll(focusedView, View.FOCUS_LEFT);
-            focusedView = mRecyclerView.getFocusedChild();
-            actualFocusIndex = mRecyclerView.getChildViewHolder(focusedView).getAdapterPosition();
-            toVisible = mRecyclerView.findViewHolderForAdapterPosition(i);
-
-            assertEquals("Focused view should not be changed, whereas it's now at "
-                    + actualFocusIndex, 6, actualFocusIndex);
-            assertTrue("Focused child should be at least partially visible.",
-                    isViewPartiallyInBound(mRecyclerView, focusedView));
-            assertTrue("Child view at adapter pos " + i + " should be fully visible.",
-                    isViewFullyInBound(mRecyclerView, toVisible.itemView));
-        }
-    }
-
-    @Test
-    public void rightUnfocusableViewsVisibility() throws Throwable {
-        // The maximum number of columns that can be fully in-bounds of RV.
-        final int visibleColCount = 5;
-        final int spanCount = 3;
-        final int lastFocusableIndex = 6;
-
-        setupByConfig(new Config(HORIZONTAL, false, spanCount,
-                        GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS),
-                new GridTestAdapter(18, 1) {
-                    RecyclerView mAttachedRv;
-
-                    @Override
-                    public TestViewHolder onCreateViewHolder(ViewGroup parent,
-                            int viewType) {
-                        TestViewHolder testViewHolder = super.onCreateViewHolder(parent, viewType);
-                        testViewHolder.itemView.setFocusable(true);
-                        testViewHolder.itemView.setFocusableInTouchMode(true);
-                        // Good to have colors for debugging
-                        StateListDrawable stl = new StateListDrawable();
-                        stl.addState(new int[]{android.R.attr.state_focused},
-                                new ColorDrawable(Color.RED));
-                        stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
-                        //noinspection deprecation used to support kitkat tests
-                        testViewHolder.itemView.setBackgroundDrawable(stl);
-                        return testViewHolder;
-                    }
-
-                    @Override
-                    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
-                        mAttachedRv = recyclerView;
-                    }
-
-                    @Override
-                    public void onBindViewHolder(TestViewHolder holder,
-                            int position) {
-                        super.onBindViewHolder(holder, position);
-                        RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) holder.itemView
-                                .getLayoutParams();
-                        if (position <= lastFocusableIndex) {
-                            holder.itemView.setFocusable(true);
-                            holder.itemView.setFocusableInTouchMode(true);
-                        } else {
-                            holder.itemView.setFocusable(false);
-                            holder.itemView.setFocusableInTouchMode(false);
-                        }
-                        holder.itemView.setMinimumWidth(mAttachedRv.getWidth() / visibleColCount);
-                        lp.topMargin = 0;
-                        lp.leftMargin = 0;
-                        lp.rightMargin = 0;
-                        lp.bottomMargin = 0;
-                        if (position == 11) {
-                            lp.leftMargin = 9;
-                        }
-                    }
-                });
-
-        /**
-         * 0 3 6 7 8 9  11 12 15
-         * 1 4 6   8 10 11 13 16
-         * 2 5 6   8    11 14 17
-         */
-        mAdapter.mFullSpanItems.add(6);
-        mAdapter.mFullSpanItems.add(8);
-        mAdapter.mFullSpanItems.add(11);
-        waitFirstLayout();
-
-
-        // adapter position of the currently focused item.
-        int focusIndex = 1;
-        RecyclerView.ViewHolder toFocus = mRecyclerView.findViewHolderForAdapterPosition(
-                focusIndex);
-        View viewToFocus = toFocus.itemView;
-        assertTrue(requestFocus(viewToFocus, true));
-        assertSame(viewToFocus, mRecyclerView.getFocusedChild());
-
-        // The VH of the unfocusable item that just became fully visible after focusSearch.
-        RecyclerView.ViewHolder toVisible = null;
-
-        View focusedView = viewToFocus;
-        int actualFocusIndex = -1;
-        // First, scroll until the last focusable column.
-        for (int i : new int[]{4, 6}) {
-            focusSearchAndWaitForScroll(focusedView, View.FOCUS_RIGHT);
-            focusedView = mRecyclerView.getFocusedChild();
-            actualFocusIndex = mRecyclerView.getChildViewHolder(focusedView).getAdapterPosition();
-            assertEquals("Focused view should be at adapter position " + i + " whereas it's at "
-                    + actualFocusIndex, i, actualFocusIndex);
-        }
-
-        // Further scroll right in order to make the unfocusable rows visible. This process should
-        // continue until the currently focused item is still visible. The focused item should not
-        // change in this loop.
-        for (int i : new int[]{9, 11, 11, 11}) {
-            focusSearchAndWaitForScroll(focusedView, View.FOCUS_RIGHT);
-            focusedView = mRecyclerView.getFocusedChild();
-            actualFocusIndex = mRecyclerView.getChildViewHolder(focusedView).getAdapterPosition();
-            toVisible = mRecyclerView.findViewHolderForAdapterPosition(i);
-
-            assertEquals("Focused view should not be changed, whereas it's now at "
-                    + actualFocusIndex, 6, actualFocusIndex);
-            assertTrue("Focused child should be at least partially visible.",
-                    isViewPartiallyInBound(mRecyclerView, focusedView));
-            assertTrue("Child view at adapter pos " + i + " should be fully visible.",
-                    isViewFullyInBound(mRecyclerView, toVisible.itemView));
-        }
-    }
 
     @Test
     public void scrollToPositionWithPredictive() throws Throwable {
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/ViewBoundsCheckTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/ViewBoundsCheckTest.java
deleted file mode 100644
index c950a78..0000000
--- a/v7/recyclerview/tests/src/android/support/v7/widget/ViewBoundsCheckTest.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (C) 2017 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.v7.widget;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-
-import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.view.View;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-
-@SmallTest
-@RunWith(JUnit4.class)
-public class ViewBoundsCheckTest {
-
-
-    private static final String TAG = "ViewBoundsCheckTest";
-    private Context mContext;
-
-    /** Case #1:
-     * Parent:                    [2.......................8]
-     Views: [-3...-1] [-1...1] [1...3] [3...5] [5...7] [7...9] [9...11] [11...13]
-     */
-    int[] mParentBound1 = {2, 8};
-    int[][] mChildrenBound1 = {{-3, -1}, {-1, 1}, {1, 3}, {3, 5}, {5, 7}, {7, 9}, {9, 11},
-            {11, 13}};
-
-    /** Case #2:
-     * Parent:                  [1...................7]
-     Views: [-3...-1] [-1...1][1...3] [3...5] [5...7] [7...9] [9...11]
-     */
-    int[] mParentBound2 = {1, 7};
-    int[][] mChildrenBound2 = {{-3, -1}, {-1, 1}, {1, 3}, {3, 5}, {5, 7}, {7, 9}, {9, 11}};
-
-    View mParent;
-    View[] mChildren;
-
-    private final ViewBoundsCheck.Callback mBoundCheckCallback =
-            new ViewBoundsCheck.Callback() {
-                @Override
-                public int getChildCount() {
-                    return mChildren.length;
-                }
-
-                @Override
-                public View getParent() {
-                    return mParent;
-                }
-
-                @Override
-                public View getChildAt(int index) {
-                    return mChildren[index];
-                }
-
-                @Override
-                public int getParentStart() {
-                    return mParent.getLeft();
-                }
-
-                @Override
-                public int getParentEnd() {
-                    return mParent.getRight();
-                }
-
-                @Override
-                public int getChildStart(View view) {
-                    return view.getLeft();
-                }
-
-                @Override
-                public int getChildEnd(View view) {
-                    return view.getRight();
-                }
-            };
-
-    ViewBoundsCheck mBoundCheck = new ViewBoundsCheck(mBoundCheckCallback);
-
-    @Before
-    public void setUp() throws Exception {
-        mContext = InstrumentationRegistry.getContext();
-    }
-
-    private void setUpViews(int[] parentBound, int[][] childrenBound) {
-        mParent = new View(mContext);
-        mParent.setLeft(parentBound[0]);
-        mParent.setRight(parentBound[1]);
-        mChildren = new View[childrenBound.length];
-        for (int i = 0; i < childrenBound.length; i++) {
-            mChildren[i] = new View(mContext);
-            mChildren[i].setLeft(childrenBound[i][0]);
-            mChildren[i].setRight(childrenBound[i][1]);
-        }
-    }
-
-    @Test
-    public void preferredFromStart() {
-        setUpViews(mParentBound1, mChildrenBound1);
-        @ViewBoundsCheck.ViewBounds int preferredBoundsFlag = ViewBoundsCheck.FLAG_CVS_GT_PVS
-                | ViewBoundsCheck.FLAG_CVS_EQ_PVS | ViewBoundsCheck.FLAG_CVE_LT_PVE
-                | ViewBoundsCheck.FLAG_CVE_EQ_PVE;
-        @ViewBoundsCheck.ViewBounds int acceptableBoundsFlag = 0;
-        View view = mBoundCheck.findOneViewWithinBoundFlags(0, mChildren.length,
-                preferredBoundsFlag, acceptableBoundsFlag);
-        assertEquals("The first fully visible child from start should be returned", 3,
-                view.getLeft());
-        assertEquals("The first fully visible child from start should be returned", 5,
-                view.getRight());
-    }
-
-    @Test
-    public void preferredFromEnd() {
-        setUpViews(mParentBound1, mChildrenBound1);
-        @ViewBoundsCheck.ViewBounds int preferredBoundsFlag = ViewBoundsCheck.FLAG_CVS_GT_PVS
-                | ViewBoundsCheck.FLAG_CVS_EQ_PVS | ViewBoundsCheck.FLAG_CVE_LT_PVE
-                | ViewBoundsCheck.FLAG_CVE_EQ_PVE;
-        @ViewBoundsCheck.ViewBounds int acceptableBoundsFlag = 0;
-        View view = mBoundCheck.findOneViewWithinBoundFlags(mChildren.length - 1, -1,
-                preferredBoundsFlag, acceptableBoundsFlag);
-        assertEquals("The first fully visible child from end should be returned", 5,
-                view.getLeft());
-        assertEquals("The first fully visible child from end should be returned", 7,
-                view.getRight());
-    }
-
-    @Test
-    public void acceptableFromStart() {
-        setUpViews(mParentBound1, mChildrenBound1);
-        @ViewBoundsCheck.ViewBounds int preferredBoundsFlag = 0;
-        @ViewBoundsCheck.ViewBounds int acceptableBoundsFlag = (ViewBoundsCheck.FLAG_CVS_LT_PVS
-                | ViewBoundsCheck.FLAG_CVE_LT_PVE | ViewBoundsCheck.FLAG_CVE_GT_PVS);
-        View view = mBoundCheck.findOneViewWithinBoundFlags(0, mChildren.length,
-                preferredBoundsFlag, acceptableBoundsFlag);
-        assertEquals("The first partially visible child from start should be returned", 1,
-                view.getLeft());
-        assertEquals("The first partially visible child from start should be returned", 3,
-                view.getRight());
-    }
-
-    @Test
-    public void acceptableFromEnd() {
-        setUpViews(mParentBound1, mChildrenBound1);
-        @ViewBoundsCheck.ViewBounds int preferredBoundsFlag = 0;
-        @ViewBoundsCheck.ViewBounds int acceptableBoundsFlag = (ViewBoundsCheck.FLAG_CVE_GT_PVE
-                | ViewBoundsCheck.FLAG_CVS_GT_PVS | ViewBoundsCheck.FLAG_CVS_LT_PVE);
-        View view = mBoundCheck.findOneViewWithinBoundFlags(mChildren.length - 1, -1,
-                preferredBoundsFlag, acceptableBoundsFlag);
-        assertEquals("The first partially visible child from end should be returned", 7,
-                view.getLeft());
-        assertEquals("The first partially visible child from end should be returned", 9,
-                view.getRight());
-    }
-
-    @Test
-    public void noPreferredFoundAcceptableReturnedFromStart() {
-        setUpViews(mParentBound2, mChildrenBound2);
-        @ViewBoundsCheck.ViewBounds int  preferredBoundsFlag = (ViewBoundsCheck.FLAG_CVS_LT_PVS
-                | ViewBoundsCheck.FLAG_CVE_LT_PVE | ViewBoundsCheck.FLAG_CVE_GT_PVS);
-        @ViewBoundsCheck.ViewBounds int  acceptableBoundsFlag = (ViewBoundsCheck.FLAG_CVS_LT_PVS
-                | ViewBoundsCheck.FLAG_CVE_LT_PVE);
-        View view = mBoundCheck.findOneViewWithinBoundFlags(0, mChildren.length,
-                preferredBoundsFlag, acceptableBoundsFlag);
-        assertEquals("The last fully invisible child from start should be returned", -1,
-                view.getLeft());
-        assertEquals("TThe last fully invisible child from start should be returned", 1,
-                view.getRight());
-    }
-
-    @Test
-    public void noPreferredFoundAcceptableReturnedFromEnd() {
-        setUpViews(mParentBound2, mChildrenBound2);
-        @ViewBoundsCheck.ViewBounds int preferredBoundsFlag = (ViewBoundsCheck.FLAG_CVE_GT_PVE
-                | ViewBoundsCheck.FLAG_CVS_GT_PVS | ViewBoundsCheck.FLAG_CVS_LT_PVE);
-        @ViewBoundsCheck.ViewBounds int acceptableBoundsFlag = (ViewBoundsCheck.FLAG_CVE_GT_PVE
-                | ViewBoundsCheck.FLAG_CVS_GT_PVS);
-        View view = mBoundCheck.findOneViewWithinBoundFlags(mChildren.length - 1, -1,
-                preferredBoundsFlag, acceptableBoundsFlag);
-        assertEquals("The last fully invisible child from end should be returned", 7,
-                view.getLeft());
-        assertEquals("TThe last fully invisible child from end should be returned", 9,
-                view.getRight());
-    }
-
-    @Test
-    public void noViewsFoundWithinGivenBounds() {
-        setUpViews(mParentBound1, mChildrenBound1);
-        // create a view whose bounds cover its parent. Since no such view exist in the example
-        // layout, null should be returned.
-        @ViewBoundsCheck.ViewBounds int preferredBoundsFlag = (ViewBoundsCheck.FLAG_CVS_LT_PVS
-                | ViewBoundsCheck.FLAG_CVE_GT_PVE);
-        @ViewBoundsCheck.ViewBounds int acceptableBoundsFlag = preferredBoundsFlag;
-        View view = mBoundCheck.findOneViewWithinBoundFlags(0, mChildren.length,
-                preferredBoundsFlag, acceptableBoundsFlag);
-        assertNull("Null should be returned since no views are within the given bounds",
-                view);
-    }
-
-}