am 168e4ed6: am 6789459d: am 88242bfd: Merge "Fix janky browse transition" into mnc-dev

* commit '168e4ed63a3434f782f5e7a26aa69ceb5cf59add':
  Fix janky browse transition
diff --git a/design/base/android/support/design/widget/StateListAnimator.java b/design/base/android/support/design/widget/StateListAnimator.java
index c937b0b..2de5dba 100644
--- a/design/base/android/support/design/widget/StateListAnimator.java
+++ b/design/base/android/support/design/widget/StateListAnimator.java
@@ -124,8 +124,11 @@
         if (mLastMatch != null) {
             cancel();
         }
+
         mLastMatch = match;
-        if (match != null) {
+
+        View view = mViewRef.get();
+        if (match != null && view != null && view.getVisibility() == View.VISIBLE ) {
             start(match);
         }
     }
diff --git a/design/res/layout/design_menu_item_action_area.xml b/design/res/layout/design_menu_item_action_area.xml
new file mode 100644
index 0000000..ba8141d
--- /dev/null
+++ b/design/res/layout/design_menu_item_action_area.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+             android:layout_width="wrap_content"
+             android:layout_height="match_parent"/>
diff --git a/design/res/layout/design_navigation_item.xml b/design/res/layout/design_navigation_item.xml
index 3fcd74a..14c1be3 100644
--- a/design/res/layout/design_navigation_item.xml
+++ b/design/res/layout/design_navigation_item.xml
@@ -19,8 +19,4 @@
         android:layout_width="match_parent"
         android:layout_height="?attr/listPreferredItemHeightSmall"
         android:paddingLeft="?attr/listPreferredItemPaddingLeft"
-        android:paddingRight="?attr/listPreferredItemPaddingRight"
-        android:drawablePadding="@dimen/design_navigation_icon_padding"
-        android:gravity="center_vertical|start"
-        android:maxLines="1"
-        android:textAppearance="@style/TextAppearance.AppCompat.Body2"/>
+        android:paddingRight="?attr/listPreferredItemPaddingRight"/>
diff --git a/design/res/layout/design_navigation_menu_item.xml b/design/res/layout/design_navigation_menu_item.xml
new file mode 100644
index 0000000..91104bb1
--- /dev/null
+++ b/design/res/layout/design_navigation_menu_item.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <CheckedTextView
+            android:id="@+id/design_menu_item_text"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:drawablePadding="@dimen/design_navigation_icon_padding"
+            android:gravity="center_vertical|start"
+            android:maxLines="1"
+            android:textAppearance="@style/TextAppearance.AppCompat.Body2"/>
+
+    <ViewStub
+            android:id="@+id/design_menu_item_action_area_stub"
+            android:inflatedId="@+id/design_menu_item_action_area"
+            android:layout="@layout/design_menu_item_action_area"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"/>
+
+</merge>
diff --git a/design/src/android/support/design/internal/NavigationMenuItemView.java b/design/src/android/support/design/internal/NavigationMenuItemView.java
index 7813163..1d819df 100644
--- a/design/src/android/support/design/internal/NavigationMenuItemView.java
+++ b/design/src/android/support/design/internal/NavigationMenuItemView.java
@@ -27,19 +27,30 @@
 import android.support.v4.widget.TextViewCompat;
 import android.support.v7.internal.view.menu.MenuItemImpl;
 import android.support.v7.internal.view.menu.MenuView;
+import android.support.v7.widget.LinearLayoutCompat;
 import android.util.AttributeSet;
 import android.util.TypedValue;
-import android.widget.TextView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewStub;
+import android.widget.CheckedTextView;
+import android.widget.FrameLayout;
 
 /**
  * @hide
  */
-public class NavigationMenuItemView extends TextView implements MenuView.ItemView {
+public class NavigationMenuItemView extends LinearLayoutCompat implements MenuView.ItemView {
 
     private static final int[] CHECKED_STATE_SET = {android.R.attr.state_checked};
 
-    private int mIconSize;
+    private final int mIconSize;
+
+    private final CheckedTextView mTextView;
+
+    private FrameLayout mActionArea;
+
     private MenuItemImpl mItemData;
+
     private ColorStateList mIconTintList;
 
     public NavigationMenuItemView(Context context) {
@@ -52,8 +63,14 @@
 
     public NavigationMenuItemView(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
+        setOrientation(HORIZONTAL);
+        LayoutInflater.from(context).inflate(R.layout.design_navigation_menu_item, this, true);
         mIconSize = context.getResources().getDimensionPixelSize(
                 R.dimen.design_navigation_icon_size);
+        mTextView = (CheckedTextView) findViewById(R.id.design_menu_item_text);
+        mTextView.setDuplicateParentStateEnabled(true);
+        // Prevent the action view from stealing the event on the item row.
+        setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS);
     }
 
     @Override
@@ -71,6 +88,18 @@
         setEnabled(itemData.isEnabled());
         setTitle(itemData.getTitle());
         setIcon(itemData.getIcon());
+        setActionView(itemData.getActionView());
+    }
+
+    private void setActionView(View actionView) {
+        if (mActionArea == null) {
+            mActionArea = (FrameLayout) ((ViewStub) findViewById(
+                    R.id.design_menu_item_action_area_stub)).inflate();
+        }
+        mActionArea.removeAllViews();
+        if (actionView != null) {
+            mActionArea.addView(actionView);
+        }
     }
 
     private StateListDrawable createDefaultBackground() {
@@ -91,7 +120,7 @@
 
     @Override
     public void setTitle(CharSequence title) {
-        setText(title);
+        mTextView.setText(title);
     }
 
     @Override
@@ -102,6 +131,7 @@
     @Override
     public void setChecked(boolean checked) {
         refreshDrawableState();
+        mTextView.setChecked(checked);
     }
 
     @Override
@@ -115,7 +145,7 @@
             icon.setBounds(0, 0, mIconSize, mIconSize);
             DrawableCompat.setTintList(icon, mIconTintList);
         }
-        TextViewCompat.setCompoundDrawablesRelative(this, icon, null, null, null);
+        TextViewCompat.setCompoundDrawablesRelative(mTextView, icon, null, null, null);
     }
 
     @Override
@@ -144,4 +174,13 @@
             setIcon(mItemData.getIcon());
         }
     }
+
+    public void setTextAppearance(Context context, int textAppearance) {
+        mTextView.setTextAppearance(context, textAppearance);
+    }
+
+    public void setTextColor(ColorStateList colors) {
+        mTextView.setTextColor(colors);
+    }
+
 }
diff --git a/design/src/android/support/design/internal/NavigationMenuPresenter.java b/design/src/android/support/design/internal/NavigationMenuPresenter.java
index e523c38..41b361b 100644
--- a/design/src/android/support/design/internal/NavigationMenuPresenter.java
+++ b/design/src/android/support/design/internal/NavigationMenuPresenter.java
@@ -266,6 +266,7 @@
 
         private static final String STATE_CHECKED_ITEM = "android:menu:checked";
 
+        private static final String STATE_ACTION_VIEWS = "android:menu:action_views";
         private static final int VIEW_TYPE_NORMAL = 0;
         private static final int VIEW_TYPE_SUBHEADER = 1;
         private static final int VIEW_TYPE_SEPARATOR = 2;
@@ -470,6 +471,18 @@
             if (mCheckedItem != null) {
                 state.putInt(STATE_CHECKED_ITEM, mCheckedItem.getItemId());
             }
+            // Store the states of the action views.
+            SparseArray<ParcelableSparseArray> actionViewStates = new SparseArray<>();
+            for (NavigationMenuItem navigationMenuItem : mItems) {
+                MenuItemImpl item = navigationMenuItem.getMenuItem();
+                View actionView = item != null ? item.getActionView() : null;
+                if (actionView != null) {
+                    ParcelableSparseArray container = new ParcelableSparseArray();
+                    actionView.saveHierarchyState(container);
+                    actionViewStates.put(item.getItemId(), container);
+                }
+            }
+            state.putSparseParcelableArray(STATE_ACTION_VIEWS, actionViewStates);
             return state;
         }
 
@@ -479,7 +492,7 @@
                 mUpdateSuspended = true;
                 for (NavigationMenuItem item : mItems) {
                     MenuItemImpl menuItem = item.getMenuItem();
-                    if (menuItem !=  null && menuItem.getItemId() == checkedItem) {
+                    if (menuItem != null && menuItem.getItemId() == checkedItem) {
                         setCheckedItem(menuItem);
                         break;
                     }
@@ -487,6 +500,16 @@
                 mUpdateSuspended = false;
                 prepareMenuItems();
             }
+            // Restore the states of the action views.
+            SparseArray<ParcelableSparseArray> actionViewStates = state
+                    .getSparseParcelableArray(STATE_ACTION_VIEWS);
+            for (NavigationMenuItem navigationMenuItem : mItems) {
+                MenuItemImpl item = navigationMenuItem.getMenuItem();
+                View actionView = item != null ? item.getActionView() : null;
+                if (actionView != null) {
+                    actionView.restoreHierarchyState(actionViewStates.get(item.getItemId()));
+                }
+            }
         }
 
         public void setUpdateSuspended(boolean updateSuspended) {
diff --git a/design/src/android/support/design/internal/ParcelableSparseArray.java b/design/src/android/support/design/internal/ParcelableSparseArray.java
new file mode 100644
index 0000000..74abcc2
--- /dev/null
+++ b/design/src/android/support/design/internal/ParcelableSparseArray.java
@@ -0,0 +1,76 @@
+/*
+ * 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.design.internal;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.SparseArray;
+
+/**
+ * @hide
+ */
+public class ParcelableSparseArray extends SparseArray<Parcelable> implements Parcelable {
+
+    public ParcelableSparseArray() {
+        super();
+    }
+
+    public ParcelableSparseArray(Parcel source) {
+        super();
+        int size = source.readInt();
+        int[] keys = new int[size];
+        source.readIntArray(keys);
+        Parcelable[] values = source.readParcelableArray(
+                ParcelableSparseArray.class.getClassLoader());
+        for (int i = 0; i < size; ++i) {
+            put(keys[i], values[i]);
+        }
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        int size = size();
+        int[] keys = new int[size];
+        Parcelable[] values = new Parcelable[size];
+        for (int i = 0; i < size; ++i) {
+            keys[i] = keyAt(i);
+            values[i] = valueAt(i);
+        }
+        parcel.writeInt(size);
+        parcel.writeIntArray(keys);
+        parcel.writeParcelableArray(values, flags);
+    }
+
+    public static final Parcelable.Creator<ParcelableSparseArray> CREATOR
+            = new Creator<ParcelableSparseArray>() {
+        @Override
+        public ParcelableSparseArray createFromParcel(Parcel source) {
+            return new ParcelableSparseArray(source);
+        }
+
+        @Override
+        public ParcelableSparseArray[] newArray(int size) {
+            return new ParcelableSparseArray[size];
+        }
+    };
+
+}
diff --git a/design/src/android/support/design/widget/TextInputLayout.java b/design/src/android/support/design/widget/TextInputLayout.java
index a3d8dcd..2826344 100644
--- a/design/src/android/support/design/widget/TextInputLayout.java
+++ b/design/src/android/support/design/widget/TextInputLayout.java
@@ -95,7 +95,7 @@
 
         final TypedArray a = context.obtainStyledAttributes(attrs,
                 R.styleable.TextInputLayout, defStyleAttr, R.style.Widget_Design_TextInputLayout);
-        mHint = a.getText(R.styleable.TextInputLayout_android_hint);
+        setHint(a.getText(R.styleable.TextInputLayout_android_hint));
         mHintAnimationEnabled = a.getBoolean(
                 R.styleable.TextInputLayout_hintAnimationEnabled, true);
 
diff --git a/v17/leanback/Android.mk b/v17/leanback/Android.mk
index dd03d6a..57b54e0 100644
--- a/v17/leanback/Android.mk
+++ b/v17/leanback/Android.mk
@@ -40,6 +40,16 @@
 
 # -----------------------------------------------------------------------
 
+#  A helper sub-library that makes direct use of API 23.
+include $(CLEAR_VARS)
+LOCAL_MODULE := android-support-v17-leanback-api23
+LOCAL_SDK_VERSION := current
+LOCAL_SRC_FILES := $(call all-java-files-under, api23)
+LOCAL_JAVA_LIBRARIES := android-support-v17-leanback-res android-support-v17-leanback-common
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# -----------------------------------------------------------------------
+
 #  A helper sub-library that makes direct use of API 21.
 include $(CLEAR_VARS)
 LOCAL_MODULE := android-support-v17-leanback-api21
@@ -79,6 +89,7 @@
 LOCAL_SDK_VERSION := 17
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-v17-leanback-kitkat android-support-v17-leanback-jbmr2 \
+        android-support-v17-leanback-api23 \
         android-support-v17-leanback-api21 android-support-v17-leanback-common
 LOCAL_JAVA_LIBRARIES := \
         android-support-v4 \
diff --git a/v17/leanback/api/current.txt b/v17/leanback/api/current.txt
index d25529c..388ce92 100644
--- a/v17/leanback/api/current.txt
+++ b/v17/leanback/api/current.txt
@@ -189,6 +189,7 @@
     method public android.support.v17.leanback.widget.GuidanceStylist.Guidance onCreateGuidance(android.os.Bundle);
     method public android.support.v17.leanback.widget.GuidanceStylist onCreateGuidanceStylist();
     method public void onGuidedActionClicked(android.support.v17.leanback.widget.GuidedAction);
+    method public void onGuidedActionEdited(android.support.v17.leanback.widget.GuidedAction);
     method public void onGuidedActionFocused(android.support.v17.leanback.widget.GuidedAction);
     method public int onProvideTheme();
     method public void setActions(java.util.List<android.support.v17.leanback.widget.GuidedAction>);
@@ -744,6 +745,8 @@
     method public abstract void onFragmentExit(java.util.List<android.animation.Animator>);
     method public abstract void onFragmentReenter(java.util.List<android.animation.Animator>);
     method public abstract void onFragmentReturn(java.util.List<android.animation.Animator>);
+    method public abstract void onImeAppearing(java.util.List<android.animation.Animator>);
+    method public abstract void onImeDisappearing(java.util.List<android.animation.Animator>);
   }
 
   public class FullWidthDetailsOverviewRowPresenter extends android.support.v17.leanback.widget.RowPresenter {
@@ -821,6 +824,8 @@
     method public void onFragmentExit(java.util.List<android.animation.Animator>);
     method public void onFragmentReenter(java.util.List<android.animation.Animator>);
     method public void onFragmentReturn(java.util.List<android.animation.Animator>);
+    method public void onImeAppearing(java.util.List<android.animation.Animator>);
+    method public void onImeDisappearing(java.util.List<android.animation.Animator>);
     method public int onProvideLayoutId();
   }
 
@@ -841,9 +846,11 @@
     method public boolean hasNext();
     method public boolean infoOnly();
     method public boolean isChecked();
+    method public boolean isEditable();
     method public boolean isEnabled();
     method public void setChecked(boolean);
     method public void setEnabled(boolean);
+    method public void setTitle(java.lang.CharSequence);
     field public static final int DEFAULT_CHECK_SET_ID = 1; // 0x1
     field public static final int NO_CHECK_SET = 0; // 0x0
     field public static final int NO_DRAWABLE = 0; // 0x0
@@ -855,6 +862,7 @@
     method public android.support.v17.leanback.widget.GuidedAction.Builder checkSetId(int);
     method public android.support.v17.leanback.widget.GuidedAction.Builder checked(boolean);
     method public android.support.v17.leanback.widget.GuidedAction.Builder description(java.lang.String);
+    method public android.support.v17.leanback.widget.GuidedAction.Builder editable(boolean);
     method public android.support.v17.leanback.widget.GuidedAction.Builder enabled(boolean);
     method public android.support.v17.leanback.widget.GuidedAction.Builder hasNext(boolean);
     method public android.support.v17.leanback.widget.GuidedAction.Builder icon(android.graphics.drawable.Drawable);
@@ -881,6 +889,8 @@
     method public void onFragmentExit(java.util.List<android.animation.Animator>);
     method public void onFragmentReenter(java.util.List<android.animation.Animator>);
     method public void onFragmentReturn(java.util.List<android.animation.Animator>);
+    method public void onImeAppearing(java.util.List<android.animation.Animator>);
+    method public void onImeDisappearing(java.util.List<android.animation.Animator>);
     method public int onProvideItemLayoutId();
     method public int onProvideLayoutId();
     field protected android.support.v17.leanback.widget.VerticalGridView mActionsGridView;
@@ -934,9 +944,10 @@
   }
 
   public class ImageCardView extends android.support.v17.leanback.widget.BaseCardView {
+    ctor public ImageCardView(android.content.Context, int);
+    ctor public ImageCardView(android.content.Context, android.util.AttributeSet, int);
     ctor public ImageCardView(android.content.Context);
     ctor public ImageCardView(android.content.Context, android.util.AttributeSet);
-    ctor public ImageCardView(android.content.Context, android.util.AttributeSet, int);
     method public android.graphics.drawable.Drawable getBadgeImage();
     method public java.lang.CharSequence getContentText();
     method public android.graphics.drawable.Drawable getInfoAreaBackground();
@@ -953,6 +964,19 @@
     method public void setMainImageDimensions(int, int);
     method public void setMainImageScaleType(android.widget.ImageView.ScaleType);
     method public void setTitleText(java.lang.CharSequence);
+    field public static final int CARD_TYPE_FLAG_CONTENT = 2; // 0x2
+    field public static final int CARD_TYPE_FLAG_ICON_LEFT = 8; // 0x8
+    field public static final int CARD_TYPE_FLAG_ICON_RIGHT = 4; // 0x4
+    field public static final int CARD_TYPE_FLAG_IMAGE_ONLY = 0; // 0x0
+    field public static final int CARD_TYPE_FLAG_TITLE = 1; // 0x1
+  }
+
+  public abstract interface ImeKeyMonitor {
+    method public abstract void setImeKeyListener(android.support.v17.leanback.widget.ImeKeyMonitor.ImeKeyListener);
+  }
+
+  public static abstract interface ImeKeyMonitor.ImeKeyListener {
+    method public abstract boolean onKeyPreIme(android.widget.EditText, int, android.view.KeyEvent);
   }
 
   public final class ItemAlignmentFacet {
@@ -1463,10 +1487,12 @@
     ctor public ShadowOverlayContainer(android.content.Context);
     ctor public ShadowOverlayContainer(android.content.Context, android.util.AttributeSet);
     ctor public ShadowOverlayContainer(android.content.Context, android.util.AttributeSet, int);
+    ctor public ShadowOverlayContainer(android.content.Context, int, boolean, boolean);
     method public int getShadowType();
     method public android.view.View getWrappedView();
     method public deprecated void initialize(boolean, boolean);
-    method public void initialize(boolean, boolean, boolean);
+    method public deprecated void initialize(boolean, boolean, boolean);
+    method public void initialize(int, boolean, boolean);
     method protected void onLayout(boolean, int, int, int, int);
     method public static void prepareParentForShadow(android.view.ViewGroup);
     method public void setOverlayColor(int);
diff --git a/v17/leanback/api21/android/support/v17/leanback/widget/ShadowHelperApi21.java b/v17/leanback/api21/android/support/v17/leanback/widget/ShadowHelperApi21.java
index ab4d179..cd4ff3e 100644
--- a/v17/leanback/api21/android/support/v17/leanback/widget/ShadowHelperApi21.java
+++ b/v17/leanback/api21/android/support/v17/leanback/widget/ShadowHelperApi21.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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
@@ -19,14 +19,14 @@
 import android.graphics.Outline;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
-import android.view.ViewGroup;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.ViewOutlineProvider;
 
 class ShadowHelperApi21 {
 
     static class ShadowImpl {
-        ViewGroup mShadowContainer;
+        View mShadowContainer;
         float mNormalZ;
         float mFocusedZ;
     }
@@ -41,7 +41,7 @@
 
     /* add shadows and return a implementation detail object */
     public static Object addDynamicShadow(
-            ViewGroup shadowContainer, float unfocusedZ, float focusedZ, boolean roundedCorners) {
+            View shadowContainer, float unfocusedZ, float focusedZ, boolean roundedCorners) {
         if (roundedCorners) {
             RoundedRectHelperApi21.setClipToRoundedOutline(shadowContainer, true);
         } else {
@@ -52,7 +52,9 @@
         impl.mNormalZ = unfocusedZ;
         impl.mFocusedZ = focusedZ;
         shadowContainer.setZ(impl.mNormalZ);
-        shadowContainer.setTransitionGroup(true);
+        if (shadowContainer instanceof ViewGroup) {
+            ((ViewGroup) shadowContainer).setTransitionGroup(true);
+        }
         return impl;
     }
 
diff --git a/v17/leanback/api23/android/support/v17/leanback/widget/ForegroundHelperApi23.java b/v17/leanback/api23/android/support/v17/leanback/widget/ForegroundHelperApi23.java
new file mode 100644
index 0000000..c4760d4
--- /dev/null
+++ b/v17/leanback/api23/android/support/v17/leanback/widget/ForegroundHelperApi23.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package android.support.v17.leanback.widget;
+
+import android.support.v17.leanback.R;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.Outline;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.view.ViewGroup;
+import android.view.View;
+import android.view.ViewOutlineProvider;
+
+class ForegroundHelperApi23 {
+
+    public static Drawable getForeground(View view) {
+        return view.getForeground();
+    }
+
+    public static void setForeground(View view, Drawable drawable) {
+        view.setForeground(drawable);
+    }
+}
diff --git a/v17/leanback/build.gradle b/v17/leanback/build.gradle
index 8dc79e8..401a5c4 100644
--- a/v17/leanback/build.gradle
+++ b/v17/leanback/build.gradle
@@ -19,8 +19,8 @@
 
     sourceSets {
         main.manifest.srcFile 'AndroidManifest.xml'
-        main.java.srcDirs = ['common', 'jbmr2', 'kitkat', 'api21', 'src']
-        main.aidl.srcDirs = ['common', 'jbmr2', 'kitkat', 'api21', 'src']
+        main.java.srcDirs = ['common', 'jbmr2', 'kitkat', 'api21', 'api23', 'src']
+        main.aidl.srcDirs = ['common', 'jbmr2', 'kitkat', 'api21', 'api23', 'src']
         main.res.srcDirs = ['res']
 
         androidTest.setRoot('tests')
diff --git a/v17/leanback/res/layout/lb_card_color_overlay.xml b/v17/leanback/res/animator/lb_guidedstep_slide_down.xml
similarity index 62%
copy from v17/leanback/res/layout/lb_card_color_overlay.xml
copy to v17/leanback/res/animator/lb_guidedstep_slide_down.xml
index 45a40e1..b31421f 100644
--- a/v17/leanback/res/layout/lb_card_color_overlay.xml
+++ b/v17/leanback/res/animator/lb_guidedstep_slide_down.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-     Copyright (C) 2014 The Android Open Source Project
+     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.
@@ -14,8 +14,9 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
-<View
-      xmlns:android="http://schemas.android.com/apk/res/android"
-      android:layout_width="match_parent"
-      android:layout_height="match_parent" />
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:duration="@android:integer/config_shortAnimTime"
+    android:propertyName="translationY"
+    android:valueFrom="@dimen/lb_guidedstep_slide_ime_distance"
+    android:valueTo="0.0"
+    android:valueType="floatType" />
diff --git a/v17/leanback/res/layout/lb_card_color_overlay.xml b/v17/leanback/res/animator/lb_guidedstep_slide_up.xml
similarity index 62%
copy from v17/leanback/res/layout/lb_card_color_overlay.xml
copy to v17/leanback/res/animator/lb_guidedstep_slide_up.xml
index 45a40e1..165fe18 100644
--- a/v17/leanback/res/layout/lb_card_color_overlay.xml
+++ b/v17/leanback/res/animator/lb_guidedstep_slide_up.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-     Copyright (C) 2014 The Android Open Source Project
+     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.
@@ -14,8 +14,9 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
-<View
-      xmlns:android="http://schemas.android.com/apk/res/android"
-      android:layout_width="match_parent"
-      android:layout_height="match_parent" />
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:duration="@android:integer/config_shortAnimTime"
+    android:propertyName="translationY"
+    android:valueFrom="0.0"
+    android:valueTo="@dimen/lb_guidedstep_slide_ime_distance"
+    android:valueType="floatType" />
diff --git a/v17/leanback/res/layout/lb_guidedactions_item.xml b/v17/leanback/res/layout/lb_guidedactions_item.xml
index 4e41454..1d81470 100644
--- a/v17/leanback/res/layout/lb_guidedactions_item.xml
+++ b/v17/leanback/res/layout/lb_guidedactions_item.xml
@@ -34,7 +34,7 @@
         android:id="@+id/guidedactions_item_content"
         style="?attr/guidedActionItemContentStyle" >
 
-        <TextView
+        <android.support.v17.leanback.widget.LeanbackEditText
             android:id="@+id/guidedactions_item_title"
             style="?attr/guidedActionItemTitleStyle" />
 
diff --git a/v17/leanback/res/layout/lb_image_card_view.xml b/v17/leanback/res/layout/lb_image_card_view.xml
index 2261965..1bc23f8 100644
--- a/v17/leanback/res/layout/lb_image_card_view.xml
+++ b/v17/leanback/res/layout/lb_image_card_view.xml
@@ -15,59 +15,16 @@
      limitations under the License.
 -->
 
-<merge
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:lb="http://schemas.android.com/apk/res-auto">
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:lb="http://schemas.android.com/apk/res-auto" >
 
     <ImageView
         android:id="@+id/main_image"
-        lb:layout_viewType="main"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:scaleType="centerCrop"
-        android:adjustViewBounds="true"
-        android:contentDescription="@null" />
-        <android.support.v17.leanback.widget.NonOverlappingRelativeLayout
-            lb:layout_viewType="info"
-            android:id="@+id/info_field"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/lb_basic_card_info_height"
-            android:paddingStart="@dimen/lb_basic_card_info_padding_horizontal"
-            android:paddingEnd="@dimen/lb_basic_card_info_padding_horizontal"
-            android:paddingTop="@dimen/lb_basic_card_info_padding_top"
-            android:layout_centerHorizontal="true" >
-            <TextView
-                android:id="@+id/title_text"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_alignParentStart="true"
-                android:layout_marginBottom="@dimen/lb_basic_card_info_text_margin"
-                android:maxLines="1"
-                android:fontFamily="sans-serif-condensed"
-                android:textColor="@color/lb_basic_card_title_text_color"
-                android:textSize="@dimen/lb_basic_card_title_text_size"
-                android:ellipsize="end" />
-            <TextView
-                android:id="@+id/content_text"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_below="@id/title_text"
-                android:layout_alignParentStart="true"
-                android:layout_toStartOf="@+id/extra_badge"
-                android:maxLines="1"
-                android:fontFamily="sans-serif-condensed"
-                android:textColor="@color/lb_basic_card_content_text_color"
-                android:textSize="@dimen/lb_basic_card_content_text_size"
-                android:ellipsize="none" />
-            <ImageView
-                android:id="@+id/extra_badge"
-                android:layout_width="@dimen/lb_basic_card_info_badge_size"
-                android:layout_height="@dimen/lb_basic_card_info_badge_size"
-                android:layout_marginStart="@dimen/lb_basic_card_info_badge_margin"
-                android:layout_alignBottom="@id/content_text"
-                android:layout_alignParentEnd="true"
-                android:scaleType="fitCenter"
-                android:visibility="gone"
-                android:contentDescription="@null" />
-        </android.support.v17.leanback.widget.NonOverlappingRelativeLayout>
-</merge>
+        style="?attr/lbImageCardViewImageStyle" />
+
+    <android.support.v17.leanback.widget.NonOverlappingRelativeLayout
+        android:id="@+id/info_field"
+        style="?attr/lbImageCardViewInfoAreaStyle">
+    </android.support.v17.leanback.widget.NonOverlappingRelativeLayout>
+
+</merge>
\ No newline at end of file
diff --git a/v17/leanback/res/layout/lb_card_color_overlay.xml b/v17/leanback/res/layout/lb_image_card_view_themed_badge_left.xml
similarity index 68%
copy from v17/leanback/res/layout/lb_card_color_overlay.xml
copy to v17/leanback/res/layout/lb_image_card_view_themed_badge_left.xml
index 45a40e1..35d2da6 100644
--- a/v17/leanback/res/layout/lb_card_color_overlay.xml
+++ b/v17/leanback/res/layout/lb_image_card_view_themed_badge_left.xml
@@ -15,7 +15,9 @@
      limitations under the License.
 -->
 
-<View
-      xmlns:android="http://schemas.android.com/apk/res/android"
-      android:layout_width="match_parent"
-      android:layout_height="match_parent" />
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/extra_badge"
+    android:layout_alignBottom="@+id/content_text"
+    android:layout_alignParentStart="true"
+    android:layout_marginEnd="@dimen/lb_basic_card_info_badge_margin"
+    style="?attr/lbImageCardViewBadgeStyle" />
\ No newline at end of file
diff --git a/v17/leanback/res/layout/lb_card_color_overlay.xml b/v17/leanback/res/layout/lb_image_card_view_themed_badge_right.xml
similarity index 68%
copy from v17/leanback/res/layout/lb_card_color_overlay.xml
copy to v17/leanback/res/layout/lb_image_card_view_themed_badge_right.xml
index 45a40e1..02dd917 100644
--- a/v17/leanback/res/layout/lb_card_color_overlay.xml
+++ b/v17/leanback/res/layout/lb_image_card_view_themed_badge_right.xml
@@ -15,7 +15,9 @@
      limitations under the License.
 -->
 
-<View
-      xmlns:android="http://schemas.android.com/apk/res/android"
-      android:layout_width="match_parent"
-      android:layout_height="match_parent" />
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/extra_badge"
+    android:layout_alignBottom="@+id/content_text"
+    android:layout_alignParentEnd="true"
+    android:layout_marginStart="@dimen/lb_basic_card_info_badge_margin"
+    style="?attr/lbImageCardViewBadgeStyle" />
\ No newline at end of file
diff --git a/v17/leanback/res/layout/lb_card_color_overlay.xml b/v17/leanback/res/layout/lb_image_card_view_themed_content.xml
similarity index 80%
rename from v17/leanback/res/layout/lb_card_color_overlay.xml
rename to v17/leanback/res/layout/lb_image_card_view_themed_content.xml
index 45a40e1..5592371 100644
--- a/v17/leanback/res/layout/lb_card_color_overlay.xml
+++ b/v17/leanback/res/layout/lb_image_card_view_themed_content.xml
@@ -15,7 +15,6 @@
      limitations under the License.
 -->
 
-<View
-      xmlns:android="http://schemas.android.com/apk/res/android"
-      android:layout_width="match_parent"
-      android:layout_height="match_parent" />
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/content_text"
+    style="?attr/lbImageCardViewContentStyle" />
diff --git a/v17/leanback/res/layout/lb_card_color_overlay.xml b/v17/leanback/res/layout/lb_image_card_view_themed_title.xml
similarity index 80%
copy from v17/leanback/res/layout/lb_card_color_overlay.xml
copy to v17/leanback/res/layout/lb_image_card_view_themed_title.xml
index 45a40e1..67e2493 100644
--- a/v17/leanback/res/layout/lb_card_color_overlay.xml
+++ b/v17/leanback/res/layout/lb_image_card_view_themed_title.xml
@@ -15,7 +15,6 @@
      limitations under the License.
 -->
 
-<View
-      xmlns:android="http://schemas.android.com/apk/res/android"
-      android:layout_width="match_parent"
-      android:layout_height="match_parent" />
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/title_text"
+    style="?attr/lbImageCardViewTitleStyle" />
diff --git a/v17/leanback/res/values-az-rAZ/strings.xml b/v17/leanback/res/values-az-rAZ/strings.xml
deleted file mode 100644
index d1e685f..0000000
--- a/v17/leanback/res/values-az-rAZ/strings.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-Copyright (C) 2014 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="orb_search_action" msgid="5651268540267663887">"Axtarış Fəaliyyəti"</string>
-    <string name="lb_search_bar_hint" msgid="8325490927970116252">"Axtarış"</string>
-    <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Axtarış üçün danışın"</string>
-    <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Axtarış: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
-    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Axtarış üçün danışın: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
-    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
-    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
-    <string name="lb_playback_controls_play" msgid="731953341987346903">"Oyun"</string>
-    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Pauza"</string>
-    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"İrəli Ötürmə"</string>
-    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"İrəli sarı %1$dX"</string>
-    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Geri ötürmə"</string>
-    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Geri sarı %1$dX"</string>
-    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Növbətini atlayın"</string>
-    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Öncəkini atlayın"</string>
-    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Digər fəaliyyətlər"</string>
-    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Bəyənməkdən imtina edin"</string>
-    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Bəyənin"</string>
-    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Bəyənməməkdən imtina edin"</string>
-    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Bəyənməyin"</string>
-    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Təkrarlanmasın"</string>
-    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Hamısını təkrarlayın"</string>
-    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Biri təkrarlansın"</string>
-    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Qarışdırma aktiv edilsin"</string>
-    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Qarışdırma deaktiv edilsin"</string>
-    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Yüksək keyfiyyəti aktiv edin"</string>
-    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Yüksək keyfiyyəti deaktiv edin"</string>
-    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Qapalı çəkilişi aktiv edin"</string>
-    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Qapalı çəkilişi deaktiv edin"</string>
-</resources>
diff --git a/v17/leanback/res/values/attrs.xml b/v17/leanback/res/values/attrs.xml
index e7da321..10ee282 100644
--- a/v17/leanback/res/values/attrs.xml
+++ b/v17/leanback/res/values/attrs.xml
@@ -49,6 +49,10 @@
     </declare-styleable>
 
     <declare-styleable name="lbBaseCardView">
+        <!-- Defines the background of card -->
+        <attr name="cardForeground" format="reference|color"/>
+        <!-- Defines the background of card -->
+        <attr name="cardBackground" format="reference|color"/>
         <!-- Defines the type of the card layout -->
         <attr name="cardType" format="enum">
             <!-- A simple card layout with a single layout region. -->
@@ -116,7 +120,23 @@
     </declare-styleable>
 
     <declare-styleable name="lbImageCardView">
+        <!-- Deprecated. Use 'lbImageCardViewInfoAreaStyle' instead. -->
         <attr name="infoAreaBackground" format="reference|color"/>
+        <!-- Use these attributes to override a ImageCardView's component style. -->
+        <attr name="lbImageCardViewImageStyle" format="reference" />
+        <attr name="lbImageCardViewTitleStyle" format="reference" />
+        <attr name="lbImageCardViewContentStyle" format="reference" />
+        <attr name="lbImageCardViewBadgeStyle" format="reference" />
+        <attr name="lbImageCardViewInfoAreaStyle" format="reference" />
+        <!-- Defines what components the ImageCardView will use. -->
+        <attr name="lbImageCardViewType">
+            <flag name="Title" value="1" />
+            <flag name="Content" value="2" />
+            <flag name="IconOnRight" value="4" />
+            <flag name="IconOnLeft" value="8" />
+            <!-- Only display the main image. -->
+            <flag name="ImageOnly" value="0" />
+        </attr>
     </declare-styleable>
 
     <declare-styleable name="lbSearchOrbView">
@@ -308,6 +328,14 @@
              fragment stack pop. Default is {@link
              android.support.v17.leanback.R.animator#lb_guidedstep_slide_out_to_end}. -->
         <attr name="guidedStepReturnAnimation" format="reference" />
+        <!-- Theme attribute for the animation used when a guided step element is animated in
+             response to the IME appearing. Default is {@link
+             android.support.v17.leanback.R.animator#lb_guidedstep_slide_up}. -->
+        <attr name="guidedStepImeAppearingAnimation" format="reference" />
+        <!-- Theme attribute for the animation used when a guided step element is animated in
+             response to the IME disappearing. Default is {@link
+             android.support.v17.leanback.R.animator#lb_guidedstep_slide_down}. -->
+        <attr name="guidedStepImeDisappearingAnimation" format="reference" />
 
         <!-- Theme attribute for the animation used when the guidance is animated in at activity
              start. Default is {@link android.support.v17.leanback.R.animator#lb_guidance_entry}.
@@ -431,4 +459,4 @@
 
     </declare-styleable>
 
-</resources>
+</resources>
\ No newline at end of file
diff --git a/v17/leanback/res/values/dimens.xml b/v17/leanback/res/values/dimens.xml
index 275612e..a05a6fc 100644
--- a/v17/leanback/res/values/dimens.xml
+++ b/v17/leanback/res/values/dimens.xml
@@ -203,6 +203,7 @@
     <dimen name="lb_basic_card_info_height">52dp</dimen>
     <dimen name="lb_basic_card_info_height_no_content">34dp</dimen>
     <dimen name="lb_basic_card_info_padding_top">7dp</dimen>
+    <dimen name="lb_basic_card_info_padding_bottom">8dp</dimen>
     <dimen name="lb_basic_card_info_padding_horizontal">11dp</dimen>
     <dimen name="lb_basic_card_info_text_margin">1dp</dimen>
     <dimen name="lb_basic_card_title_text_size">14sp</dimen>
@@ -226,6 +227,7 @@
     <dimen name="lb_guidedstep_guidance_section_width">576dp</dimen>
     <dimen name="lb_guidedstep_slide_start_distance">-200dp</dimen>
     <dimen name="lb_guidedstep_slide_end_distance">200dp</dimen>
+    <dimen name="lb_guidedstep_slide_ime_distance">-100dp</dimen>
 
     <dimen name="lb_guidance_entry_translationX">-120dp</dimen>
 
diff --git a/v17/leanback/res/values/ids.xml b/v17/leanback/res/values/ids.xml
index 6b67919..d4ba288 100644
--- a/v17/leanback/res/values/ids.xml
+++ b/v17/leanback/res/values/ids.xml
@@ -16,6 +16,7 @@
 -->
  <resources>
      <item type="id" name="lb_focus_animator" />
+     <item type="id" name="lb_shadow_impl" />
      <item type="id" name="lb_slide_transition_value" />
 
      <item type="id" name="lb_control_play_pause" />
@@ -30,5 +31,4 @@
      <item type="id" name="lb_control_shuffle" />
      <item type="id" name="lb_control_high_quality" />
      <item type="id" name="lb_control_closed_captioning" />
-
  </resources>
diff --git a/v17/leanback/res/values/styles.xml b/v17/leanback/res/values/styles.xml
index 3ee2821..204c0ee 100644
--- a/v17/leanback/res/values/styles.xml
+++ b/v17/leanback/res/values/styles.xml
@@ -87,14 +87,8 @@
     <style name="Widget.Leanback" parent="Widget.LeanbackBase" />
 
     <style name="Widget.Leanback.BaseCardViewStyle">
-        <item name="android:foreground">@drawable/lb_card_foreground</item>
-    </style>
-
-    <style name="Widget.Leanback.ImageCardViewStyle" parent="Widget.Leanback.BaseCardViewStyle">
-        <item name="cardType">infoUnder</item>
-        <item name="infoVisibility">activated</item>
-        <item name="android:background">@color/lb_basic_card_bg_color</item>
-        <item name="infoAreaBackground">@color/lb_basic_card_info_bg_color</item>
+        <item name="cardForeground">@drawable/lb_card_foreground</item>
+        <item name="cardBackground">@color/lb_basic_card_bg_color</item>
     </style>
 
     <style name="Widget.Leanback.TitleView" >
@@ -104,6 +98,77 @@
         <item name="android:paddingEnd">?attr/browsePaddingEnd</item>
     </style>
 
+    <style name="Widget.Leanback.ImageCardViewStyle" parent="Widget.Leanback.BaseCardViewStyle">
+        <item name="cardType">infoUnder</item>
+        <item name="infoVisibility">activated</item>
+        <!-- In order to keep backward compatibility we have to create an icon on right. -->
+        <item name="lbImageCardViewType">Title|Content|IconOnRight</item>
+        <item name="lbImageCardViewImageStyle">@style/Widget.Leanback.ImageCardView.ImageStyle</item>
+        <item name="lbImageCardViewTitleStyle">@style/Widget.Leanback.ImageCardView.TitleStyle</item>
+        <item name="lbImageCardViewContentStyle">@style/Widget.Leanback.ImageCardView.ContentStyle</item>
+        <item name="lbImageCardViewBadgeStyle">@style/Widget.Leanback.ImageCardView.BadgeStyle</item>
+        <item name="lbImageCardViewInfoAreaStyle">@style/Widget.Leanback.ImageCardView.InfoAreaStyle</item>
+        <!-- Deprecated. Use 'Widget.Leanback.ImageCardView.InfoAreaStyle' instead. -->
+        <item name="infoAreaBackground">@null</item>
+    </style>
+
+    <style name="Widget.Leanback.ImageCardView" />
+
+    <style name="Widget.Leanback.ImageCardView.ImageStyle">
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:adjustViewBounds">true</item>
+        <item name="android:contentDescription">@null</item>
+        <item name="android:scaleType">centerCrop</item>
+        <item name="layout_viewType">main</item>
+    </style>
+
+    <style name="Widget.Leanback.ImageCardView.InfoAreaStyle">
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:layout_centerHorizontal">true</item>
+        <item name="layout_viewType">info</item>
+        <item name="android:paddingBottom">@dimen/lb_basic_card_info_padding_bottom</item>
+        <item name="android:paddingEnd">@dimen/lb_basic_card_info_padding_horizontal</item>
+        <item name="android:paddingStart">@dimen/lb_basic_card_info_padding_horizontal</item>
+        <item name="android:paddingTop">@dimen/lb_basic_card_info_padding_top</item>
+        <item name="android:background">@color/lb_basic_card_info_bg_color</item>
+    </style>
+	
+    <style name="Widget.Leanback.ImageCardView.TitleStyle">
+        <item name="android:id">@id/title_text</item>
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:maxLines">1</item>
+        <item name="android:layout_marginBottom">@dimen/lb_basic_card_info_text_margin</item>
+        <item name="android:fontFamily">sans-serif-condensed</item>
+        <item name="android:textColor">@color/lb_basic_card_title_text_color</item>
+        <item name="android:textSize">@dimen/lb_basic_card_title_text_size</item>
+        <item name="android:ellipsize">end</item>
+    </style>
+
+    <style name="Widget.Leanback.ImageCardView.ContentStyle">
+        <item name="android:id">@id/content_text</item>
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:layout_alignParentStart">true</item>
+        <item name="android:layout_below">@+id/title_text</item>
+        <item name="android:layout_toStartOf">@+id/extra_badge</item>
+        <item name="android:maxLines">1</item>
+        <item name="android:fontFamily">sans-serif-condensed</item>
+        <item name="android:textColor">@color/lb_basic_card_content_text_color</item>
+        <item name="android:textSize">@dimen/lb_basic_card_content_text_size</item>
+        <item name="android:ellipsize">none</item>
+    </style>
+
+    <style name="Widget.Leanback.ImageCardView.BadgeStyle">
+        <item name="android:id">@id/extra_badge</item>
+        <item name="android:layout_width">@dimen/lb_basic_card_info_badge_size</item>
+        <item name="android:layout_height">@dimen/lb_basic_card_info_badge_size</item>
+        <item name="android:contentDescription">@null</item>
+        <item name="android:scaleType">fitCenter</item>
+    </style>
+
     <style name="Widget.Leanback.Title" />
 
     <style name="Widget.Leanback.Title.Text">
@@ -430,11 +495,13 @@
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">wrap_content</item>
         <item name="android:alpha">@string/lb_guidedactions_item_unselected_text_alpha</item>
-        <item name="android:ellipsize">marquee</item>
+        <item name="android:ellipsize">end</item>
         <item name="android:fontFamily">sans-serif-condensed</item>
         <item name="android:maxLines">@integer/lb_guidedactions_item_title_min_lines</item>
         <item name="android:textColor">@color/lb_guidedactions_item_unselected_text_color</item>
         <item name="android:textSize">@dimen/lb_guidedactions_item_title_font_size</item>
+        <item name="android:background">@null</item>
+        <item name="android:inputType">text</item>
     </style>
 
     <!-- Style for an action's description in a GuidedActionsStylist's default item layout. -->
diff --git a/v17/leanback/res/values/themes.xml b/v17/leanback/res/values/themes.xml
index 8178c50..0ded94e 100644
--- a/v17/leanback/res/values/themes.xml
+++ b/v17/leanback/res/values/themes.xml
@@ -115,6 +115,8 @@
         <item name="guidedStepExitAnimation">@animator/lb_guidedstep_slide_out_to_start</item>
         <item name="guidedStepReentryAnimation">@animator/lb_guidedstep_slide_in_from_start</item>
         <item name="guidedStepReturnAnimation">@animator/lb_guidedstep_slide_out_to_end</item>
+        <item name="guidedStepImeAppearingAnimation">@animator/lb_guidedstep_slide_up</item>
+        <item name="guidedStepImeDisappearingAnimation">@animator/lb_guidedstep_slide_down</item>
         <item name="guidanceEntryAnimation">@animator/lb_guidance_entry</item>
         <item name="guidedActionsEntryAnimation">@animator/lb_guidedactions_entry</item>
 
diff --git a/v17/leanback/src/android/support/v17/leanback/app/GuidedActionAdapter.java b/v17/leanback/src/android/support/v17/leanback/app/GuidedActionAdapter.java
index 41ecac9..1edd0d1 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/GuidedActionAdapter.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/GuidedActionAdapter.java
@@ -19,6 +19,7 @@
 import android.support.v17.leanback.R;
 import android.support.v17.leanback.widget.GuidedAction;
 import android.support.v17.leanback.widget.GuidedActionsStylist;
+import android.support.v17.leanback.widget.ImeKeyMonitor;
 import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.RecyclerView.ViewHolder;
 import android.util.Log;
@@ -26,9 +27,14 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
 import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.EditText;
 import android.widget.ImageView;
 import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -43,6 +49,9 @@
     private static final String TAG = "GuidedActionAdapter";
     private static final boolean DEBUG = false;
 
+    private static final String TAG_EDIT = "EditableAction";
+    private static final boolean DEBUG_EDIT = false;
+
     /**
      * Object listening for click events within a {@link GuidedActionAdapter}.
      */
@@ -66,6 +75,17 @@
     }
 
     /**
+     * Object listening for edit events within a {@link GuidedActionAdapter}.
+     */
+    public interface EditListener {
+
+        /**
+         * Called when the user enters or exits edit mode on an action.
+         */
+        public void onGuidedActionEdited(GuidedAction action, boolean entering);
+    }
+
+    /**
      * View holder containing a {@link GuidedAction}.
      */
     private static class ActionViewHolder extends ViewHolder {
@@ -101,6 +121,7 @@
     private RecyclerView mRecyclerView;
     private final ActionOnKeyListener mActionOnKeyListener;
     private final ActionOnFocusListener mActionOnFocusListener;
+    private final ActionEditListener mActionEditListener;
     private final List<GuidedAction> mActions;
     private ClickListener mClickListener;
     private GuidedActionsStylist mStylist;
@@ -126,13 +147,15 @@
      * @param presenter The presenter that will manage the display of items in this adapter.
      */
     public GuidedActionAdapter(List<GuidedAction> actions, ClickListener clickListener,
-            FocusListener focusListener, GuidedActionsStylist presenter) {
+            FocusListener focusListener, EditListener editListener,
+            GuidedActionsStylist presenter) {
         super();
         mActions = new ArrayList<GuidedAction>(actions);
         mClickListener = clickListener;
         mStylist = presenter;
-        mActionOnKeyListener = new ActionOnKeyListener(clickListener, mActions);
+        mActionOnKeyListener = new ActionOnKeyListener();
         mActionOnFocusListener = new ActionOnFocusListener(focusListener);
+        mActionEditListener = new ActionEditListener(editListener);
     }
 
     /**
@@ -169,7 +192,6 @@
      */
     public void setClickListener(ClickListener clickListener) {
         mClickListener = clickListener;
-        mActionOnKeyListener.setListener(clickListener);
     }
 
     /**
@@ -215,6 +237,16 @@
         v.setOnClickListener(mOnClickListener);
         v.setOnFocusChangeListener(mActionOnFocusListener);
 
+        final EditText edit = (EditText)vh.getTitleView();
+        if (edit != null) {
+            edit.setPrivateImeOptions("EscapeNorth=1;");
+            edit.setOnEditorActionListener(mActionEditListener);
+            ImeKeyMonitor monitor = (ImeKeyMonitor)edit;
+            if (monitor != null) {
+                monitor.setImeKeyListener(mActionEditListener);
+            }
+        }
+
         return new ActionViewHolder(v, vh);
     }
 
@@ -230,6 +262,13 @@
         GuidedAction action = mActions.get(position);
         avh.setAction(action);
         mStylist.onBindViewHolder(avh.mStylistViewHolder, action);
+
+        final EditText edit = (EditText)avh.mStylistViewHolder.getTitleView();
+        if (edit != null) {
+            int next = getNextEditableActionIndex(action);
+            int flag = (next == -1) ? EditorInfo.IME_ACTION_DONE : EditorInfo.IME_ACTION_NEXT;
+            edit.setImeOptions(flag);
+        }
     }
 
     /**
@@ -240,6 +279,25 @@
         return mActions.size();
     }
 
+    private int getNextEditableActionIndex(GuidedAction action) {
+        int i, size = mActions.size();
+        for (i = 0; i < size; i++) {
+            GuidedAction a = mActions.get(i);
+            if (mActions.get(i) == action) {
+                i++;
+                break;
+            }
+        }
+        for (; i < size; i++) {
+            GuidedAction a = mActions.get(i);
+            if (a.isEditable()) {
+                break;
+            }
+        }
+        int result = (i == size) ? -1 : i;
+        return result;
+    }
+
     private class ActionOnFocusListener implements View.OnFocusChangeListener {
 
         private FocusListener mFocusListener;
@@ -287,19 +345,7 @@
 
     private class ActionOnKeyListener implements View.OnKeyListener {
 
-        private final List<GuidedAction> mActions;
         private boolean mKeyPressed = false;
-        private ClickListener mClickListener;
-
-        public ActionOnKeyListener(ClickListener listener,
-                List<GuidedAction> actions) {
-            mClickListener = listener;
-            mActions = actions;
-        }
-
-        public void setListener(ClickListener listener) {
-            mClickListener = listener;
-        }
 
         private void playSound(View v, int soundEffect) {
             if (v.isSoundEffectsEnabled()) {
@@ -360,10 +406,14 @@
                                     Log.d(TAG, "Enter Key up");
                                 }
 
-                                mStylist.onAnimateItemPressed(avh.mStylistViewHolder,
-                                            mKeyPressed);
-                                handleCheckedActions(avh, action);
-                                mClickListener.onGuidedActionClicked(action);
+                                mStylist.onAnimateItemPressed(avh.mStylistViewHolder, mKeyPressed);
+                                if (action.isEditable()) {
+                                    if (DEBUG_EDIT) Log.v(TAG_EDIT, "openIme click");
+                                    mActionEditListener.openIme(avh, true);
+                                } else {
+                                    handleCheckedActions(avh, action);
+                                    mClickListener.onGuidedActionClicked(action);
+                                }
                                 handled = true;
                             }
                             break;
@@ -403,4 +453,97 @@
             }
         }
     }
+
+    private class ActionEditListener implements OnEditorActionListener,
+            ImeKeyMonitor.ImeKeyListener {
+
+        private EditListener mEditListener;
+
+        public ActionEditListener(EditListener listener) {
+            mEditListener = listener;
+        }
+
+        @Override
+        public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+            if (DEBUG_EDIT) Log.v(TAG_EDIT, "IME action: " + actionId);
+            boolean handled = false;
+            if (actionId == EditorInfo.IME_ACTION_NEXT ||
+                actionId == EditorInfo.IME_ACTION_DONE) {
+
+                ActionViewHolder avh = findSubChildViewHolder(v);
+                GuidedAction action = avh.getAction();
+                action.setTitle(v.getText());
+                mClickListener.onGuidedActionClicked(action);
+                int next = getNextEditableActionIndex(action);
+                if (next != -1) {
+                    ViewHolder vh = mRecyclerView.findViewHolderForPosition(next);
+                    if (vh != null) {
+                        if (DEBUG_EDIT) Log.v(TAG_EDIT, "openIme next/done");
+                        handled = true;
+                        openIme((ActionViewHolder)vh, false);
+                    }
+                }
+                if (!handled) {
+                    if (DEBUG_EDIT) Log.v(TAG_EDIT, "closeIme no next");
+                    handled = true;
+                    closeIme(avh);
+                }
+            } else if (actionId == EditorInfo.IME_ACTION_NONE) {
+                if (DEBUG_EDIT) Log.v(TAG_EDIT, "closeIme escape north");
+                // Escape north handling: stay on current item, but close editor
+                handled = true;
+                ActionViewHolder avh = findSubChildViewHolder(v);
+                closeIme(avh);
+            }
+            return handled;
+        }
+
+        @Override
+        public boolean onKeyPreIme(EditText editText, int keyCode, KeyEvent event) {
+            if (DEBUG_EDIT) Log.v(TAG_EDIT, "IME key: " + keyCode);
+            if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
+                ActionViewHolder avh = findSubChildViewHolder(editText);
+                GuidedAction action = avh.getAction();
+                action.setTitle(editText.getText());
+                editText.clearFocus();
+                mEditListener.onGuidedActionEdited(action, false);
+            }
+            return false;
+        }
+
+        public void openIme(ActionViewHolder avh, boolean notify) {
+            View v = avh.mStylistViewHolder.getTitleView();
+            InputMethodManager mgr = (InputMethodManager)
+                    v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+            v.requestFocus();
+            mgr.showSoftInput(v, 0);
+            if (notify) {
+                mEditListener.onGuidedActionEdited(avh.getAction(), true);
+            }
+        }
+
+        public void closeIme(ActionViewHolder avh) {
+            View v = avh.mStylistViewHolder.getTitleView();
+            InputMethodManager mgr = (InputMethodManager)
+                    v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+            v.clearFocus();
+            mgr.hideSoftInputFromWindow(v.getWindowToken(), 0);
+            mEditListener.onGuidedActionEdited(avh.getAction(), false);
+        }
+
+        private ActionViewHolder findSubChildViewHolder(View v) {
+            // Needed because RecyclerView.getChildViewHolder does not traverse the hierarchy
+            ActionViewHolder result = null;
+            ViewParent parent = v.getParent();
+            while (parent != mRecyclerView && parent != null && v != null) {
+                v = (View)parent;
+                parent = parent.getParent();
+            }
+            if (parent != null && v != null) {
+                result = (ActionViewHolder)mRecyclerView.getChildViewHolder(v);
+            }
+            return result;
+        }
+    }
+
 }
diff --git a/v17/leanback/src/android/support/v17/leanback/app/GuidedStepFragment.java b/v17/leanback/src/android/support/v17/leanback/app/GuidedStepFragment.java
index b1e87a1..170aa63 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/GuidedStepFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/GuidedStepFragment.java
@@ -211,6 +211,12 @@
     }
 
     /**
+     * Callback invoked when an action's title has been edited.
+     */
+    public void onGuidedActionEdited(GuidedAction action) {
+    }
+
+    /**
      * Adds the specified GuidedStepFragment to the fragment stack, replacing any existing
      * GuidedStepFragments in the stack, and configuring the fragment-to-fragment custom animations.
      * <p>
@@ -354,7 +360,17 @@
         View actionsView = mActionsStylist.onCreateView(inflater, actionContainer);
         actionContainer.addView(actionsView);
 
-        mAdapter = new GuidedActionAdapter(mActions, this, this, mActionsStylist);
+        GuidedActionAdapter.EditListener editListener = new GuidedActionAdapter.EditListener() {
+                @Override
+                public void onGuidedActionEdited(GuidedAction action, boolean entering) {
+                    runImeAnimations(entering);
+                    if (!entering) {
+                        GuidedStepFragment.this.onGuidedActionEdited(action);
+                    }
+                }
+        };
+
+        mAdapter = new GuidedActionAdapter(mActions, this, this, editListener, mActionsStylist);
 
         mListView = mActionsStylist.getActionsGridView();
         mListView.setAdapter(mAdapter);
@@ -522,6 +538,20 @@
                 });
     }
 
+    private void runImeAnimations(boolean entering) {
+        ArrayList<Animator> animators = new ArrayList<Animator>();
+        if (entering) {
+            mGuidanceStylist.onImeAppearing(animators);
+            mActionsStylist.onImeAppearing(animators);
+        } else {
+            mGuidanceStylist.onImeDisappearing(animators);
+            mActionsStylist.onImeDisappearing(animators);
+        }
+        AnimatorSet set = new AnimatorSet();
+        set.playTogether(animators);
+        set.start();
+    }
+
     private Animator createDummyAnimator(final View v, ArrayList<Animator> animators) {
         final AnimatorSet animatorSet = new AnimatorSet();
         animatorSet.playTogether(animators);
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/BaseCardView.java b/v17/leanback/src/android/support/v17/leanback/widget/BaseCardView.java
index 614f12b..085aac3 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/BaseCardView.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/BaseCardView.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
 import android.support.v17.leanback.R;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -154,6 +155,14 @@
 
         try {
             mCardType = a.getInteger(R.styleable.lbBaseCardView_cardType, CARD_TYPE_MAIN_ONLY);
+            Drawable cardForeground = a.getDrawable(R.styleable.lbBaseCardView_cardForeground);
+            if (cardForeground != null) {
+                setForeground(cardForeground);
+            }
+            Drawable cardBackground = a.getDrawable(R.styleable.lbBaseCardView_cardBackground);
+            if (cardBackground != null) {
+                setBackground(cardBackground);
+            }
             mInfoVisibility = a.getInteger(R.styleable.lbBaseCardView_infoVisibility,
                     CARD_REGION_VISIBLE_ACTIVATED);
             mExtraVisibility = a.getInteger(R.styleable.lbBaseCardView_extraVisibility,
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/FocusHighlightHelper.java b/v17/leanback/src/android/support/v17/leanback/widget/FocusHighlightHelper.java
index 48829eb..4f32ff2 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/FocusHighlightHelper.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/FocusHighlightHelper.java
@@ -85,7 +85,7 @@
                 mWrapper = null;
             }
             mAnimator.setTimeListener(this);
-            if (mWrapper != null && useDimmer) {
+            if (useDimmer) {
                 mDimmer = ColorOverlayDimmer.createDefault(view.getContext());
             } else {
                 mDimmer = null;
@@ -99,9 +99,16 @@
             mView.setScaleY(scale);
             if (mWrapper != null) {
                 mWrapper.setShadowFocusLevel(level);
-                if (mDimmer != null) {
-                    mDimmer.setActiveLevel(level);
-                    mWrapper.setOverlayColor(mDimmer.getPaint().getColor());
+            } else {
+                ShadowOverlayHelper.setShadowFocusLevel(mView, level);
+            }
+            if (mDimmer != null) {
+                mDimmer.setActiveLevel(level);
+                int color = mDimmer.getPaint().getColor();
+                if (mWrapper != null) {
+                    mWrapper.setOverlayColor(color);
+                } else {
+                    ShadowOverlayHelper.setForegroundColor(mView, color);
                 }
             }
         }
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ForegroundHelper.java b/v17/leanback/src/android/support/v17/leanback/widget/ForegroundHelper.java
new file mode 100644
index 0000000..c9bed58
--- /dev/null
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ForegroundHelper.java
@@ -0,0 +1,78 @@
+package android.support.v17.leanback.widget;
+
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.view.View;
+import android.view.ViewGroup;
+
+final class ForegroundHelper {
+
+    final static ForegroundHelper sInstance = new ForegroundHelper();
+    ForegroundHelperVersionImpl mImpl;
+
+    /**
+     * Interface implemented by classes that support Shadow.
+     */
+    static interface ForegroundHelperVersionImpl {
+
+        public void setForeground(View view, Drawable drawable);
+
+        public Drawable getForeground(View view);
+    }
+
+    /**
+     * Implementation used on api 23 (and above).
+     */
+    private static final class ForegroundHelperApi23Impl implements ForegroundHelperVersionImpl {
+        @Override
+        public void setForeground(View view, Drawable drawable) {
+            ForegroundHelperApi23.setForeground(view, drawable);
+        }
+
+        @Override
+        public Drawable getForeground(View view) {
+            return ForegroundHelperApi23.getForeground(view);
+        }
+    }
+
+    /**
+     * Stub implementation
+     */
+    private static final class ForegroundHelperStubImpl implements ForegroundHelperVersionImpl {
+        @Override
+        public void setForeground(View view, Drawable drawable) {
+        }
+
+        @Override
+        public Drawable getForeground(View view) {
+            return null;
+        }
+    }
+
+    private ForegroundHelper() {
+        if (supportsForeground()) {
+            mImpl = new ForegroundHelperApi23Impl();
+        } else {
+            mImpl = new ForegroundHelperStubImpl();
+        }
+    }
+
+    public static ForegroundHelper getInstance() {
+        return sInstance;
+    }
+
+    /**
+     * Returns true if view.setForeground() is supported.
+     */
+    public static boolean supportsForeground() {
+        return Build.VERSION.SDK_INT >= 23;
+    }
+
+    public Drawable getForeground(View view) {
+        return mImpl.getForeground(view);
+    }
+
+    public void setForeground(View view, Drawable drawable) {
+        mImpl.setForeground(view, drawable);
+    }
+}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/FragmentAnimationProvider.java b/v17/leanback/src/android/support/v17/leanback/widget/FragmentAnimationProvider.java
index 8bd0007..b1f6169 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/FragmentAnimationProvider.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/FragmentAnimationProvider.java
@@ -69,4 +69,16 @@
      */
     public abstract void onFragmentReturn(@NonNull List<Animator> animators);
 
+    /**
+     * Animates the fragment in response to the IME appearing.
+     * @param animators A list of animations to which this provider's animations should be added.
+     */
+    public abstract void onImeAppearing(@NonNull List<Animator> animators);
+
+    /**
+     * Animates the fragment in response to the IME disappearing.
+     * @param animators A list of animations to which this provider's animations should be added.
+     */
+    public abstract void onImeDisappearing(@NonNull List<Animator> animators);
+
 }
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/GuidanceStylist.java b/v17/leanback/src/android/support/v17/leanback/widget/GuidanceStylist.java
index 8d12510..b95c114 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GuidanceStylist.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GuidanceStylist.java
@@ -59,6 +59,8 @@
  * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepExitAnimation
  * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepReentryAnimation
  * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepReturnAnimation
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepImeAppearingAnimation
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepImeDisappearingAnimation
  * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidanceContainerStyle
  * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidanceTitleStyle
  * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidanceDescriptionStyle
@@ -280,6 +282,28 @@
         addAnimator(animators, mIconView, R.attr.guidedStepReturnAnimation);
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onImeAppearing(@NonNull List<Animator> animators) {
+        addAnimator(animators, mTitleView, R.attr.guidedStepImeAppearingAnimation);
+        addAnimator(animators, mBreadcrumbView, R.attr.guidedStepImeAppearingAnimation);
+        addAnimator(animators, mDescriptionView, R.attr.guidedStepImeAppearingAnimation);
+        addAnimator(animators, mIconView, R.attr.guidedStepImeAppearingAnimation);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onImeDisappearing(@NonNull List<Animator> animators) {
+        addAnimator(animators, mTitleView, R.attr.guidedStepImeDisappearingAnimation);
+        addAnimator(animators, mBreadcrumbView, R.attr.guidedStepImeDisappearingAnimation);
+        addAnimator(animators, mDescriptionView, R.attr.guidedStepImeDisappearingAnimation);
+        addAnimator(animators, mIconView, R.attr.guidedStepImeDisappearingAnimation);
+    }
+
     private void addAnimator(List<Animator> animators, View v, int attrId) {
         if (v != null) {
             Context ctx = v.getContext();
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/GuidedAction.java b/v17/leanback/src/android/support/v17/leanback/widget/GuidedAction.java
index e4db2eb..30edc2f 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GuidedAction.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GuidedAction.java
@@ -50,6 +50,7 @@
         private boolean mMultilineDescription;
         private boolean mHasNext;
         private boolean mInfoOnly;
+        private boolean mEditable = false;
         private int mCheckSetId = NO_CHECK_SET;
         private boolean mEnabled = true;
         private Intent mIntent;
@@ -68,6 +69,7 @@
 
             // Subclass values
             action.mIntent = mIntent;
+            action.mEditable = mEditable;
             action.mChecked = mChecked;
             action.mCheckSetId = mCheckSetId;
             action.mMultilineDescription = mMultilineDescription;
@@ -138,11 +140,27 @@
         }
 
         /**
+         * Indicates whether this action is editable. Note: Editable actions cannot also be
+         * checked, or belong to a check set.
+         * @param editable Whether this action is editable.
+         */
+        public Builder editable(boolean editable) {
+            mEditable = editable;
+            if (mChecked || mCheckSetId != NO_CHECK_SET) {
+                throw new IllegalArgumentException("Editable actions cannot also be checked");
+            }
+            return this;
+        }
+
+        /**
          * Indicates whether this action is initially checked.
          * @param checked Whether this action is checked.
          */
         public Builder checked(boolean checked) {
             mChecked = checked;
+            if (mEditable) {
+                throw new IllegalArgumentException("Editable actions cannot also be checked");
+            }
             return this;
         }
 
@@ -154,6 +172,9 @@
          */
         public Builder checkSetId(int checkSetId) {
             mCheckSetId = checkSetId;
+            if (mEditable) {
+                throw new IllegalArgumentException("Editable actions cannot also be in check sets");
+            }
             return this;
         }
 
@@ -195,9 +216,10 @@
         }
     }
 
-    private boolean mChecked;
+    private boolean mEditable;
     private boolean mMultilineDescription;
     private boolean mHasNext;
+    private boolean mChecked;
     private boolean mInfoOnly;
     private int mCheckSetId;
     private boolean mEnabled;
@@ -217,6 +239,14 @@
     }
 
     /**
+     * Returns the title of this action.
+     * @return The title set when this action was built.
+     */
+    public void setTitle(CharSequence title) {
+        setLabel1(title);
+    }
+
+    /**
      * Returns the description of this action.
      * @return The description set when this action was built.
      */
@@ -233,6 +263,14 @@
     }
 
     /**
+     * Returns whether this action is editable.
+     * @return true if the action is editable, false otherwise.
+     */
+    public boolean isEditable() {
+        return mEditable;
+    }
+
+    /**
      * Returns whether this action is checked.
      * @return true if the action is currently checked, false otherwise.
      */
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionsStylist.java b/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionsStylist.java
index 15943b4..525e2fc 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionsStylist.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionsStylist.java
@@ -81,7 +81,17 @@
  * </ul><p>
  * These view IDs are allowed to be missing, in which case the corresponding views in {@link
  * GuidedActionsStylist.ViewHolder} will be null.
+ * <p>
+ * In order to support editable actions, the view associated with guidedactions_item_title should
+ * be a subclass of {@link android.widget.EditText}, and should satisfy the {@link
+ * ImeKeyMonitor} interface.
  *
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepEntryAnimation
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepExitAnimation
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepReentryAnimation
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepReturnAnimation
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepImeAppearingAnimation
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepImeDisappearingAnimation
  * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsEntryAnimation
  * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsSelectorShowAnimation
  * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsSelectorHideAnimation
@@ -483,6 +493,24 @@
         animators.add(createAnimator(mSelectorView, R.attr.guidedStepReturnAnimation));
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onImeAppearing(@NonNull List<Animator> animators) {
+        animators.add(createAnimator(mActionsGridView, R.attr.guidedStepImeAppearingAnimation));
+        animators.add(createAnimator(mSelectorView, R.attr.guidedStepImeAppearingAnimation));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onImeDisappearing(@NonNull List<Animator> animators) {
+        animators.add(createAnimator(mActionsGridView, R.attr.guidedStepImeDisappearingAnimation));
+        animators.add(createAnimator(mSelectorView, R.attr.guidedStepImeDisappearingAnimation));
+    }
+
     /*
      * ==========================================
      * Private methods
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ImageCardView.java b/v17/leanback/src/android/support/v17/leanback/widget/ImageCardView.java
index 2c1c7e0..08eb617 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/ImageCardView.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ImageCardView.java
@@ -18,60 +18,288 @@
 import android.graphics.drawable.Drawable;
 import android.support.annotation.ColorInt;
 import android.support.v17.leanback.R;
-import android.text.TextUtils;
 import android.util.AttributeSet;
+import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
 import android.widget.ImageView.ScaleType;
+import android.widget.RelativeLayout;
 import android.widget.TextView;
 
 /**
- * A subclass of {@link BaseCardView} with an {@link ImageView} as its main region.
+ * A subclass of {@link BaseCardView} with an {@link ImageView} as its main
+ * region. The {@link ImageCardView} is highly customizable and can be used for
+ * various use-cases by adjusting the ImageViewCard's type to any combination of
+ * Title, Content, Badge or ImageOnly.
+ * <p>
+ * <h3>Styling</h3> There are three different ways to style the ImageCardView.
+ * <br>
+ * No matter what way you use, all your styles applied to an ImageCardView have
+ * to extend the style {@link R.style#Widget_Leanback_ImageCardViewStyle}.
+ * <p>
+ * <u>Example:</u><br>
+ * 
+ * <pre>
+ * {@code <style name="CustomImageCardViewStyle" parent="Widget.Leanback.ImageCardViewStyle">
+        <item name="cardBackground">#F0F</item>
+        <item name="lbImageCardViewType">Title|Content</item>
+        <item name="lbImageCardViewInfoAreaStyle">@style/ImageCardViewColoredInfoArea</item>
+        <item name="lbImageCardViewTitleStyle">@style/ImageCardViewColoredTitle</item>
+    </style>}
+ * </pre>
+ * <p>
+ * The first possibility is to set a custom Style in the Leanback Theme's
+ * attribute <code>imageCardViewStyle</code>. The style set here, is the default
+ * style for all ImageCardViews. The other two possibilities allow you to style
+ * a particular ImageCardView. This is usefull if you want to create multiple
+ * types of cards. E.g. you might want to display a card with only a title and
+ * another one with title and content. Thus you need to define two different
+ * <code>ImageCardViewStyles</code> and apply them to the ImageCardViews. You
+ * can do this by either using a the {@link #ImageCardView(Context, int)}
+ * constructor and passing a style as second argument or by setting the style in
+ * a layout.
+ * <p>
+ * <u>Example (using constructor):</u><br>
+ * 
+ * <pre>
+ * {@code
+ *     new ImageCardView(context, R.style.CustomImageCardViewStyle);
+ * }
+ * </pre>
+ * 
+ * <u>Example (using style attribute in a layout):</u><br>
+ * 
+ * <pre>
+ * {@code     <android.support.v17.leanback.widget.ImageCardView
+        android:id="@+id/imageCardView"
+        style="@style/CustomImageCardViewStyle"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content">
+    </android.support.v17.leanback.widget.ImageCardView>}
+ * </pre>
+ * <p>
+ * You can style all ImageCardView's components such as the title, content,
+ * badge, infoArea and the image itself by extending the corresponding style and
+ * overriding the specific attribute in your custom
+ * <code>ImageCardViewStyle</code>.
+ * 
+ * <h3>Components</h3> The ImageCardView contains three components which can be
+ * combined in any combination:
+ * <ul>
+ * <li>Title: The card's title</li>
+ * <li>Content: A short description</li>
+ * <li>Badge: An icon which can be displayed on the right or left side of the
+ * card.</li>
+ * </ul>
+ * In order to choose the components you want to use in your ImageCardView, you
+ * have to specify them in the <code>lbImageCardViewType</code> attribute of
+ * your custom <code>ImageCardViewStyle</code>. You can combine the following
+ * values: <code>Title, Content, IconOnRight, IconOnLeft, ImageOnly</code>.
+ * <p>
+ * <u>Examples:</u><br>
+ * 
+ * <pre>
+ * {@code <style name="CustomImageCardViewStyle" parent="Widget.Leanback.ImageCardViewStyle">
+        ...
+        <item name="lbImageCardViewType">Title|Content|IconOnLeft</item>
+        ...
+    </style>}
+ * </pre>
+ * 
+ * <pre>
+ * {@code <style name="CustomImageCardViewStyle" parent="Widget.Leanback.ImageCardViewStyle">
+        ...
+        <item name="lbImageCardViewType">ImageOnly</item>
+        ...
+    </style>}
+ * </pre>
+ * 
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackTheme_imageCardViewStyle
+ * @attr ref android.support.v17.leanback.R.styleable#lbImageCardView_lbImageCardViewType
+ * @attr ref android.support.v17.leanback.R.styleable#lbImageCardView_lbImageCardViewTitleStyle
+ * @attr ref android.support.v17.leanback.R.styleable#lbImageCardView_lbImageCardViewContentStyle
+ * @attr ref android.support.v17.leanback.R.styleable#lbImageCardView_lbImageCardViewBadgeStyle
+ * @attr ref android.support.v17.leanback.R.styleable#lbImageCardView_lbImageCardViewImageStyle
+ * @attr ref android.support.v17.leanback.R.styleable#lbImageCardView_lbImageCardViewInfoAreaStyle
  */
 public class ImageCardView extends BaseCardView {
 
+    public static final int CARD_TYPE_FLAG_IMAGE_ONLY = 0;
+    public static final int CARD_TYPE_FLAG_TITLE = 1;
+    public static final int CARD_TYPE_FLAG_CONTENT = 2;
+    public static final int CARD_TYPE_FLAG_ICON_RIGHT = 4;
+    public static final int CARD_TYPE_FLAG_ICON_LEFT = 8;
+
     private ImageView mImageView;
-    private View mInfoArea;
+    private ViewGroup mInfoArea;
     private TextView mTitleView;
     private TextView mContentView;
     private ImageView mBadgeImage;
     private boolean mAttachedToWindow;
 
+    /**
+     * Create an ImageCardView using a given style for customization.
+     * 
+     * @param context
+     *            The Context the view is running in, through which it can
+     *            access the current theme, resources, etc.
+     * @param styleResId
+     *            The resourceId of the style you want to apply to the
+     *            ImageCardView. The style has to extend
+     *            {@link R.style#Widget_Leanback_ImageCardViewStyle}.
+     */
+    public ImageCardView(Context context, int styleResId) {
+        super(new ContextThemeWrapper(context, styleResId), null, 0);
+        buildImageCardView(styleResId);
+    }
+
+    /**
+     * @see #View(Context, AttributeSet, int)
+     */
+    public ImageCardView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(getStyledContext(context, attrs, defStyleAttr), attrs, defStyleAttr);
+        buildImageCardView(getImageCardViewStyle(context, attrs, defStyleAttr));
+    }
+
+    private void buildImageCardView(int styleResId) {
+        // Make sure the ImageCardView is focusable.
+        setFocusable(true);
+        setFocusableInTouchMode(true);
+
+        LayoutInflater inflater = LayoutInflater.from(getContext());
+        inflater.inflate(R.layout.lb_image_card_view, this);
+        TypedArray cardAttrs = getContext().obtainStyledAttributes(styleResId, R.styleable.lbImageCardView);
+        int cardType = cardAttrs.getInt(R.styleable.lbImageCardView_lbImageCardViewType, CARD_TYPE_FLAG_IMAGE_ONLY);
+        boolean hasImageOnly = cardType == CARD_TYPE_FLAG_IMAGE_ONLY;
+        boolean hasTitle = (cardType & CARD_TYPE_FLAG_TITLE) == CARD_TYPE_FLAG_TITLE;
+        boolean hasContent = (cardType & CARD_TYPE_FLAG_CONTENT) == CARD_TYPE_FLAG_CONTENT;
+        boolean hasIconRight = (cardType & CARD_TYPE_FLAG_ICON_RIGHT) == CARD_TYPE_FLAG_ICON_RIGHT;
+        boolean hasIconLeft = !hasIconRight && (cardType & CARD_TYPE_FLAG_ICON_LEFT) == CARD_TYPE_FLAG_ICON_LEFT;
+
+        mImageView = (ImageView) findViewById(R.id.main_image);
+        if (mImageView.getDrawable() == null) {
+            mImageView.setVisibility(View.INVISIBLE);
+        }
+
+        mInfoArea = (ViewGroup) findViewById(R.id.info_field);
+        if (hasImageOnly) {
+            removeView(mInfoArea);
+            cardAttrs.recycle();
+            return;
+        }
+        // Create children
+        if (hasTitle) {
+            mTitleView = (TextView) inflater.inflate(R.layout.lb_image_card_view_themed_title, mInfoArea, false);
+            mInfoArea.addView(mTitleView);
+        }
+
+        if (hasContent) {
+            mContentView = (TextView) inflater.inflate(R.layout.lb_image_card_view_themed_content, mInfoArea, false);
+            mInfoArea.addView(mContentView);
+        }
+
+        if (hasIconRight || hasIconLeft) {
+            int layoutId = R.layout.lb_image_card_view_themed_badge_right;
+            if (hasIconLeft) {
+                layoutId = R.layout.lb_image_card_view_themed_badge_left;
+            }
+            mBadgeImage = (ImageView) inflater.inflate(layoutId, mInfoArea, false);
+            mInfoArea.addView(mBadgeImage);
+        }
+
+        // Set up LayoutParams for children
+        if (hasTitle && !hasContent && mBadgeImage != null) {
+            RelativeLayout.LayoutParams relativeLayoutParams = (RelativeLayout.LayoutParams) mTitleView
+                    .getLayoutParams();
+            // Adjust title TextView if there is an icon but no content
+            if (hasIconLeft) {
+                relativeLayoutParams.addRule(RelativeLayout.END_OF, mBadgeImage.getId());
+            } else {
+                relativeLayoutParams.addRule(RelativeLayout.START_OF, mBadgeImage.getId());
+            }
+            mTitleView.setLayoutParams(relativeLayoutParams);
+        }
+
+        // Set up LayoutParams for children
+        if (hasContent) {
+            RelativeLayout.LayoutParams relativeLayoutParams = (RelativeLayout.LayoutParams) mContentView
+                    .getLayoutParams();
+            if (!hasTitle) {
+                relativeLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+            }
+            // Adjust content TextView if icon is on the left
+            if (hasIconLeft) {
+                relativeLayoutParams.removeRule(RelativeLayout.START_OF);
+                relativeLayoutParams.removeRule(RelativeLayout.ALIGN_PARENT_START);
+                relativeLayoutParams.addRule(RelativeLayout.END_OF, mBadgeImage.getId());
+            }
+            mContentView.setLayoutParams(relativeLayoutParams);
+        }
+
+        if (mBadgeImage != null) {
+            RelativeLayout.LayoutParams relativeLayoutParams = (RelativeLayout.LayoutParams) mBadgeImage
+                    .getLayoutParams();
+            if (hasContent) {
+                relativeLayoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, mContentView.getId());
+            } else if (hasTitle) {
+                relativeLayoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, mTitleView.getId());
+            }
+            mBadgeImage.setLayoutParams(relativeLayoutParams);
+        }
+
+        // Backward compatibility: Newly created ImageCardViews should change
+        // the InfoArea's background color in XML using the corresponding style.
+        // However, since older implementations might make use of the
+        // 'infoAreaBackground' attribute, we have to make sure to support it.
+        // If the user has set a specific value here, it will differ from null.
+        // In this case, we do want to override the value set in the style.
+        Drawable background = cardAttrs.getDrawable(R.styleable.lbImageCardView_infoAreaBackground);
+        if (null != background) {
+            setInfoAreaBackground(background);
+        }
+        // Backward compatibility: There has to be an icon in the default
+        // version. If there is one, we have to set it's visibility to 'GONE'.
+        // Disabling 'adjustIconVisibility' allows the user to set the icon's
+        // visibility state in XML rather than code.
+        if (mBadgeImage != null && mBadgeImage.getDrawable() == null) {
+            mBadgeImage.setVisibility(View.GONE);
+        }
+        cardAttrs.recycle();
+    }
+
+    private static Context getStyledContext(Context context, AttributeSet attrs, int defStyleAttr) {
+        int style = getImageCardViewStyle(context, attrs, defStyleAttr);
+        return new ContextThemeWrapper(context, style);
+    }
+
+    private static int getImageCardViewStyle(Context context, AttributeSet attrs, int defStyleAttr) {
+        // Read style attribute defined in XML layout.
+        int style = null == attrs ? 0 : attrs.getStyleAttribute();
+        if (0 == style) {
+            // Not found? Read global ImageCardView style from Theme attribute.
+            TypedArray styledAttrs = context.obtainStyledAttributes(R.styleable.LeanbackTheme);
+            style = styledAttrs.getResourceId(R.styleable.LeanbackTheme_imageCardViewStyle, 0);
+            styledAttrs.recycle();
+        }
+        return style;
+    }
+
+    /**
+     * @see #View(Context)
+     */
     public ImageCardView(Context context) {
         this(context, null);
     }
 
+    /**
+     * @see #View(Context, AttributeSet)
+     */
     public ImageCardView(Context context, AttributeSet attrs) {
         this(context, attrs, R.attr.imageCardViewStyle);
     }
 
-    public ImageCardView(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-
-        LayoutInflater inflater = LayoutInflater.from(context);
-        View v = inflater.inflate(R.layout.lb_image_card_view, this);
-
-        mImageView = (ImageView) v.findViewById(R.id.main_image);
-        mImageView.setVisibility(View.INVISIBLE);
-        mInfoArea = v.findViewById(R.id.info_field);
-        mTitleView = (TextView) v.findViewById(R.id.title_text);
-        mContentView = (TextView) v.findViewById(R.id.content_text);
-        mBadgeImage = (ImageView) v.findViewById(R.id.extra_badge);
-
-        if (mInfoArea != null) {
-            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.lbImageCardView,
-                    defStyle, 0);
-            try {
-                setInfoAreaBackground(
-                        a.getDrawable(R.styleable.lbImageCardView_infoAreaBackground));
-            } finally {
-                a.recycle();
-            }
-        }
-    }
-
     /**
      * Returns the main image view.
      */
@@ -170,7 +398,7 @@
 
     /**
      * Sets the info area background color.
-     */    
+     */
     public void setInfoAreaBackgroundColor(@ColorInt int color) {
         if (mInfoArea != null) {
             mInfoArea.setBackgroundColor(color);
@@ -184,7 +412,6 @@
         if (mTitleView == null) {
             return;
         }
-
         mTitleView.setText(text);
     }
 
@@ -206,7 +433,6 @@
         if (mContentView == null) {
             return;
         }
-
         mContentView.setText(text);
     }
 
@@ -229,7 +455,7 @@
             return;
         }
         mBadgeImage.setImageDrawable(drawable);
-        if (drawable != null && mContentView!= null && mContentView.getVisibility() != GONE) {
+        if (drawable != null) {
             mBadgeImage.setVisibility(View.VISIBLE);
         } else {
             mBadgeImage.setVisibility(View.GONE);
@@ -250,8 +476,8 @@
     private void fadeIn() {
         mImageView.setAlpha(0f);
         if (mAttachedToWindow) {
-            mImageView.animate().alpha(1f).setDuration(mImageView.getResources().getInteger(
-                    android.R.integer.config_shortAnimTime));
+            mImageView.animate().alpha(1f)
+                    .setDuration(mImageView.getResources().getInteger(android.R.integer.config_shortAnimTime));
         }
     }
 
@@ -276,4 +502,5 @@
         mImageView.setAlpha(1f);
         super.onDetachedFromWindow();
     }
+
 }
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ImeKeyMonitor.java b/v17/leanback/src/android/support/v17/leanback/widget/ImeKeyMonitor.java
new file mode 100644
index 0000000..4691ad2
--- /dev/null
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ImeKeyMonitor.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package android.support.v17.leanback.widget;
+
+import android.widget.EditText;
+import android.view.KeyEvent;
+
+/**
+ * Interface for an EditText subclass that can delegate calls to onKeyPreIme up to a registered
+ * listener.
+ * <p>
+ * Used in editable actions within {@link android.support.v17.leanback.app.GuidedStepFragment} to
+ * allow for custom back key handling. Specifically, this is used to implement the behavior that
+ * dismissing the IME also clears edit text focus. Clients who need to supply custom layouts for
+ * {@link GuidedActionsStylist} with their own EditText classes should satisfy this interface in
+ * order to inherit this behavior.
+ */
+public interface ImeKeyMonitor {
+
+    /**
+     * Listener interface for key events intercepted pre-IME by edit text objects.
+     */
+    public interface ImeKeyListener {
+        /**
+         * Callback invoked from EditText's onKeyPreIme method override. Returning true tells the
+         * caller that the key event is handled and should not be propagated.
+         */
+        public abstract boolean onKeyPreIme(EditText editText, int keyCode, KeyEvent event);
+    }
+
+    /**
+     * Set the listener for this edit text object. The listener's onKeyPreIme method will be
+     * invoked from the host edit text's onKeyPreIme method.
+     */
+    public void setImeKeyListener(ImeKeyListener listener);
+}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/LeanbackEditText.java b/v17/leanback/src/android/support/v17/leanback/widget/LeanbackEditText.java
new file mode 100644
index 0000000..97c4477
--- /dev/null
+++ b/v17/leanback/src/android/support/v17/leanback/widget/LeanbackEditText.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package android.support.v17.leanback.widget;
+
+import android.content.Context;
+import android.support.v17.leanback.widget.ImeKeyMonitor.ImeKeyListener;
+import android.util.AttributeSet;
+import android.widget.EditText;
+import android.view.KeyEvent;
+
+/**
+ * A custom EditText that satisfies the IME key monitoring requirements of GuidedStepFragment.
+ *
+ * @hide
+ */
+public class LeanbackEditText extends EditText implements ImeKeyMonitor {
+
+    private ImeKeyListener mKeyListener;
+
+    public LeanbackEditText(Context ctx) {
+        this(ctx, null);
+    }
+
+    public LeanbackEditText(Context ctx, AttributeSet attrs) {
+        this(ctx, attrs, android.R.attr.editTextStyle);
+    }
+
+    public LeanbackEditText(Context ctx, AttributeSet attrs, int defStyleAttr) {
+        super(ctx, attrs, defStyleAttr);
+    }
+
+    @Override
+    public void setImeKeyListener(ImeKeyListener listener) {
+        mKeyListener = listener;
+    }
+
+    @Override
+    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+        boolean result = false;
+        if (mKeyListener != null) {
+            result = mKeyListener.onKeyPreIme(this, keyCode, event);
+        }
+        if (!result) {
+            result = super.onKeyPreIme(keyCode, event);
+        }
+        return result;
+    }
+
+}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ListRowPresenter.java b/v17/leanback/src/android/support/v17/leanback/widget/ListRowPresenter.java
index 9e588eb..1c5c1f9 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/ListRowPresenter.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ListRowPresenter.java
@@ -15,6 +15,7 @@
 
 import android.content.Context;
 import android.content.res.TypedArray;
+import android.os.Build;
 import android.support.v17.leanback.R;
 import android.support.v17.leanback.system.Settings;
 import android.util.Log;
@@ -96,6 +97,13 @@
         }
 
         @Override
+        protected void onCreate(ItemBridgeAdapter.ViewHolder viewHolder) {
+            if (mShadowOverlayHelper != null) {
+                mShadowOverlayHelper.onViewCreated(viewHolder.itemView);
+            }
+        }
+
+        @Override
         public void onBind(final ItemBridgeAdapter.ViewHolder viewHolder) {
             // Only when having an OnItemClickListner, we will attach the OnClickListener.
             if (mRowViewHolder.getOnItemViewClickedListener() != null) {
@@ -122,9 +130,13 @@
 
         @Override
         public void onAttachedToWindow(ItemBridgeAdapter.ViewHolder viewHolder) {
-            if (needsDefaultListSelectEffect()) {
+            if (mShadowOverlayHelper != null && mShadowOverlayHelper.needsOverlay()) {
                 int dimmedColor = mRowViewHolder.mColorDimmer.getPaint().getColor();
-                ((ShadowOverlayContainer) viewHolder.itemView).setOverlayColor(dimmedColor);
+                if (mShadowOverlayHelper.getWrapper() != null) {
+                    ((ShadowOverlayContainer) viewHolder.itemView).setOverlayColor(dimmedColor);
+                } else {
+                    ShadowOverlayHelper.setForegroundColor(viewHolder.itemView, dimmedColor);
+                }
             }
             mRowViewHolder.syncActivatedStatus(viewHolder.itemView);
         }
@@ -145,6 +157,7 @@
     private int mBrowseRowsFadingEdgeLength = -1;
     private boolean mRoundedCornersEnabled = true;
     private HashMap<Presenter, Integer> mRecycledPoolSize = new HashMap<Presenter, Integer>();
+    private ShadowOverlayHelper mShadowOverlayHelper;
 
     private static int sSelectedRowTopPadding;
     private static int sExpandedSelectedRowTopPadding;
@@ -253,44 +266,24 @@
         return mUseFocusDimmer;
     }
 
-    private ItemBridgeAdapter.Wrapper mCardWrapper = new ItemBridgeAdapter.Wrapper() {
-        @Override
-        public View createWrapper(View root) {
-            ShadowOverlayContainer wrapper = new ShadowOverlayContainer(root.getContext());
-            wrapper.setLayoutParams(
-                    new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
-            if (isUsingZOrder(root.getContext())) {
-                wrapper.useDynamicShadow();
-            } else {
-                wrapper.useStaticShadow();
-            }
-            wrapper.initialize(needsDefaultShadow(),
-                    needsDefaultListSelectEffect(),
-                    areChildRoundedCornersEnabled());
-            return wrapper;
-        }
-        @Override
-        public void wrap(View wrapper, View wrapped) {
-            ((ShadowOverlayContainer) wrapper).wrap(wrapped);
-        }
-    };
-
     @Override
     protected void initializeRowViewHolder(RowPresenter.ViewHolder holder) {
         super.initializeRowViewHolder(holder);
         final ViewHolder rowViewHolder = (ViewHolder) holder;
+        Context context = holder.view.getContext();
+        if (mShadowOverlayHelper == null) {
+            mShadowOverlayHelper = new ShadowOverlayHelper(context, needsDefaultListSelectEffect(),
+                    needsDefaultShadow(), areChildRoundedCornersEnabled(), isUsingZOrder(context));
+        }
         rowViewHolder.mItemBridgeAdapter = new ListRowPresenterItemBridgeAdapter(rowViewHolder);
-        if (needsDefaultListSelectEffect() || needsDefaultShadow()
-                || areChildRoundedCornersEnabled()) {
-            rowViewHolder.mItemBridgeAdapter.setWrapper(mCardWrapper);
-        }
-        if (needsDefaultShadow()) {
-            ShadowOverlayContainer.prepareParentForShadow(rowViewHolder.mGridView);
-        }
+        // set wrapper if needed
+        rowViewHolder.mItemBridgeAdapter.setWrapper(mShadowOverlayHelper.getWrapper());
+        mShadowOverlayHelper.prepareParentForShadow(rowViewHolder.mGridView);
+
         FocusHighlightHelper.setupBrowseItemFocusHighlight(rowViewHolder.mItemBridgeAdapter,
                 mFocusZoomFactor, mUseFocusDimmer);
-        rowViewHolder.mGridView.setFocusDrawingOrderEnabled(
-                !isUsingZOrder(rowViewHolder.getGridView().getContext()));
+        rowViewHolder.mGridView.setFocusDrawingOrderEnabled(mShadowOverlayHelper.getShadowType()
+                == ShadowOverlayHelper.SHADOW_STATIC);
         rowViewHolder.mGridView.setOnChildSelectedListener(
                 new OnChildSelectedListener() {
             @Override
@@ -545,7 +538,7 @@
      * Subclass may return false to disable.
      */
     public boolean isUsingDefaultShadow() {
-        return ShadowOverlayContainer.supportsShadow();
+        return ShadowOverlayHelper.supportsShadow();
     }
 
     /**
@@ -554,8 +547,7 @@
      * and does not use Z-shadow on SDK >= L, it should override isUsingZOrder() return false.
      */
     public boolean isUsingZOrder(Context context) {
-        return ShadowOverlayContainer.supportsDynamicShadow() &&
-                !Settings.getInstance(context).preferStaticShadows();
+        return !Settings.getInstance(context).preferStaticShadows();
     }
 
     /**
@@ -615,12 +607,18 @@
     @Override
     protected void onSelectLevelChanged(RowPresenter.ViewHolder holder) {
         super.onSelectLevelChanged(holder);
-        if (needsDefaultListSelectEffect()) {
+        if (mShadowOverlayHelper != null && mShadowOverlayHelper.needsOverlay()) {
             ViewHolder vh = (ViewHolder) holder;
             int dimmedColor = vh.mColorDimmer.getPaint().getColor();
-            for (int i = 0, count = vh.mGridView.getChildCount(); i < count; i++) {
-                ShadowOverlayContainer wrapper = (ShadowOverlayContainer) vh.mGridView.getChildAt(i);
-                wrapper.setOverlayColor(dimmedColor);
+            if (mShadowOverlayHelper.getWrapper() != null) {
+                for (int i = 0, count = vh.mGridView.getChildCount(); i < count; i++) {
+                    ((ShadowOverlayContainer) vh.mGridView.getChildAt(i))
+                            .setOverlayColor(dimmedColor);
+                }
+            } else {
+                for (int i = 0, count = vh.mGridView.getChildCount(); i < count; i++) {
+                    ShadowOverlayHelper.setForegroundColor(vh.mGridView.getChildAt(i), dimmedColor);
+                }
             }
             if (vh.mGridView.getFadingLeftEdge()) {
                 vh.mGridView.invalidate();
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/RoundedRectHelper.java b/v17/leanback/src/android/support/v17/leanback/widget/RoundedRectHelper.java
index e1c5979..f21670c 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/RoundedRectHelper.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/RoundedRectHelper.java
@@ -33,6 +33,10 @@
         return sInstance;
     }
 
+    public static boolean supportsRoundedCorner() {
+        return Build.VERSION.SDK_INT >= 21;
+    }
+
     /**
      * Sets or removes a rounded rectangle outline on the given view.
      */
@@ -65,7 +69,7 @@
     }
 
     private RoundedRectHelper() {
-        if (Build.VERSION.SDK_INT >= 21) {
+        if (supportsRoundedCorner()) {
             mImpl = new Api21Impl();
         } else {
             mImpl = new StubImpl();
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ShadowHelper.java b/v17/leanback/src/android/support/v17/leanback/widget/ShadowHelper.java
index be70575..9532635 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/ShadowHelper.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ShadowHelper.java
@@ -32,7 +32,7 @@
      */
     static interface ShadowHelperVersionImpl {
         public Object addDynamicShadow(
-                ViewGroup shadowContainer, float unfocusedZ, float focusedZ, boolean roundedCorners);
+                View shadowContainer, float unfocusedZ, float focusedZ, boolean roundedCorners);
         public void setZ(View view, float z);
         public void setShadowFocusLevel(Object impl, float level);
     }
@@ -43,7 +43,7 @@
     private static final class ShadowHelperStubImpl implements ShadowHelperVersionImpl {
         @Override
         public Object addDynamicShadow(
-                ViewGroup shadowContainer, float focusedZ, float unfocusedZ, boolean roundedCorners) {
+                View shadowContainer, float focusedZ, float unfocusedZ, boolean roundedCorners) {
             // do nothing
             return null;
         }
@@ -65,7 +65,7 @@
     private static final class ShadowHelperApi21Impl implements ShadowHelperVersionImpl {
         @Override
         public Object addDynamicShadow(
-                ViewGroup shadowContainer, float unfocusedZ, float focusedZ, boolean roundedCorners) {
+                View shadowContainer, float unfocusedZ, float focusedZ, boolean roundedCorners) {
             return ShadowHelperApi21.addDynamicShadow(
                     shadowContainer, unfocusedZ, focusedZ, roundedCorners);
         }
@@ -102,7 +102,7 @@
     }
 
     public Object addDynamicShadow(
-            ViewGroup shadowContainer, float unfocusedZ, float focusedZ, boolean roundedCorners) {
+            View shadowContainer, float unfocusedZ, float focusedZ, boolean roundedCorners) {
         return mImpl.addDynamicShadow(shadowContainer, unfocusedZ, focusedZ, roundedCorners);
     }
 
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayContainer.java b/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayContainer.java
index e367494..84a30e4 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayContainer.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayContainer.java
@@ -20,6 +20,9 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
 import android.graphics.Rect;
 
 /**
@@ -51,20 +54,19 @@
     /**
      * No shadow.
      */
-    public static final int SHADOW_NONE = 1;
+    public static final int SHADOW_NONE = ShadowOverlayHelper.SHADOW_NONE;
 
     /**
      * Shadows are fixed.
      */
-    public static final int SHADOW_STATIC = 2;
+    public static final int SHADOW_STATIC = ShadowOverlayHelper.SHADOW_STATIC;
 
     /**
      * Shadows depend on the size, shape, and position of the view.
      */
-    public static final int SHADOW_DYNAMIC = 3;
+    public static final int SHADOW_DYNAMIC = ShadowOverlayHelper.SHADOW_DYNAMIC;
 
     private boolean mInitialized;
-    private View mColorDimOverlay;
     private Object mShadowImpl;
     private View mWrappedView;
     private boolean mRoundedCorners;
@@ -72,15 +74,26 @@
     private float mUnfocusedZ;
     private float mFocusedZ;
     private static final Rect sTempRect = new Rect();
+    private Paint mOverlayPaint;
+    private int mOverlayColor;
 
+    /**
+     * Create ShadowOverlayContainer and auto select shadow type.
+     */
     public ShadowOverlayContainer(Context context) {
         this(context, null, 0);
     }
 
+    /**
+     * Create ShadowOverlayContainer and auto select shadow type.
+     */
     public ShadowOverlayContainer(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
     }
 
+    /**
+     * Create ShadowOverlayContainer and auto select shadow type.
+     */
     public ShadowOverlayContainer(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         useStaticShadow();
@@ -88,6 +101,17 @@
     }
 
     /**
+     * Create ShadowOverlayContainer with specific shadowType.
+     */
+    public ShadowOverlayContainer(Context context,
+            int shadowType, boolean hasColorDimOverlay, boolean roundedCorners) {
+        super(context);
+        mUnfocusedZ = getResources().getDimension(R.dimen.lb_material_shadow_normal_z);
+        mFocusedZ = getResources().getDimension(R.dimen.lb_material_shadow_focused_z);
+        initialize(shadowType, hasColorDimOverlay, roundedCorners);
+    }
+
+    /**
      * Return true if the platform sdk supports shadow.
      */
     public static boolean supportsShadow() {
@@ -164,29 +188,59 @@
 
     /**
      * Initialize shadows, color overlay, and rounded corners.  All are optional.
+     * Shadow type are auto-selected based on {@link #useStaticShadow()} and
+     * {@link #useDynamicShadow()} call.
+     * @deprecated use {@link #initialize(int, boolean, boolean)} instead.
      */
+    @Deprecated
     public void initialize(boolean hasShadow, boolean hasColorDimOverlay, boolean roundedCorners) {
+        int shadowType;
+        if (!hasShadow) {
+            shadowType = SHADOW_NONE;
+        } else {
+            shadowType = mShadowType;
+        }
+        initialize(shadowType, hasColorDimOverlay, roundedCorners);
+    }
+
+    /**
+     * Initialize shadows, color overlay, and rounded corners.  All are optional.
+     */
+    public void initialize(int shadowType, boolean hasColorDimOverlay, boolean roundedCorners) {
         if (mInitialized) {
             throw new IllegalStateException();
         }
         mInitialized = true;
-        if (hasShadow) {
-            switch (mShadowType) {
-                case SHADOW_DYNAMIC:
-                    mShadowImpl = ShadowHelper.getInstance().addDynamicShadow(
-                            this, mUnfocusedZ, mFocusedZ, roundedCorners);
-                    break;
-                case SHADOW_STATIC:
-                    mShadowImpl = StaticShadowHelper.getInstance().addStaticShadow(
-                            this, roundedCorners);
-                    break;
-            }
+        mShadowType = shadowType;
+        switch (mShadowType) {
+            case SHADOW_DYNAMIC:
+                mShadowImpl = ShadowHelper.getInstance().addDynamicShadow(
+                        this, mUnfocusedZ, mFocusedZ, roundedCorners);
+                break;
+            case SHADOW_STATIC:
+                mShadowImpl = StaticShadowHelper.getInstance().addStaticShadow(this);
+                break;
         }
         mRoundedCorners = roundedCorners;
         if (hasColorDimOverlay) {
-            mColorDimOverlay = LayoutInflater.from(getContext())
-                    .inflate(R.layout.lb_card_color_overlay, this, false);
-            addView(mColorDimOverlay);
+            setWillNotDraw(false);
+            mOverlayColor = Color.TRANSPARENT;
+            mOverlayPaint = new Paint();
+            mOverlayPaint.setColor(mOverlayColor);
+            mOverlayPaint.setStyle(Paint.Style.FILL);
+        } else {
+            setWillNotDraw(true);
+            mOverlayPaint = null;
+        }
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        super.draw(canvas);
+        if (mOverlayPaint != null && mOverlayColor != Color.TRANSPARENT) {
+            canvas.drawRect(mWrappedView.getLeft(), mWrappedView.getTop(),
+                    mWrappedView.getRight(), mWrappedView.getBottom(),
+                    mOverlayPaint);
         }
     }
 
@@ -195,19 +249,7 @@
      */
     public void setShadowFocusLevel(float level) {
         if (mShadowImpl != null) {
-            if (level < 0f) {
-                level = 0f;
-            } else if (level > 1f) {
-                level = 1f;
-            }
-            switch (mShadowType) {
-                case SHADOW_DYNAMIC:
-                    ShadowHelper.getInstance().setShadowFocusLevel(mShadowImpl, level);
-                    break;
-                case SHADOW_STATIC:
-                    StaticShadowHelper.getInstance().setShadowFocusLevel(mShadowImpl, level);
-                    break;
-            }
+            ShadowOverlayHelper.setShadowFocusLevel(mShadowImpl, mShadowType, level);
         }
     }
 
@@ -215,8 +257,12 @@
      * Set color (with alpha) of the overlay.
      */
     public void setOverlayColor(@ColorInt int overlayColor) {
-        if (mColorDimOverlay != null) {
-            mColorDimOverlay.setBackgroundColor(overlayColor);
+        if (mOverlayPaint != null) {
+            if (overlayColor != mOverlayColor) {
+                mOverlayColor = overlayColor;
+                mOverlayPaint.setColor(overlayColor);
+                invalidate();
+            }
         }
     }
 
@@ -227,15 +273,11 @@
         if (!mInitialized || mWrappedView != null) {
             throw new IllegalStateException();
         }
-        if (mColorDimOverlay != null) {
-            addView(view, indexOfChild(mColorDimOverlay));
-        } else {
-            addView(view);
+        addView(view);
+        if (mRoundedCorners && mShadowType == SHADOW_STATIC) {
+            RoundedRectHelper.getInstance().setClipToRoundedOutline(view, true);
         }
         mWrappedView = view;
-        if (mRoundedCorners) {
-            RoundedRectHelper.getInstance().setClipToRoundedOutline(mWrappedView, true);
-        }
     }
 
     /**
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayHelper.java b/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayHelper.java
new file mode 100644
index 0000000..457e882
--- /dev/null
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayHelper.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package android.support.v17.leanback.widget;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.support.v17.leanback.R;
+import android.support.v17.leanback.system.Settings;
+import android.util.AttributeSet;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.view.View;
+
+
+/**
+ * ShadowOverlayHelper is a helper class for shadow, overlay and rounded corner.
+ * Initialize it with all the options and it decides the best strategy.
+ * <li> For shadow:  it may use 9-patch with opticalBounds or Z-value based shadow for
+ *                   API >= 21.  When 9-patch is used, it requires a ShadowOverlayContainer
+ *                   created by ItemBridgeAdapter.Wrapper to include 9-patch views.
+ * <li> For overlay: it may use ShadowOverlayContainer which overrides draw() or it may
+ *                   use setForeground(new ColorDrawable()) for API>=23.  The foreground support
+ *                   might be disabled if rounded corner is applied due to performance reason.
+ * <li> For rounded-corner:  it uses a ViewOutlineProvider for API>=21.
+ * @hide
+ */
+public final class ShadowOverlayHelper {
+
+    /**
+     * No shadow.
+     */
+    public static final int SHADOW_NONE = 1;
+
+    /**
+     * Shadows are fixed.
+     */
+    public static final int SHADOW_STATIC = 2;
+
+    /**
+     * Shadows depend on the size, shape, and position of the view.
+     */
+    public static final int SHADOW_DYNAMIC = 3;
+
+    int mShadowType = SHADOW_NONE;
+    boolean mNeedsOverlay;
+    boolean mNeedsRoundedCorner;
+    boolean mNeedsShadow;
+    boolean mNeedsWrapper;
+    private ItemBridgeAdapter.Wrapper mCardWrapper;
+
+    float mUnfocusedZ;
+    float mFocusedZ;
+
+    /**
+     * Return true if the platform sdk supports shadow.
+     */
+    public static boolean supportsShadow() {
+        return StaticShadowHelper.getInstance().supportsShadow();
+    }
+
+    /**
+     * Returns true if the platform sdk supports dynamic shadows.
+     */
+    public static boolean supportsDynamicShadow() {
+        return ShadowHelper.getInstance().supportsDynamicShadow();
+    }
+
+    /**
+     * Returns true if the platform sdk supports rounded corner through outline.
+     */
+    public static boolean supportsRoundedCorner() {
+        return RoundedRectHelper.supportsRoundedCorner();
+    }
+
+    /**
+     * Returns true if view.setForeground() is supported.
+     */
+    public static boolean supportsForeground() {
+        return ForegroundHelper.supportsForeground();
+    }
+
+    /**
+     * Create ShadowHelper that includes all options.
+     *
+     * @param context               Context that required to query options
+     * @param needsOverlay          true if overlay (dim) is needed
+     * @param needsShadow           true if shadow is needed
+     * @param needsRoundedCorner    true if roundedCorner is needed.
+     * @param preferZOrder          true if prefer dynamic shadow otherwise static shadow is used.
+     */
+    public ShadowOverlayHelper(Context context,
+            boolean needsOverlay, boolean needsShadow, boolean needsRoundedCorner,
+            boolean preferZOrder) {
+        mNeedsOverlay = needsOverlay;
+        mNeedsRoundedCorner = needsRoundedCorner && supportsRoundedCorner();
+        mNeedsShadow = needsShadow && supportsShadow();
+
+        // Force to use wrapper to avoid rebuild rounded corner outline on animating foreground
+        // drawable.  See b/22724385
+        final boolean forceWrapperForOverlay = mNeedsRoundedCorner;
+
+        // figure out shadow type and if we need use wrapper:
+        if (mNeedsShadow) {
+            // if static shadow is prefered or dynamic shadow is not supported,
+            // use static shadow,  otherwise use dynamic shadow.
+            if (!preferZOrder || !supportsDynamicShadow()) {
+                mShadowType = SHADOW_STATIC;
+                // static shadow requires ShadowOverlayContainer to support crossfading
+                // of two shadow views.
+                mNeedsWrapper = true;
+            } else {
+                useDynamicShadow(context);
+                mNeedsWrapper = ((!supportsForeground() || forceWrapperForOverlay) && mNeedsOverlay);
+            }
+        } else {
+            mShadowType = SHADOW_NONE;
+            mNeedsWrapper = ((!supportsForeground() || forceWrapperForOverlay) && mNeedsOverlay);
+        }
+
+        if (mNeedsWrapper) {
+            mCardWrapper = new ItemBridgeAdapter.Wrapper() {
+                @Override
+                public View createWrapper(View root) {
+                    Context context = root.getContext();
+                    ShadowOverlayContainer wrapper = createShadowOverlayContainer(context);
+                    wrapper.setLayoutParams(
+                            new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+                    return wrapper;
+                }
+                @Override
+                public void wrap(View wrapper, View wrapped) {
+                    ((ShadowOverlayContainer) wrapper).wrap(wrapped);
+                }
+            };
+        }
+    }
+
+    /**
+     * {@link #prepareParentForShadow(ViewGroup)} must be called on parent of container
+     * before using shadow.  Depending on Shadow type, optical bounds might be applied.
+     */
+    public void prepareParentForShadow(ViewGroup parent) {
+        if (mShadowType == SHADOW_STATIC) {
+            StaticShadowHelper.getInstance().prepareParent(parent);
+        }
+    }
+
+    void useDynamicShadow(Context context) {
+        Resources res = context.getResources();
+        useDynamicShadow(res.getDimension(R.dimen.lb_material_shadow_normal_z),
+                res.getDimension(R.dimen.lb_material_shadow_focused_z));
+    }
+
+    void useDynamicShadow(float unfocusedZ, float focusedZ) {
+        mShadowType = SHADOW_DYNAMIC;
+        mUnfocusedZ = unfocusedZ;
+        mFocusedZ = focusedZ;
+    }
+
+    public int getShadowType() {
+        return mShadowType;
+    }
+
+    public boolean needsOverlay() {
+        return mNeedsOverlay;
+    }
+
+    public boolean needsRoundedCorner() {
+        return mNeedsRoundedCorner;
+    }
+
+    ShadowOverlayContainer createShadowOverlayContainer(Context context) {
+        return new ShadowOverlayContainer(context, mShadowType, mNeedsOverlay,
+                mNeedsRoundedCorner);
+    }
+
+    public ItemBridgeAdapter.Wrapper getWrapper() {
+        return mCardWrapper;
+    }
+
+    /**
+     * Set foreground color for view other than ShadowOverlayContainer.
+     */
+    public static void setForegroundColor(View view, int color) {
+        Drawable d = ForegroundHelper.getInstance().getForeground(view);
+        if (d instanceof ColorDrawable) {
+            ((ColorDrawable) d).setColor(color);
+        } else {
+            ForegroundHelper.getInstance().setForeground(view, new ColorDrawable(color));
+        }
+    }
+
+    /**
+     * Called on view is created.
+     * @param view
+     */
+    public void onViewCreated(View view) {
+        if (!mNeedsWrapper) {
+            if (!mNeedsShadow) {
+                if (mNeedsRoundedCorner) {
+                    RoundedRectHelper.getInstance().setClipToRoundedOutline(view, true);
+                }
+            } else {
+                if (mShadowType == SHADOW_DYNAMIC) {
+                    Object tag = ShadowHelper.getInstance().addDynamicShadow(
+                            view, mUnfocusedZ, mFocusedZ, mNeedsRoundedCorner);
+                    view.setTag(R.id.lb_shadow_impl, tag);
+                }
+            }
+        }
+    }
+
+    public static Object getNoneWrapperDyamicShadowImpl(View view) {
+        return view.getTag(R.id.lb_shadow_impl);
+    }
+
+    /**
+     * Set shadow focus level (0 to 1). 0 for unfocused, 1f for fully focused.
+     * This is for view other than ShadowOverlayContainer.
+     */
+    public static void setShadowFocusLevel(View view, float level) {
+        setShadowFocusLevel(getNoneWrapperDyamicShadowImpl(view), SHADOW_DYNAMIC, level);
+    }
+
+    static void setShadowFocusLevel(Object impl, int shadowType, float level) {
+        if (impl != null) {
+            if (level < 0f) {
+                level = 0f;
+            } else if (level > 1f) {
+                level = 1f;
+            }
+            switch (shadowType) {
+                case SHADOW_DYNAMIC:
+                    ShadowHelper.getInstance().setShadowFocusLevel(impl, level);
+                    break;
+                case SHADOW_STATIC:
+                    StaticShadowHelper.getInstance().setShadowFocusLevel(impl, level);
+                    break;
+            }
+        }
+    }
+}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/StaticShadowHelper.java b/v17/leanback/src/android/support/v17/leanback/widget/StaticShadowHelper.java
index 4d8411b..022ff1d 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/StaticShadowHelper.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/StaticShadowHelper.java
@@ -34,7 +34,7 @@
      */
     static interface ShadowHelperVersionImpl {
         public void prepareParent(ViewGroup parent);
-        public Object addStaticShadow(ViewGroup shadowContainer, boolean roundedCorners);
+        public Object addStaticShadow(ViewGroup shadowContainer);
         public void setShadowFocusLevel(Object impl, float level);
     }
 
@@ -48,7 +48,7 @@
         }
 
         @Override
-        public Object addStaticShadow(ViewGroup shadowContainer, boolean roundedCorners) {
+        public Object addStaticShadow(ViewGroup shadowContainer) {
             // do nothing
             return null;
         }
@@ -69,8 +69,7 @@
         }
 
         @Override
-        public Object addStaticShadow(ViewGroup shadowContainer, boolean roundedCorners) {
-            // Static shadows are always rounded
+        public Object addStaticShadow(ViewGroup shadowContainer) {
             return ShadowHelperJbmr2.addShadow(shadowContainer);
         }
 
@@ -105,8 +104,8 @@
         mImpl.prepareParent(parent);
     }
 
-    public Object addStaticShadow(ViewGroup shadowContainer, boolean roundedCorners) {
-        return mImpl.addStaticShadow(shadowContainer, roundedCorners);
+    public Object addStaticShadow(ViewGroup shadowContainer) {
+        return mImpl.addStaticShadow(shadowContainer);
     }
 
     public void setShadowFocusLevel(Object impl, float level) {
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/VerticalGridPresenter.java b/v17/leanback/src/android/support/v17/leanback/widget/VerticalGridPresenter.java
index 16b66cd..c04fe85 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/VerticalGridPresenter.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/VerticalGridPresenter.java
@@ -31,6 +31,13 @@
 
     class VerticalGridItemBridgeAdapter extends ItemBridgeAdapter {
         @Override
+        protected void onCreate(ItemBridgeAdapter.ViewHolder viewHolder) {
+            if (mShadowOverlayHelper != null) {
+                mShadowOverlayHelper.onViewCreated(viewHolder.itemView);
+            }
+        }
+
+        @Override
         public void onBind(final ItemBridgeAdapter.ViewHolder itemViewHolder) {
             // Only when having an OnItemClickListner, we attach the OnClickListener.
             if (getOnItemViewClickedListener() != null) {
@@ -86,6 +93,7 @@
     private OnItemViewSelectedListener mOnItemViewSelectedListener;
     private OnItemViewClickedListener mOnItemViewClickedListener;
     private boolean mRoundedCornersEnabled = true;
+    private ShadowOverlayHelper mShadowOverlayHelper;
 
     /**
      * Constructs a VerticalGridPresenter with defaults.
@@ -170,7 +178,7 @@
      * Subclass may return false to disable.
      */
     public boolean isUsingDefaultShadow() {
-        return ShadowOverlayContainer.supportsShadow();
+        return ShadowOverlayHelper.supportsShadow();
     }
 
     /**
@@ -194,8 +202,7 @@
      * and does not use Z-shadow on SDK >= L, it should override isUsingZOrder() return false.
      */
     public boolean isUsingZOrder(Context context) {
-        return ShadowOverlayContainer.supportsDynamicShadow() &&
-                !Settings.getInstance(context).preferStaticShadows();
+        return !Settings.getInstance(context).preferStaticShadows();
     }
 
     final boolean needsDefaultShadow() {
@@ -238,21 +245,6 @@
         return new ViewHolder((VerticalGridView) root.findViewById(R.id.browse_grid));
     }
 
-    private ItemBridgeAdapter.Wrapper mWrapper = new ItemBridgeAdapter.Wrapper() {
-        @Override
-        public View createWrapper(View root) {
-            ShadowOverlayContainer wrapper = new ShadowOverlayContainer(root.getContext());
-            wrapper.setLayoutParams(
-                    new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
-            wrapper.initialize(needsDefaultShadow(), true, areChildRoundedCornersEnabled());
-            return wrapper;
-        }
-        @Override
-        public void wrap(View wrapper, View wrapped) {
-            ((ShadowOverlayContainer) wrapper).wrap(wrapped);
-        }
-    };
-
     /**
      * Called after a {@link VerticalGridPresenter.ViewHolder} is created.
      * Subclasses may override this method and start by calling
@@ -268,12 +260,15 @@
         vh.getGridView().setNumColumns(mNumColumns);
         vh.mInitialized = true;
 
-        vh.mItemBridgeAdapter.setWrapper(mWrapper);
-        if (needsDefaultShadow() || areChildRoundedCornersEnabled()) {
-            ShadowOverlayContainer.prepareParentForShadow(vh.getGridView());
-            ((ViewGroup) vh.view).setClipChildren(false);
+        Context context = vh.mGridView.getContext();
+        if (mShadowOverlayHelper == null) {
+            mShadowOverlayHelper = new ShadowOverlayHelper(context, mUseFocusDimmer,
+                    needsDefaultShadow(), areChildRoundedCornersEnabled(), isUsingZOrder(context));
         }
-        vh.getGridView().setFocusDrawingOrderEnabled(!isUsingZOrder(vh.getGridView().getContext()));
+        vh.mItemBridgeAdapter.setWrapper(mShadowOverlayHelper.getWrapper());
+        mShadowOverlayHelper.prepareParentForShadow(vh.mGridView);
+        vh.getGridView().setFocusDrawingOrderEnabled(mShadowOverlayHelper.getShadowType()
+                == ShadowOverlayHelper.SHADOW_STATIC);
         FocusHighlightHelper.setupBrowseItemFocusHighlight(vh.mItemBridgeAdapter,
                 mFocusZoomFactor, mUseFocusDimmer);
 
diff --git a/v17/preference-leanback/res/color/lb_preference_item_primary_text_color.xml b/v17/preference-leanback/res/color/lb_preference_item_primary_text_color.xml
new file mode 100644
index 0000000..efdf1c0
--- /dev/null
+++ b/v17/preference-leanback/res/color/lb_preference_item_primary_text_color.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false" android:color="@color/lb_preference_item_primary_text_color_disabled" />
+    <item android:color="@color/lb_preference_item_primary_text_color_default"/>
+</selector>
diff --git a/v17/preference-leanback/res/color/lb_preference_item_secondary_text_color.xml b/v17/preference-leanback/res/color/lb_preference_item_secondary_text_color.xml
new file mode 100644
index 0000000..68bb81a
--- /dev/null
+++ b/v17/preference-leanback/res/color/lb_preference_item_secondary_text_color.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false" android:color="@color/lb_preference_item_secondary_text_color_disabled" />
+    <item android:color="@color/lb_preference_item_secondary_text_color_default"/>
+</selector>
diff --git a/v17/preference-leanback/res/layout/leanback_list_preference_fragment.xml b/v17/preference-leanback/res/layout/leanback_list_preference_fragment.xml
index 9fae0f8..c0a5bf9 100644
--- a/v17/preference-leanback/res/layout/leanback_list_preference_fragment.xml
+++ b/v17/preference-leanback/res/layout/leanback_list_preference_fragment.xml
@@ -35,11 +35,11 @@
             android:id="@+id/decor_title"
             android:layout_width="match_parent"
             android:layout_height="@dimen/lb_preference_decor_title_text_height"
+            android:layout_marginTop="@dimen/lb_preference_decor_title_margin_top"
+            android:layout_marginStart="@dimen/lb_preference_decor_title_margin_start"
+            android:layout_marginEnd="@dimen/lb_preference_decor_title_margin_end"
             android:fontFamily="sans-serif-condensed"
             android:gravity="center_vertical"
-            android:paddingTop="@dimen/lb_preference_decor_title_padding_top"
-            android:paddingStart="@dimen/lb_preference_decor_title_padding_start"
-            android:paddingEnd="@dimen/lb_preference_decor_title_padding_end"
             android:singleLine="true"
             android:textSize="@dimen/lb_preference_decor_title_text_size"
             android:textColor="?android:attr/textColorPrimary"
diff --git a/v17/preference-leanback/res/layout/leanback_list_preference_item_multi.xml b/v17/preference-leanback/res/layout/leanback_list_preference_item_multi.xml
index 3b1345c..04ea1dc 100644
--- a/v17/preference-leanback/res/layout/leanback_list_preference_item_multi.xml
+++ b/v17/preference-leanback/res/layout/leanback_list_preference_item_multi.xml
@@ -18,20 +18,34 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/container"
     android:layout_width="match_parent"
-    android:layout_height="?android:attr/listPreferredItemHeight"
+    android:layout_height="wrap_content"
     android:background="?android:attr/selectableItemBackground"
     android:clickable="true"
     android:focusable="true"
     android:descendantFocusability="blocksDescendants"
-    android:orientation="horizontal">
+    android:orientation="horizontal"
+    android:paddingStart="@dimen/lb_preference_item_padding_start"
+    android:paddingEnd="@dimen/lb_preference_item_padding_end" >
+
     <CheckBox
         android:id="@+id/button"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content" />
-    <TextView
-        android:id="@android:id/title"
-        android:layout_width="0dp"
-        android:layout_height="match_parent"
-        android:layout_weight="1"
-        android:gravity="center_vertical" />
+        android:layout_width="@dimen/lb_preference_item_icon_size"
+        android:layout_height="@dimen/lb_preference_item_icon_size"
+        android:layout_marginEnd="@dimen/lb_preference_item_icon_margin_end"
+        android:layout_gravity="center_vertical" />
+
+    <LinearLayout android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+        <Space android:layout_width="0dp" android:layout_height="@dimen/lb_preference_item_text_space_top" />
+        <TextView
+            android:id="@android:id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginBottom="@dimen/lb_preference_item_primary_text_margin_bottom"
+            android:textColor="@color/lb_preference_item_primary_text_color"
+            android:textSize="@dimen/lb_preference_item_primary_text_size"/>
+        <Space android:layout_width="0dp" android:layout_height="@dimen/lb_preference_item_text_space_bottom" />
+    </LinearLayout>
+
 </LinearLayout>
diff --git a/v17/preference-leanback/res/layout/leanback_list_preference_item_single.xml b/v17/preference-leanback/res/layout/leanback_list_preference_item_single.xml
index eaf42a4..23e94bc 100644
--- a/v17/preference-leanback/res/layout/leanback_list_preference_item_single.xml
+++ b/v17/preference-leanback/res/layout/leanback_list_preference_item_single.xml
@@ -18,20 +18,34 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/container"
     android:layout_width="match_parent"
-    android:layout_height="?android:attr/listPreferredItemHeight"
+    android:layout_height="wrap_content"
     android:background="?android:attr/selectableItemBackground"
     android:clickable="true"
     android:focusable="true"
     android:descendantFocusability="blocksDescendants"
-    android:orientation="horizontal">
+    android:orientation="horizontal"
+    android:paddingStart="@dimen/lb_preference_item_padding_start"
+    android:paddingEnd="@dimen/lb_preference_item_padding_end" >
+
     <RadioButton
         android:id="@+id/button"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content" />
-    <TextView
-        android:id="@android:id/title"
-        android:layout_width="0dp"
-        android:layout_height="match_parent"
-        android:layout_weight="1"
-        android:gravity="center_vertical" />
+        android:layout_width="@dimen/lb_preference_item_icon_size"
+        android:layout_height="@dimen/lb_preference_item_icon_size"
+        android:layout_marginEnd="@dimen/lb_preference_item_icon_margin_end"
+        android:layout_gravity="center_vertical" />
+
+    <LinearLayout android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+        <Space android:layout_width="0dp" android:layout_height="@dimen/lb_preference_item_text_space_top" />
+        <TextView
+            android:id="@android:id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginBottom="@dimen/lb_preference_item_primary_text_margin_bottom"
+            android:textColor="@color/lb_preference_item_primary_text_color"
+            android:textSize="@dimen/lb_preference_item_primary_text_size"/>
+        <Space android:layout_width="0dp" android:layout_height="@dimen/lb_preference_item_text_space_bottom" />
+    </LinearLayout>
+
 </LinearLayout>
diff --git a/v17/preference-leanback/res/layout/leanback_preference.xml b/v17/preference-leanback/res/layout/leanback_preference.xml
new file mode 100644
index 0000000..ca391c9
--- /dev/null
+++ b/v17/preference-leanback/res/layout/leanback_preference.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="?android:attr/selectableItemBackground"
+    android:clickable="true"
+    android:focusable="true"
+    android:descendantFocusability="blocksDescendants"
+    android:orientation="horizontal"
+    android:paddingStart="@dimen/lb_preference_item_padding_start"
+    android:paddingEnd="@dimen/lb_preference_item_padding_end" >
+
+    <FrameLayout
+        android:id="@+id/icon_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical" >
+        <ImageView
+            android:id="@android:id/icon"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            />
+    </FrameLayout>
+
+    <LinearLayout android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:orientation="vertical">
+        <Space android:layout_width="0dp" android:layout_height="@dimen/lb_preference_item_text_space_top" />
+        <TextView
+            android:id="@android:id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginBottom="@dimen/lb_preference_item_primary_text_margin_bottom"
+            android:textColor="@color/lb_preference_item_primary_text_color"
+            android:textSize="@dimen/lb_preference_item_primary_text_size"/>
+        <TextView
+            android:id="@android:id/summary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textColor="@color/lb_preference_item_secondary_text_color"
+            android:textSize="@dimen/lb_preference_item_secondary_text_size"
+            android:maxLines="4" />
+        <Space android:layout_width="0dp" android:layout_height="@dimen/lb_preference_item_text_space_bottom" />
+    </LinearLayout>
+
+    <!-- Preference should place its actual preference widget here. -->
+    <LinearLayout android:id="@android:id/widget_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:gravity="center_vertical"
+        android:orientation="vertical" />
+
+</LinearLayout>
diff --git a/v17/preference-leanback/res/layout/leanback_preference_category.xml b/v17/preference-leanback/res/layout/leanback_preference_category.xml
new file mode 100644
index 0000000..b3c2067
--- /dev/null
+++ b/v17/preference-leanback/res/layout/leanback_preference_category.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/lb_preference_category_height"
+    android:paddingStart="@dimen/lb_preference_item_padding_start"
+    android:paddingEnd="@dimen/lb_preference_item_padding_end">
+
+    <TextView
+        android:id="@android:id/title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:textColor="@color/lb_preference_item_primary_text_color"
+        android:textSize="@dimen/lb_preference_category_text_size"/>
+</FrameLayout>
diff --git a/v17/preference-leanback/res/layout/leanback_preference_fragment.xml b/v17/preference-leanback/res/layout/leanback_preference_fragment.xml
index d119c2d..ffbbf66 100644
--- a/v17/preference-leanback/res/layout/leanback_preference_fragment.xml
+++ b/v17/preference-leanback/res/layout/leanback_preference_fragment.xml
@@ -35,11 +35,11 @@
             android:id="@+id/decor_title"
             android:layout_width="match_parent"
             android:layout_height="@dimen/lb_preference_decor_title_text_height"
+            android:layout_marginTop="@dimen/lb_preference_decor_title_margin_top"
+            android:layout_marginStart="@dimen/lb_preference_decor_title_margin_start"
+            android:layout_marginEnd="@dimen/lb_preference_decor_title_margin_end"
             android:fontFamily="sans-serif-condensed"
             android:gravity="center_vertical"
-            android:paddingTop="@dimen/lb_preference_decor_title_padding_top"
-            android:paddingStart="@dimen/lb_preference_decor_title_padding_start"
-            android:paddingEnd="@dimen/lb_preference_decor_title_padding_end"
             android:singleLine="true"
             android:textSize="@dimen/lb_preference_decor_title_text_size"
             android:textColor="?android:attr/textColorPrimary"
diff --git a/v17/preference-leanback/res/layout/leanback_preference_information.xml b/v17/preference-leanback/res/layout/leanback_preference_information.xml
new file mode 100644
index 0000000..8c0c4b9
--- /dev/null
+++ b/v17/preference-leanback/res/layout/leanback_preference_information.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="?android:attr/selectableItemBackground"
+    android:clickable="false"
+    android:focusable="false"
+    android:descendantFocusability="blocksDescendants"
+    android:orientation="horizontal"
+    android:paddingStart="@dimen/lb_preference_item_padding_start"
+    android:paddingEnd="@dimen/lb_preference_item_padding_end" >
+
+    <LinearLayout android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:orientation="vertical">
+        <Space android:layout_width="0dp" android:layout_height="@dimen/lb_preference_item_text_space_top" />
+        <TextView
+            android:id="@android:id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginBottom="@dimen/lb_preference_item_primary_text_margin_bottom"
+            android:textColor="@color/lb_preference_item_primary_text_color"
+            android:textSize="@dimen/lb_preference_item_primary_text_size"/>
+        <TextView
+            android:id="@android:id/summary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textColor="@color/lb_preference_item_secondary_text_color"
+            android:textSize="@dimen/lb_preference_item_secondary_text_size"
+            android:maxLines="4" />
+        <Space android:layout_width="0dp" android:layout_height="@dimen/lb_preference_item_text_space_bottom" />
+    </LinearLayout>
+
+    <!-- Preference should place its actual preference widget here. -->
+    <LinearLayout android:id="@android:id/widget_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:gravity="center_vertical"
+        android:orientation="vertical" />
+
+</LinearLayout>
diff --git a/v17/preference-leanback/res/values/colors.xml b/v17/preference-leanback/res/values/colors.xml
index de6c888..30a373a 100644
--- a/v17/preference-leanback/res/values/colors.xml
+++ b/v17/preference-leanback/res/values/colors.xml
@@ -16,4 +16,11 @@
   -->
 <resources>
     <color name="lb_preference_decor_list_background">#263238</color>
+
+    <color name="lb_preference_item_primary_text_color_default">#EEEEEE</color>
+    <color name="lb_preference_item_primary_text_color_disabled">#4DEEEEEE</color>
+
+    <color name="lb_preference_item_secondary_text_color_default">#B3EEEEEE</color>
+    <color name="lb_preference_item_secondary_text_color_disabled">#4DEEEEEE</color>
+
 </resources>
diff --git a/v17/preference-leanback/res/values/dimens.xml b/v17/preference-leanback/res/values/dimens.xml
index 49763fe..dbd3b04 100644
--- a/v17/preference-leanback/res/values/dimens.xml
+++ b/v17/preference-leanback/res/values/dimens.xml
@@ -15,11 +15,25 @@
   ~ limitations under the License
   -->
 <resources>
-  <dimen name="lb_preference_decor_title_text_height">64dp</dimen>
-  <dimen name="lb_preference_decor_title_padding_top">27dp</dimen>
-  <dimen name="lb_preference_decor_title_padding_start">24dp</dimen>
-  <dimen name="lb_preference_decor_title_padding_end">56dp</dimen>
-  <dimen name="lb_preference_decor_title_text_size">20sp</dimen>
+    <dimen name="lb_preference_decor_title_text_height">64dp</dimen>
+    <dimen name="lb_preference_decor_title_margin_top">27dp</dimen>
+    <dimen name="lb_preference_decor_title_margin_start">24dp</dimen>
+    <dimen name="lb_preference_decor_title_margin_end">56dp</dimen>
+    <dimen name="lb_preference_decor_title_text_size">20sp</dimen>
 
-  <dimen name="lb_settings_pane_width">360dp</dimen>
+    <dimen name="lb_preference_item_padding_start">24dp</dimen>
+    <dimen name="lb_preference_item_padding_end">56dp</dimen>
+    <dimen name="lb_preference_item_icon_size">32dp</dimen>
+    <dimen name="lb_preference_item_icon_margin_end">16dp</dimen>
+
+    <dimen name="lb_preference_item_primary_text_size">14sp</dimen>
+    <dimen name="lb_preference_item_primary_text_margin_bottom">2dp</dimen>
+    <dimen name="lb_preference_item_secondary_text_size">12sp</dimen>
+    <dimen name="lb_preference_item_text_space_top">14dp</dimen>
+    <dimen name="lb_preference_item_text_space_bottom">13dp</dimen>
+
+    <dimen name="lb_preference_category_text_size">12sp</dimen>
+    <dimen name="lb_preference_category_height">40dp</dimen>
+
+    <dimen name="lb_settings_pane_width">360dp</dimen>
 </resources>
diff --git a/v17/preference-leanback/res/values/styles.xml b/v17/preference-leanback/res/values/styles.xml
new file mode 100644
index 0000000..0b315a8
--- /dev/null
+++ b/v17/preference-leanback/res/values/styles.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+
+<resources>
+
+    <style name="LeanbackPreference">
+        <item name="layout">@layout/leanback_preference</item>
+    </style>
+
+    <style name="LeanbackPreference.Information">
+        <item name="layout">@layout/leanback_preference_information</item>
+        <item name="enabled">false</item>
+        <item name="shouldDisableView">false</item>
+    </style>
+
+    <style name="LeanbackPreference.Category">
+        <item name="layout">@layout/leanback_preference_category</item>
+        <!-- The title should not dim if the category is disabled, instead only the preference children should dim. -->
+        <item name="shouldDisableView">false</item>
+        <item name="selectable">false</item>
+    </style>
+
+    <style name="LeanbackPreference.CheckBoxPreference">
+        <item name="widgetLayout">@layout/preference_widget_checkbox</item>
+    </style>
+
+    <style name="LeanbackPreference.SwitchPreferenceCompat">
+        <item name="widgetLayout">@layout/preference_widget_switch_compat</item>
+        <item name="switchTextOn">@string/v7_preference_on</item>
+        <item name="switchTextOff">@string/v7_preference_off</item>
+    </style>
+
+    <style name="LeanbackPreference.SwitchPreference">
+        <item name="widgetLayout">@layout/preference_widget_switch</item>
+        <item name="switchTextOn">@string/v7_preference_on</item>
+        <item name="switchTextOff">@string/v7_preference_off</item>
+    </style>
+
+    <style name="LeanbackPreference.PreferenceScreen">
+    </style>
+
+    <style name="LeanbackPreference.DialogPreference">
+        <item name="positiveButtonText">@android:string/ok</item>
+        <item name="negativeButtonText">@android:string/cancel</item>
+    </style>
+
+    <style name="LeanbackPreference.DialogPreference.EditTextPreference">
+        <item name="dialogLayout">@layout/preference_dialog_edittext</item>
+    </style>
+
+</resources>
diff --git a/v17/preference-leanback/res/values/themes.xml b/v17/preference-leanback/res/values/themes.xml
new file mode 100644
index 0000000..b3060d9
--- /dev/null
+++ b/v17/preference-leanback/res/values/themes.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+
+<resources>
+    <style name="PreferenceThemeOverlay.v14.Leanback">
+        <item name="preferenceScreenStyle">@style/LeanbackPreference.PreferenceScreen</item>
+        <item name="preferenceCategoryStyle">@style/LeanbackPreference.Category</item>
+        <item name="preferenceStyle">@style/LeanbackPreference</item>
+        <item name="preferenceInformationStyle">@style/LeanbackPreference.Information</item>
+        <item name="checkBoxPreferenceStyle">@style/LeanbackPreference.CheckBoxPreference</item>
+        <item name="switchPreferenceCompatStyle">@style/LeanbackPreference.SwitchPreferenceCompat</item>
+        <item name="switchPreferenceStyle">@style/LeanbackPreference.SwitchPreference</item>
+        <item name="dialogPreferenceStyle">@style/LeanbackPreference.DialogPreference</item>
+        <item name="editTextPreferenceStyle">@style/LeanbackPreference.DialogPreference.EditTextPreference</item>
+    </style>
+</resources>
diff --git a/v4/java/android/support/v4/graphics/ColorUtils.java b/v4/java/android/support/v4/graphics/ColorUtils.java
index aac809b..4d9d9b2 100644
--- a/v4/java/android/support/v4/graphics/ColorUtils.java
+++ b/v4/java/android/support/v4/graphics/ColorUtils.java
@@ -17,6 +17,10 @@
 package android.support.v4.graphics;
 
 import android.graphics.Color;
+import android.support.annotation.ColorInt;
+import android.support.annotation.FloatRange;
+import android.support.annotation.IntRange;
+import android.support.annotation.NonNull;
 
 /**
  * A set of color-related utility methods, building upon those available in {@code Color}.
@@ -24,14 +28,14 @@
 public class ColorUtils {
 
     private static final int MIN_ALPHA_SEARCH_MAX_ITERATIONS = 10;
-    private static final int MIN_ALPHA_SEARCH_PRECISION = 10;
+    private static final int MIN_ALPHA_SEARCH_PRECISION = 1;
 
     private ColorUtils() {}
 
     /**
      * Composite two potentially translucent colors over each other and returns the result.
      */
-    public static int compositeColors(int foreground, int background) {
+    public static int compositeColors(@ColorInt int foreground, @ColorInt int background) {
         int bgAlpha = Color.alpha(background);
         int fgAlpha = Color.alpha(foreground);
         int a = compositeAlpha(fgAlpha, bgAlpha);
@@ -57,10 +61,13 @@
 
     /**
      * Returns the luminance of a color.
-     *
-     * Formula defined here: http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
+     * <p>
+     * Formula defined
+     * <a href="http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef">here</a>.
+     * </p>
      */
-    public static double calculateLuminance(int color) {
+    @FloatRange(from = 0.0, to = 1.0)
+    public static double calculateLuminance(@ColorInt int color) {
         double red = Color.red(color) / 255d;
         red = red < 0.03928 ? red / 12.92 : Math.pow((red + 0.055) / 1.055, 2.4);
 
@@ -80,9 +87,10 @@
      * Formula defined
      * <a href="http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef">here</a>.
      */
-    public static double calculateContrast(int foreground, int background) {
+    public static double calculateContrast(@ColorInt int foreground, @ColorInt int background) {
         if (Color.alpha(background) != 255) {
-            throw new IllegalArgumentException("background can not be translucent");
+            throw new IllegalArgumentException("background can not be translucent: #"
+                    + Integer.toHexString(background));
         }
         if (Color.alpha(foreground) < 255) {
             // If the foreground is translucent, composite the foreground over the background
@@ -106,10 +114,11 @@
      * @param minContrastRatio the minimum contrast ratio.
      * @return the alpha value in the range 0-255, or -1 if no value could be calculated.
      */
-    public static int calculateMinimumAlpha(int foreground, int background,
+    public static int calculateMinimumAlpha(@ColorInt int foreground, @ColorInt int background,
             float minContrastRatio) {
         if (Color.alpha(background) != 255) {
-            throw new IllegalArgumentException("background can not be translucent");
+            throw new IllegalArgumentException("background can not be translucent: #"
+                    + Integer.toHexString(background));
         }
 
         // First lets check that a fully opaque foreground has sufficient contrast
@@ -158,7 +167,9 @@
      * @param b   blue component value [0..255]
      * @param hsl 3 element array which holds the resulting HSL components.
      */
-    public static void RGBToHSL(int r, int g, int b, float[] hsl) {
+    public static void RGBToHSL(@IntRange(from = 0x0, to = 0xFF) int r,
+            @IntRange(from = 0x0, to = 0xFF) int g, @IntRange(from = 0x0, to = 0xFF) int b,
+            @NonNull float[] hsl) {
         final float rf = r / 255f;
         final float gf = g / 255f;
         final float bf = b / 255f;
@@ -206,7 +217,7 @@
      * @param color the ARGB color to convert. The alpha component is ignored.
      * @param hsl 3 element array which holds the resulting HSL components.
      */
-    public static void colorToHSL(int color, float[] hsl) {
+    public static void colorToHSL(@ColorInt int color, @NonNull float[] hsl) {
         RGBToHSL(Color.red(color), Color.green(color), Color.blue(color), hsl);
     }
 
@@ -222,7 +233,8 @@
      * @param hsl 3 element array which holds the input HSL components.
      * @return the resulting RGB color
      */
-    public static int HSLToColor(float[] hsl) {
+    @ColorInt
+    public static int HSLToColor(@NonNull float[] hsl) {
         final float h = hsl[0];
         final float s = hsl[1];
         final float l = hsl[2];
@@ -279,7 +291,9 @@
     /**
      * Set the alpha component of {@code color} to be {@code alpha}.
      */
-    public static int setAlphaComponent(int color, int alpha) {
+    @ColorInt
+    public static int setAlphaComponent(@ColorInt int color,
+            @IntRange(from = 0x0, to = 0xFF) int alpha) {
         if (alpha < 0 || alpha > 255) {
             throw new IllegalArgumentException("alpha must be between 0 and 255.");
         }
diff --git a/v4/tests/java/android/support/v4/graphics/ColorUtilsTest.java b/v4/tests/java/android/support/v4/graphics/ColorUtilsTest.java
index 855cdba..56cb6fb 100644
--- a/v4/tests/java/android/support/v4/graphics/ColorUtilsTest.java
+++ b/v4/tests/java/android/support/v4/graphics/ColorUtilsTest.java
@@ -17,9 +17,9 @@
 package android.support.v4.graphics;
 
 import android.graphics.Color;
-import android.support.v4.graphics.ColorUtils;
 import android.test.AndroidTestCase;
 
+import java.lang.Integer;
 import java.util.ArrayList;
 
 /**
@@ -31,21 +31,31 @@
     private static final float ALLOWED_OFFSET_HUE = 360 * 0.005f;
     private static final float ALLOWED_OFFSET_SATURATION = 0.005f;
     private static final float ALLOWED_OFFSET_LIGHTNESS = 0.005f;
+    private static final float ALLOWED_OFFSET_MIN_ALPHA = 0.01f;
 
     private static final int ALLOWED_OFFSET_RGB_COMPONENT = 2;
 
     private static final ArrayList<TestEntry> sEntryList = new ArrayList<>();
 
     static {
-        sEntryList.add(new TestEntry(Color.BLACK).setHsl(0f, 0f, 0f));
-        sEntryList.add(new TestEntry(Color.WHITE).setHsl(0f, 0f, 1f));
-        sEntryList.add(new TestEntry(Color.BLUE).setHsl(240f, 1f, 0.5f));
-        sEntryList.add(new TestEntry(Color.GREEN).setHsl(120f, 1f, 0.5f));
-        sEntryList.add(new TestEntry(Color.RED).setHsl(0f, 1f, 0.5f));
-        sEntryList.add(new TestEntry(Color.CYAN).setHsl(180f, 1f, 0.5f));
-        sEntryList.add(new TestEntry(0x2196F3).setHsl(207f, 0.9f, 0.54f));
-        sEntryList.add(new TestEntry(0xD1C4E9).setHsl(261f, 0.46f, 0.84f));
-        sEntryList.add(new TestEntry(0x311B92).setHsl(251.09f, 0.687f, 0.339f));
+        sEntryList.add(new TestEntry(Color.BLACK).setHsl(0f, 0f, 0f)
+                .setWhiteMinAlpha30(0.35f).setWhiteMinAlpha45(0.46f));
+        sEntryList.add(new TestEntry(Color.WHITE).setHsl(0f, 0f, 1f)
+                .setBlackMinAlpha30(0.42f).setBlackMinAlpha45(0.54f));
+        sEntryList.add(new TestEntry(Color.BLUE).setHsl(240f, 1f, 0.5f)
+                .setWhiteMinAlpha30(0.55f).setWhiteMinAlpha45(0.71f));
+        sEntryList.add(new TestEntry(Color.GREEN).setHsl(120f, 1f, 0.5f)
+                .setBlackMinAlpha30(0.43f).setBlackMinAlpha45(0.55f));
+        sEntryList.add(new TestEntry(Color.RED).setHsl(0f, 1f, 0.5f)
+                .setWhiteMinAlpha30(0.84f).setBlackMinAlpha30(0.55f).setBlackMinAlpha45(0.78f));
+        sEntryList.add(new TestEntry(Color.CYAN).setHsl(180f, 1f, 0.5f)
+                .setBlackMinAlpha30(0.43f).setBlackMinAlpha45(0.55f));
+        sEntryList.add(new TestEntry(0xFF2196F3).setHsl(207f, 0.9f, 0.54f)
+                .setBlackMinAlpha30(0.52f).setWhiteMinAlpha30(0.97f).setBlackMinAlpha45(0.7f));
+        sEntryList.add(new TestEntry(0xFFD1C4E9).setHsl(261f, 0.46f, 0.84f)
+                .setBlackMinAlpha30(0.45f).setBlackMinAlpha45(0.58f));
+        sEntryList.add(new TestEntry(0xFF311B92).setHsl(251.09f, 0.687f, 0.339f)
+                .setWhiteMinAlpha30(0.39f).setWhiteMinAlpha45(0.54f));
     }
 
     public void testToHSL() {
@@ -72,6 +82,28 @@
         }
     }
 
+    public void testMinAlphas() {
+        for (TestEntry entry : sEntryList) {
+            testMinAlpha("Black title", entry.rgb, entry.blackMinAlpha30,
+                    ColorUtils.calculateMinimumAlpha(Color.BLACK, entry.rgb, 3.0f));
+            testMinAlpha("Black body", entry.rgb, entry.blackMinAlpha45,
+                    ColorUtils.calculateMinimumAlpha(Color.BLACK, entry.rgb, 4.5f));
+            testMinAlpha("White title", entry.rgb, entry.whiteMinAlpha30,
+                    ColorUtils.calculateMinimumAlpha(Color.WHITE, entry.rgb, 3.0f));
+            testMinAlpha("White body", entry.rgb, entry.whiteMinAlpha45,
+                    ColorUtils.calculateMinimumAlpha(Color.WHITE, entry.rgb, 4.5f));
+        }
+    }
+
+    private static void testMinAlpha(String title, int color, float expected, int actual) {
+        final String message = title + " text within error for #" + Integer.toHexString(color);
+        if (expected < 0) {
+            assertEquals(message, actual, -1);
+        } else {
+            assertClose(message, expected, actual / 255f, ALLOWED_OFFSET_MIN_ALPHA);
+        }
+    }
+
     private static void assertClose(String message, float expected, float actual,
             float allowedOffset) {
         StringBuilder sb = new StringBuilder(message);
@@ -114,6 +146,10 @@
     private static class TestEntry {
         final int rgb;
         final float[] hsl = new float[3];
+        float blackMinAlpha45 = -1;
+        float blackMinAlpha30 = -1;
+        float whiteMinAlpha45 = -1;
+        float whiteMinAlpha30 = -1;
 
         TestEntry(int rgb) {
             this.rgb = rgb;
@@ -125,5 +161,25 @@
             hsl[2] = l;
             return this;
         }
+
+        TestEntry setBlackMinAlpha30(float minAlpha) {
+            blackMinAlpha30 = minAlpha;
+            return this;
+        }
+
+        TestEntry setBlackMinAlpha45(float minAlpha) {
+            blackMinAlpha45 = minAlpha;
+            return this;
+        }
+
+        TestEntry setWhiteMinAlpha30(float minAlpha) {
+            whiteMinAlpha30 = minAlpha;
+            return this;
+        }
+
+        TestEntry setWhiteMinAlpha45(float minAlpha) {
+            whiteMinAlpha45 = minAlpha;
+            return this;
+        }
     }
 }
\ No newline at end of file
diff --git a/v7/appcompat/api/current.txt b/v7/appcompat/api/current.txt
index 336e3a7..0a3bec5 100644
--- a/v7/appcompat/api/current.txt
+++ b/v7/appcompat/api/current.txt
@@ -368,6 +368,7 @@
     field public static int alertDialogCenterButtons;
     field public static int alertDialogStyle;
     field public static int alertDialogTheme;
+    field public static int allowStacking;
     field public static int arrowHeadLength;
     field public static int arrowShaftLength;
     field public static int autoCompleteTextViewStyle;
@@ -477,6 +478,7 @@
     field public static int searchHintIcon;
     field public static int searchIcon;
     field public static int searchViewStyle;
+    field public static int seekBarStyle;
     field public static int selectableItemBackground;
     field public static int selectableItemBackgroundBorderless;
     field public static int showAsAction;
@@ -540,6 +542,7 @@
     field public static int abc_action_bar_embed_tabs;
     field public static int abc_action_bar_embed_tabs_pre_jb;
     field public static int abc_action_bar_expanded_action_views_exclusive;
+    field public static int abc_allow_stacked_button_bar;
     field public static int abc_config_actionMenuItemAllCaps;
     field public static int abc_config_allowActionMenuItemTextWithIcon;
     field public static int abc_config_closeDialogWhenTouchOutside;
@@ -664,6 +667,8 @@
     field public static int abc_panel_menu_list_width;
     field public static int abc_search_view_preferred_width;
     field public static int abc_search_view_text_min_width;
+    field public static int abc_seekbar_track_background_height_material;
+    field public static int abc_seekbar_track_progress_height_material;
     field public static int abc_switch_padding;
     field public static int abc_text_size_body_1_material;
     field public static int abc_text_size_body_2_material;
@@ -748,6 +753,13 @@
     field public static int abc_menu_hardkey_panel_mtrl_mult;
     field public static int abc_popup_background_mtrl_mult;
     field public static int abc_ratingbar_full_material;
+    field public static int abc_scrubber_control_off_mtrl_alpha;
+    field public static int abc_scrubber_control_to_pressed_mtrl_000;
+    field public static int abc_scrubber_control_to_pressed_mtrl_005;
+    field public static int abc_scrubber_primary_mtrl_alpha;
+    field public static int abc_scrubber_track_mtrl_alpha;
+    field public static int abc_seekbar_thumb_material;
+    field public static int abc_seekbar_track_material;
     field public static int abc_spinner_mtrl_am_alpha;
     field public static int abc_spinner_textfield_background_material;
     field public static int abc_switch_thumb_material;
@@ -837,6 +849,7 @@
     field public static int showCustom;
     field public static int showHome;
     field public static int showTitle;
+    field public static int spacer;
     field public static int split_action_bar;
     field public static int src_atop;
     field public static int src_in;
@@ -877,6 +890,7 @@
     field public static int abc_action_mode_close_item_material;
     field public static int abc_activity_chooser_view;
     field public static int abc_activity_chooser_view_list_item;
+    field public static int abc_alert_dialog_button_bar_material;
     field public static int abc_alert_dialog_material;
     field public static int abc_dialog_title_material;
     field public static int abc_expanded_menu_layout;
@@ -1067,6 +1081,7 @@
     field public static int Base_Widget_AppCompat_RatingBar;
     field public static int Base_Widget_AppCompat_SearchView;
     field public static int Base_Widget_AppCompat_SearchView_ActionBar;
+    field public static int Base_Widget_AppCompat_SeekBar;
     field public static int Base_Widget_AppCompat_Spinner;
     field public static int Base_Widget_AppCompat_Spinner_Underlined;
     field public static int Base_Widget_AppCompat_TextView_SpinnerItem;
@@ -1225,6 +1240,7 @@
     field public static int Widget_AppCompat_RatingBar;
     field public static int Widget_AppCompat_SearchView;
     field public static int Widget_AppCompat_SearchView_ActionBar;
+    field public static int Widget_AppCompat_SeekBar;
     field public static int Widget_AppCompat_Spinner;
     field public static int Widget_AppCompat_Spinner_DropDown;
     field public static int Widget_AppCompat_Spinner_DropDown_ActionBar;
@@ -1289,6 +1305,7 @@
     field public static final int[] AppCompatTextView;
     field public static int AppCompatTextView_android_textAppearance;
     field public static int AppCompatTextView_textAllCaps;
+    field public static int ButtonBarLayout_allowStacking;
     field public static final int[] CompoundButton;
     field public static int CompoundButton_android_button;
     field public static int CompoundButton_buttonTint;
@@ -1483,6 +1500,7 @@
     field public static int Theme_radioButtonStyle;
     field public static int Theme_ratingBarStyle;
     field public static int Theme_searchViewStyle;
+    field public static int Theme_seekBarStyle;
     field public static int Theme_selectableItemBackground;
     field public static int Theme_selectableItemBackgroundBorderless;
     field public static int Theme_spinnerDropDownItemStyle;
@@ -1708,6 +1726,12 @@
     ctor public AppCompatRatingBar(android.content.Context, android.util.AttributeSet, int);
   }
 
+  public class AppCompatSeekBar extends android.widget.SeekBar {
+    ctor public AppCompatSeekBar(android.content.Context);
+    ctor public AppCompatSeekBar(android.content.Context, android.util.AttributeSet);
+    ctor public AppCompatSeekBar(android.content.Context, android.util.AttributeSet, int);
+  }
+
   public class AppCompatSpinner extends android.widget.Spinner {
     ctor public AppCompatSpinner(android.content.Context);
     ctor public AppCompatSpinner(android.content.Context, int);
diff --git a/v7/appcompat/res-public/values/public_styles.xml b/v7/appcompat/res-public/values/public_styles.xml
index 4b42d0f..083fbc6 100644
--- a/v7/appcompat/res-public/values/public_styles.xml
+++ b/v7/appcompat/res-public/values/public_styles.xml
@@ -135,6 +135,7 @@
     <public type="style" name="Widget.AppCompat.RatingBar"/>
     <public type="style" name="Widget.AppCompat.SearchView"/>
     <public type="style" name="Widget.AppCompat.SearchView.ActionBar"/>
+    <public type="style" name="Widget.AppCompat.SeekBar"/>
     <public type="style" name="Widget.AppCompat.Spinner"/>
     <public type="style" name="Widget.AppCompat.Spinner.DropDown"/>
     <public type="style" name="Widget.AppCompat.Spinner.DropDown.ActionBar"/>
diff --git a/v7/appcompat/res/drawable-hdpi/abc_scrubber_control_off_mtrl_alpha.png b/v7/appcompat/res/drawable-hdpi/abc_scrubber_control_off_mtrl_alpha.png
new file mode 100644
index 0000000..4efe298
--- /dev/null
+++ b/v7/appcompat/res/drawable-hdpi/abc_scrubber_control_off_mtrl_alpha.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-hdpi/abc_scrubber_control_to_pressed_mtrl_000.png b/v7/appcompat/res/drawable-hdpi/abc_scrubber_control_to_pressed_mtrl_000.png
new file mode 100644
index 0000000..543dec3
--- /dev/null
+++ b/v7/appcompat/res/drawable-hdpi/abc_scrubber_control_to_pressed_mtrl_000.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-hdpi/abc_scrubber_control_to_pressed_mtrl_005.png b/v7/appcompat/res/drawable-hdpi/abc_scrubber_control_to_pressed_mtrl_005.png
new file mode 100644
index 0000000..9930b3a
--- /dev/null
+++ b/v7/appcompat/res/drawable-hdpi/abc_scrubber_control_to_pressed_mtrl_005.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-hdpi/abc_scrubber_primary_mtrl_alpha.9.png b/v7/appcompat/res/drawable-hdpi/abc_scrubber_primary_mtrl_alpha.9.png
new file mode 100644
index 0000000..4cfb1a7
--- /dev/null
+++ b/v7/appcompat/res/drawable-hdpi/abc_scrubber_primary_mtrl_alpha.9.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-hdpi/abc_scrubber_track_mtrl_alpha.9.png b/v7/appcompat/res/drawable-hdpi/abc_scrubber_track_mtrl_alpha.9.png
new file mode 100644
index 0000000..32ddf7a
--- /dev/null
+++ b/v7/appcompat/res/drawable-hdpi/abc_scrubber_track_mtrl_alpha.9.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-mdpi/abc_scrubber_control_off_mtrl_alpha.png b/v7/appcompat/res/drawable-mdpi/abc_scrubber_control_off_mtrl_alpha.png
new file mode 100644
index 0000000..10df639
--- /dev/null
+++ b/v7/appcompat/res/drawable-mdpi/abc_scrubber_control_off_mtrl_alpha.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-mdpi/abc_scrubber_control_to_pressed_mtrl_000.png b/v7/appcompat/res/drawable-mdpi/abc_scrubber_control_to_pressed_mtrl_000.png
new file mode 100644
index 0000000..f83b1ef
--- /dev/null
+++ b/v7/appcompat/res/drawable-mdpi/abc_scrubber_control_to_pressed_mtrl_000.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-mdpi/abc_scrubber_control_to_pressed_mtrl_005.png b/v7/appcompat/res/drawable-mdpi/abc_scrubber_control_to_pressed_mtrl_005.png
new file mode 100644
index 0000000..e9efb20f
--- /dev/null
+++ b/v7/appcompat/res/drawable-mdpi/abc_scrubber_control_to_pressed_mtrl_005.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-mdpi/abc_scrubber_primary_mtrl_alpha.9.png b/v7/appcompat/res/drawable-mdpi/abc_scrubber_primary_mtrl_alpha.9.png
new file mode 100644
index 0000000..a4ab0a1
--- /dev/null
+++ b/v7/appcompat/res/drawable-mdpi/abc_scrubber_primary_mtrl_alpha.9.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-mdpi/abc_scrubber_track_mtrl_alpha.9.png b/v7/appcompat/res/drawable-mdpi/abc_scrubber_track_mtrl_alpha.9.png
new file mode 100644
index 0000000..db9e172
--- /dev/null
+++ b/v7/appcompat/res/drawable-mdpi/abc_scrubber_track_mtrl_alpha.9.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-xhdpi/abc_scrubber_control_off_mtrl_alpha.png b/v7/appcompat/res/drawable-xhdpi/abc_scrubber_control_off_mtrl_alpha.png
new file mode 100644
index 0000000..138f643
--- /dev/null
+++ b/v7/appcompat/res/drawable-xhdpi/abc_scrubber_control_off_mtrl_alpha.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-xhdpi/abc_scrubber_control_to_pressed_mtrl_000.png b/v7/appcompat/res/drawable-xhdpi/abc_scrubber_control_to_pressed_mtrl_000.png
new file mode 100644
index 0000000..cd41d74
--- /dev/null
+++ b/v7/appcompat/res/drawable-xhdpi/abc_scrubber_control_to_pressed_mtrl_000.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-xhdpi/abc_scrubber_control_to_pressed_mtrl_005.png b/v7/appcompat/res/drawable-xhdpi/abc_scrubber_control_to_pressed_mtrl_005.png
new file mode 100644
index 0000000..8d67525
--- /dev/null
+++ b/v7/appcompat/res/drawable-xhdpi/abc_scrubber_control_to_pressed_mtrl_005.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-xhdpi/abc_scrubber_primary_mtrl_alpha.9.png b/v7/appcompat/res/drawable-xhdpi/abc_scrubber_primary_mtrl_alpha.9.png
new file mode 100644
index 0000000..2b4734d
--- /dev/null
+++ b/v7/appcompat/res/drawable-xhdpi/abc_scrubber_primary_mtrl_alpha.9.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-xhdpi/abc_scrubber_track_mtrl_alpha.9.png b/v7/appcompat/res/drawable-xhdpi/abc_scrubber_track_mtrl_alpha.9.png
new file mode 100644
index 0000000..805cb29
--- /dev/null
+++ b/v7/appcompat/res/drawable-xhdpi/abc_scrubber_track_mtrl_alpha.9.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_control_off_mtrl_alpha.png b/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_control_off_mtrl_alpha.png
new file mode 100644
index 0000000..5268745
--- /dev/null
+++ b/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_control_off_mtrl_alpha.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_control_to_pressed_mtrl_000.png b/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_control_to_pressed_mtrl_000.png
new file mode 100644
index 0000000..adffc14
--- /dev/null
+++ b/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_control_to_pressed_mtrl_000.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_control_to_pressed_mtrl_005.png b/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_control_to_pressed_mtrl_005.png
new file mode 100644
index 0000000..f3d16d5
--- /dev/null
+++ b/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_control_to_pressed_mtrl_005.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_primary_mtrl_alpha.9.png b/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_primary_mtrl_alpha.9.png
new file mode 100644
index 0000000..6a82af5
--- /dev/null
+++ b/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_primary_mtrl_alpha.9.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_track_mtrl_alpha.9.png b/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_track_mtrl_alpha.9.png
new file mode 100644
index 0000000..c3791fc
--- /dev/null
+++ b/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_track_mtrl_alpha.9.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-xxxhdpi/abc_scrubber_control_to_pressed_mtrl_000.png b/v7/appcompat/res/drawable-xxxhdpi/abc_scrubber_control_to_pressed_mtrl_000.png
new file mode 100644
index 0000000..e5a43bb
--- /dev/null
+++ b/v7/appcompat/res/drawable-xxxhdpi/abc_scrubber_control_to_pressed_mtrl_000.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-xxxhdpi/abc_scrubber_control_to_pressed_mtrl_005.png b/v7/appcompat/res/drawable-xxxhdpi/abc_scrubber_control_to_pressed_mtrl_005.png
new file mode 100644
index 0000000..eeb37c1
--- /dev/null
+++ b/v7/appcompat/res/drawable-xxxhdpi/abc_scrubber_control_to_pressed_mtrl_005.png
Binary files differ
diff --git a/v7/appcompat/res/drawable/abc_seekbar_thumb_material.xml b/v7/appcompat/res/drawable/abc_seekbar_thumb_material.xml
new file mode 100644
index 0000000..7fea83bc
--- /dev/null
+++ b/v7/appcompat/res/drawable/abc_seekbar_thumb_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+          android:constantSize="true">
+    <item android:state_enabled="false" android:state_pressed="true">
+        <bitmap android:src="@drawable/abc_scrubber_control_off_mtrl_alpha"
+                android:gravity="center"/>
+    </item>
+    <item android:state_enabled="false">
+        <bitmap android:src="@drawable/abc_scrubber_control_off_mtrl_alpha"
+                android:gravity="center"/>
+    </item>
+    <item android:state_pressed="true">
+        <bitmap android:src="@drawable/abc_scrubber_control_to_pressed_mtrl_005"
+                android:gravity="center"/>
+    </item>
+    <item>
+        <bitmap android:src="@drawable/abc_scrubber_control_to_pressed_mtrl_000"
+                android:gravity="center"/>
+    </item>
+</selector>
\ No newline at end of file
diff --git a/v7/appcompat/res/drawable/abc_seekbar_track_material.xml b/v7/appcompat/res/drawable/abc_seekbar_track_material.xml
new file mode 100644
index 0000000..e68ac03
--- /dev/null
+++ b/v7/appcompat/res/drawable/abc_seekbar_track_material.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@android:id/background"
+          android:drawable="@drawable/abc_scrubber_track_mtrl_alpha"/>
+    <item android:id="@android:id/secondaryProgress">
+        <scale android:scaleWidth="100%">
+            <selector>
+                <item android:state_enabled="false">
+                    <color android:color="@android:color/transparent"/>
+                </item>
+                <item android:drawable="@drawable/abc_scrubber_primary_mtrl_alpha"/>
+            </selector>
+        </scale>
+    </item>
+    <item android:id="@android:id/progress">
+        <scale android:scaleWidth="100%">
+            <selector>
+                <item android:state_enabled="false">
+                    <color android:color="@android:color/transparent"/>
+                </item>
+                <item android:drawable="@drawable/abc_scrubber_primary_mtrl_alpha"/>
+            </selector>
+        </scale>
+    </item>
+</layer-list>
\ No newline at end of file
diff --git a/v7/appcompat/res/layout/abc_alert_dialog_button_bar_material.xml b/v7/appcompat/res/layout/abc_alert_dialog_button_bar_material.xml
new file mode 100644
index 0000000..4405707
--- /dev/null
+++ b/v7/appcompat/res/layout/abc_alert_dialog_button_bar_material.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<android.support.v7.internal.widget.ButtonBarLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/buttonPanel"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layoutDirection="locale"
+    android:orientation="horizontal"
+    android:paddingLeft="12dp"
+    android:paddingRight="12dp"
+    android:paddingTop="4dp"
+    android:paddingBottom="4dp"
+    android:gravity="bottom"
+    app:allowStacking="@bool/abc_allow_stacked_button_bar"
+    style="?attr/buttonBarStyle">
+
+    <Button
+        android:id="@android:id/button3"
+        style="?attr/buttonBarNeutralButtonStyle"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <android.support.v4.widget.Space
+        android:id="@+id/spacer"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:visibility="invisible" />
+
+    <Button
+        android:id="@android:id/button2"
+        style="?attr/buttonBarNegativeButtonStyle"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <Button
+        android:id="@android:id/button1"
+        style="?attr/buttonBarPositiveButtonStyle"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+</android.support.v7.internal.widget.ButtonBarLayout>
diff --git a/v7/appcompat/res/layout/abc_alert_dialog_material.xml b/v7/appcompat/res/layout/abc_alert_dialog_material.xml
index 9ba81fd..01ff885 100644
--- a/v7/appcompat/res/layout/abc_alert_dialog_material.xml
+++ b/v7/appcompat/res/layout/abc_alert_dialog_material.xml
@@ -108,41 +108,6 @@
                 android:layout_height="wrap_content"/>
     </FrameLayout>
 
-    <LinearLayout
-            android:id="@+id/buttonPanel"
-            style="?attr/buttonBarStyle"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layoutDirection="locale"
-            android:orientation="horizontal"
-            android:paddingLeft="12dp"
-            android:paddingRight="12dp"
-            android:paddingTop="8dp"
-            android:paddingBottom="8dp"
-            android:gravity="bottom">
+    <include layout="@layout/abc_alert_dialog_button_bar_material" />
 
-        <Button
-                android:id="@android:id/button3"
-                style="?attr/buttonBarNeutralButtonStyle"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"/>
-
-        <android.support.v4.widget.Space
-                android:layout_width="0dp"
-                android:layout_height="0dp"
-                android:layout_weight="1"
-                android:visibility="invisible"/>
-
-        <Button
-                android:id="@android:id/button2"
-                style="?attr/buttonBarNegativeButtonStyle"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"/>
-
-        <Button
-                android:id="@android:id/button1"
-                style="?attr/buttonBarPositiveButtonStyle"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"/>
-    </LinearLayout>
 </LinearLayout>
\ No newline at end of file
diff --git a/v7/appcompat/res/values-az-rAZ/strings.xml b/v7/appcompat/res/values-az-rAZ/strings.xml
deleted file mode 100644
index a39f5f4..0000000
--- a/v7/appcompat/res/values-az-rAZ/strings.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2012 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="abc_action_mode_done" msgid="4076576682505996667">"Hazırdır"</string>
-    <string name="abc_action_bar_home_description" msgid="4600421777120114993">"Evə get"</string>
-    <string name="abc_action_bar_up_description" msgid="1594238315039666878">"Yuxarı get"</string>
-    <string name="abc_action_menu_overflow_description" msgid="3588849162933574182">"Daha çox seçim"</string>
-    <string name="abc_toolbar_collapse_description" msgid="1603543279005712093">"Dağıt"</string>
-    <string name="abc_action_bar_home_description_format" msgid="1397052879051804371">"%1$s, %2$s"</string>
-    <string name="abc_action_bar_home_subtitle_description_format" msgid="6623331958280229229">"%1$s, %2$s, %3$s"</string>
-    <string name="abc_searchview_description_search" msgid="8264924765203268293">"Axtarış"</string>
-    <string name="abc_search_hint" msgid="7723749260725869598">"Axtarış..."</string>
-    <string name="abc_searchview_description_query" msgid="2550479030709304392">"Axtarış sorğusu"</string>
-    <string name="abc_searchview_description_clear" msgid="3691816814315814921">"Sorğunu təmizlə"</string>
-    <string name="abc_searchview_description_submit" msgid="8928215447528550784">"Sorğunu göndərin"</string>
-    <string name="abc_searchview_description_voice" msgid="893419373245838918">"Səsli axtarış"</string>
-    <string name="abc_activitychooserview_choose_application" msgid="2031811694353399454">"Tətbiq seçin"</string>
-    <string name="abc_activity_chooser_view_see_all" msgid="7468859129482906941">"Hamısına baxın"</string>
-    <!-- String.format failed for translation -->
-    <!-- no translation found for abc_shareactionprovider_share_with_application (7165123711973476752) -->
-    <skip />
-    <string name="abc_shareactionprovider_share_with" msgid="3421042268587513524">"Bununla paylaşın"</string>
-    <string name="status_bar_notification_info_overflow" msgid="2869576371154716097">"999+"</string>
-</resources>
diff --git a/v17/leanback/res/layout/lb_card_color_overlay.xml b/v7/appcompat/res/values-h320dp/bools.xml
similarity index 73%
copy from v17/leanback/res/layout/lb_card_color_overlay.xml
copy to v7/appcompat/res/values-h320dp/bools.xml
index 45a40e1..5576c18 100644
--- a/v17/leanback/res/layout/lb_card_color_overlay.xml
+++ b/v7/appcompat/res/values-h320dp/bools.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 The Android Open Source Project
+<!-- 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.
@@ -15,7 +14,6 @@
      limitations under the License.
 -->
 
-<View
-      xmlns:android="http://schemas.android.com/apk/res/android"
-      android:layout_width="match_parent"
-      android:layout_height="match_parent" />
+<resources>
+    <bool name="abc_allow_stacked_button_bar">true</bool>
+</resources>
diff --git a/v7/appcompat/res/values-kk-rKZ/strings.xml b/v7/appcompat/res/values-kk-rKZ/strings.xml
index 2ce080f..52b9af5 100644
--- a/v7/appcompat/res/values-kk-rKZ/strings.xml
+++ b/v7/appcompat/res/values-kk-rKZ/strings.xml
@@ -16,7 +16,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="abc_action_mode_done" msgid="4076576682505996667">"Дайын"</string>
+    <string name="abc_action_mode_done" msgid="4076576682505996667">"Орындалды"</string>
     <string name="abc_action_bar_home_description" msgid="4600421777120114993">"Негізгі бетте қозғалу"</string>
     <string name="abc_action_bar_up_description" msgid="1594238315039666878">"Жоғары қозғалу"</string>
     <string name="abc_action_menu_overflow_description" msgid="3588849162933574182">"Басқа опциялар"</string>
diff --git a/v7/appcompat/res/values-v21/styles_base.xml b/v7/appcompat/res/values-v21/styles_base.xml
index 47681f2..649f0ca 100644
--- a/v7/appcompat/res/values-v21/styles_base.xml
+++ b/v7/appcompat/res/values-v21/styles_base.xml
@@ -172,6 +172,8 @@
 
     <style name="Base.Widget.AppCompat.RatingBar" parent="android:Widget.Material.RatingBar" />
 
+    <style name="Base.Widget.AppCompat.SeekBar" parent="android:Widget.Material.SeekBar" />
+
     <style name="Base.Widget.AppCompat.Button" parent="android:Widget.Material.Button" />
 
     <style name="Base.Widget.AppCompat.Button.Small" parent="android:Widget.Material.Button.Small" />
diff --git a/v7/appcompat/res/values/attrs.xml b/v7/appcompat/res/values/attrs.xml
index 040bea1..174fcc8 100644
--- a/v7/appcompat/res/values/attrs.xml
+++ b/v7/appcompat/res/values/attrs.xml
@@ -371,6 +371,8 @@
         <attr name="radioButtonStyle" format="reference" />
         <!-- Default RatingBar style. -->
         <attr name="ratingBarStyle" format="reference" />
+        <!-- Default SeekBar style. -->
+        <attr name="seekBarStyle" format="reference" />
         <!-- Default Spinner style. -->
         <attr name="spinnerStyle" format="reference" />
         <!-- Default style for the Switch widget. -->
@@ -943,4 +945,11 @@
         <attr name="listItemLayout" format="reference" />
     </declare-styleable>
 
+    <!-- @hide -->
+    <declare-styleable name="ButtonBarLayout">
+        <!-- Whether to automatically stack the buttons when there is not
+             enough space to lay them out side-by-side. -->
+        <attr name="allowStacking" format="boolean" />
+    </declare-styleable>
+
 </resources>
diff --git a/v7/appcompat/res/values/bools.xml b/v7/appcompat/res/values/bools.xml
index 79a5035..3508cf3 100644
--- a/v7/appcompat/res/values/bools.xml
+++ b/v7/appcompat/res/values/bools.xml
@@ -21,4 +21,8 @@
     <bool name="abc_action_bar_expanded_action_views_exclusive">true</bool>
 
     <bool name="abc_config_showMenuShortcutsWhenKeyboardPresent">false</bool>
+
+    <!-- Whether to allow vertically stacked button bars. This is disabled for
+         configurations with a small (e.g. less than 320dp) screen height. -->
+    <bool name="abc_allow_stacked_button_bar">false</bool>
 </resources>
diff --git a/v7/appcompat/res/values/dimens_material.xml b/v7/appcompat/res/values/dimens_material.xml
index f67127c..357dc3e 100644
--- a/v7/appcompat/res/values/dimens_material.xml
+++ b/v7/appcompat/res/values/dimens_material.xml
@@ -68,4 +68,7 @@
     <item name="abc_disabled_alpha_material_light" format="float" type="dimen">0.26</item>
     <item name="abc_disabled_alpha_material_dark" format="float" type="dimen">0.30</item>
 
+    <dimen name="abc_seekbar_track_background_height_material">2dp</dimen>
+    <dimen name="abc_seekbar_track_progress_height_material">2dp</dimen>
+
 </resources>
diff --git a/v7/appcompat/res/values/styles.xml b/v7/appcompat/res/values/styles.xml
index e10c01f..9453944 100644
--- a/v7/appcompat/res/values/styles.xml
+++ b/v7/appcompat/res/values/styles.xml
@@ -224,6 +224,8 @@
 
     <style name="AlertDialog.AppCompat.Light" parent="Base.AlertDialog.AppCompat.Light" />
 
+    <style name="Widget.AppCompat.SeekBar" parent="Base.Widget.AppCompat.SeekBar" />
+
     <!-- Toolbar -->
 
     <style name="Widget.AppCompat.Toolbar" parent="Base.Widget.AppCompat.Toolbar" />
diff --git a/v7/appcompat/res/values/styles_base.xml b/v7/appcompat/res/values/styles_base.xml
index d65b16f..8df76d8 100644
--- a/v7/appcompat/res/values/styles_base.xml
+++ b/v7/appcompat/res/values/styles_base.xml
@@ -395,6 +395,16 @@
         <item name="android:indeterminateDrawable">@drawable/abc_ratingbar_full_material</item>
     </style>
 
+    <style name="Base.Widget.AppCompat.SeekBar" parent="android:Widget">
+        <item name="android:indeterminateOnly">false</item>
+        <item name="android:progressDrawable">@drawable/abc_seekbar_track_material</item>
+        <item name="android:indeterminateDrawable">@drawable/abc_seekbar_track_material</item>
+        <item name="android:thumb">@drawable/abc_seekbar_thumb_material</item>
+        <item name="android:focusable">true</item>
+        <item name="android:paddingLeft">16dip</item>
+        <item name="android:paddingRight">16dip</item>
+    </style>
+
     <!-- Bordered ink button -->
     <style name="Base.Widget.AppCompat.Button" parent="android:Widget">
         <item name="android:background">@drawable/abc_btn_default_mtrl_shape</item>
diff --git a/v7/appcompat/res/values/themes_base.xml b/v7/appcompat/res/values/themes_base.xml
index d0dfca5..298196f 100644
--- a/v7/appcompat/res/values/themes_base.xml
+++ b/v7/appcompat/res/values/themes_base.xml
@@ -229,6 +229,7 @@
         <item name="switchStyle">@style/Widget.AppCompat.CompoundButton.Switch</item>
 
         <item name="ratingBarStyle">@style/Widget.AppCompat.RatingBar</item>
+        <item name="seekBarStyle">@style/Widget.AppCompat.SeekBar</item>
 
         <!-- Button styles -->
         <item name="buttonStyle">@style/Widget.AppCompat.Button</item>
@@ -379,6 +380,7 @@
         <item name="switchStyle">@style/Widget.AppCompat.CompoundButton.Switch</item>
 
         <item name="ratingBarStyle">@style/Widget.AppCompat.RatingBar</item>
+        <item name="seekBarStyle">@style/Widget.AppCompat.SeekBar</item>
 
         <!-- Button styles -->
         <item name="buttonStyle">@style/Widget.AppCompat.Button</item>
diff --git a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplBase.java b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplBase.java
index 490abb4..31d1eb0 100644
--- a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplBase.java
+++ b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplBase.java
@@ -54,6 +54,8 @@
     boolean mIsFloating;
     // true if this activity has no title
     boolean mWindowNoTitle;
+    // true if the theme has been read
+    boolean mThemeRead;
 
     private CharSequence mTitle;
 
@@ -106,13 +108,11 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         TypedArray a = mContext.obtainStyledAttributes(R.styleable.Theme);
-
         if (!a.hasValue(R.styleable.Theme_windowActionBar)) {
             a.recycle();
             throw new IllegalStateException(
                     "You need to use a Theme.AppCompat theme (or descendant) with this activity.");
         }
-
         if (a.getBoolean(R.styleable.Theme_windowNoTitle, false)) {
             requestWindowFeature(Window.FEATURE_NO_TITLE);
         } else if (a.getBoolean(R.styleable.Theme_windowActionBar, false)) {
@@ -127,6 +127,7 @@
         }
         mIsFloating = a.getBoolean(R.styleable.Theme_android_windowIsFloating, false);
         a.recycle();
+        mThemeRead = true;
     }
 
     // Methods used to create and respond to options menu
diff --git a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV7.java b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV7.java
index 0f306f5..bef6cbf 100644
--- a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV7.java
+++ b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV7.java
@@ -277,6 +277,12 @@
 
     private void ensureSubDecor() {
         if (!mSubDecorInstalled) {
+            if (!mThemeRead) {
+                throw new IllegalStateException("AppCompat can not install it's decor before "
+                        + "reading the theme. This is usually caused by calling setContentView() "
+                        + "before super.onCreate().");
+            }
+
             final LayoutInflater inflater = LayoutInflater.from(mContext);
 
             if (!mWindowNoTitle) {
diff --git a/v7/appcompat/src/android/support/v7/internal/app/AppCompatViewInflater.java b/v7/appcompat/src/android/support/v7/internal/app/AppCompatViewInflater.java
index 621fc51..95cf83a 100644
--- a/v7/appcompat/src/android/support/v7/internal/app/AppCompatViewInflater.java
+++ b/v7/appcompat/src/android/support/v7/internal/app/AppCompatViewInflater.java
@@ -30,6 +30,7 @@
 import android.support.v7.widget.AppCompatMultiAutoCompleteTextView;
 import android.support.v7.widget.AppCompatRadioButton;
 import android.support.v7.widget.AppCompatRatingBar;
+import android.support.v7.widget.AppCompatSeekBar;
 import android.support.v7.widget.AppCompatSpinner;
 import android.support.v7.internal.widget.ViewUtils;
 import android.support.v7.widget.AppCompatTextView;
@@ -101,6 +102,8 @@
                 return new AppCompatButton(context, attrs);
             case "TextView":
                 return new AppCompatTextView(context, attrs);
+            case "SeekBar":
+                return new AppCompatSeekBar(context, attrs);
         }
 
         if (originalContext != context) {
diff --git a/v7/appcompat/src/android/support/v7/internal/widget/ButtonBarLayout.java b/v7/appcompat/src/android/support/v7/internal/widget/ButtonBarLayout.java
new file mode 100644
index 0000000..dd0044b
--- /dev/null
+++ b/v7/appcompat/src/android/support/v7/internal/widget/ButtonBarLayout.java
@@ -0,0 +1,110 @@
+/*
+ * 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.v7.internal.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.support.v7.appcompat.R;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.LinearLayout;
+
+/**
+ * An extension of LinearLayout that automatically switches to vertical
+ * orientation when it can't fit its child views horizontally.
+ *
+ * @hide
+ */
+public class ButtonBarLayout extends LinearLayout {
+
+    /** Whether the current configuration allows stacking. */
+    private boolean mAllowStacking;
+    private int mLastWidthSize = -1;
+
+    public ButtonBarLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        final TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ButtonBarLayout);
+        mAllowStacking = ta.getBoolean(R.styleable.ButtonBarLayout_allowStacking, false);
+        ta.recycle();
+    }
+
+    public void setAllowStacking(boolean allowStacking) {
+        if (mAllowStacking != allowStacking) {
+            mAllowStacking = allowStacking;
+            if (!mAllowStacking && getOrientation() == LinearLayout.VERTICAL) {
+                setStacked(false);
+            }
+            requestLayout();
+        }
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+        if (mAllowStacking) {
+            if (widthSize > mLastWidthSize && isStacked()) {
+                // We're being measured wider this time, try un-stacking.
+                setStacked(false);
+            }
+            mLastWidthSize = widthSize;
+        }
+        boolean needsRemeasure = false;
+        // If we're not stacked, make sure the measure spec is AT_MOST rather
+        // than EXACTLY. This ensures that we'll still get TOO_SMALL so that we
+        // know to stack the buttons.
+        final int initialWidthMeasureSpec;
+        if (!isStacked() && MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) {
+            initialWidthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.AT_MOST);
+            // We'll need to remeasure again to fill excess space.
+            needsRemeasure = true;
+        } else {
+            initialWidthMeasureSpec = widthMeasureSpec;
+        }
+        super.onMeasure(initialWidthMeasureSpec, heightMeasureSpec);
+        if (mAllowStacking && !isStacked()) {
+            final int measuredWidth = getMeasuredWidthAndState();
+            final int measuredWidthState = measuredWidth & MEASURED_STATE_MASK;
+            if (measuredWidthState == MEASURED_STATE_TOO_SMALL) {
+                setStacked(true);
+                // Measure again in the new orientation.
+                needsRemeasure = true;
+            }
+        }
+        if (needsRemeasure) {
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        }
+    }
+
+    private void setStacked(boolean stacked) {
+        setOrientation(stacked ? LinearLayout.VERTICAL : LinearLayout.HORIZONTAL);
+        setGravity(stacked ? Gravity.RIGHT : Gravity.BOTTOM);
+        final View spacer = findViewById(R.id.spacer);
+        if (spacer != null) {
+            spacer.setVisibility(stacked ? View.GONE : View.INVISIBLE);
+        }
+        // Reverse the child order. This is specific to the Material button
+        // bar's layout XML and will probably not generalize.
+        final int childCount = getChildCount();
+        for (int i = childCount - 2; i >= 0; i--) {
+            bringChildToFront(getChildAt(i));
+        }
+    }
+
+    private boolean isStacked() {
+        return getOrientation() == LinearLayout.VERTICAL;
+    }
+}
\ No newline at end of file
diff --git a/v7/appcompat/src/android/support/v7/internal/widget/TintManager.java b/v7/appcompat/src/android/support/v7/internal/widget/TintManager.java
index d926e17..ec85157 100644
--- a/v7/appcompat/src/android/support/v7/internal/widget/TintManager.java
+++ b/v7/appcompat/src/android/support/v7/internal/widget/TintManager.java
@@ -191,10 +191,18 @@
                     DrawableCompat.setTintMode(drawable, tintMode);
                 }
             } else if (resId == R.drawable.abc_cab_background_top_material) {
-                return new LayerDrawable(new Drawable[] {
+                return new LayerDrawable(new Drawable[]{
                         getDrawable(R.drawable.abc_cab_background_internal_bg),
                         getDrawable(R.drawable.abc_cab_background_top_mtrl_alpha)
                 });
+            } else if (resId == R.drawable.abc_seekbar_track_material) {
+                LayerDrawable ld = (LayerDrawable) drawable;
+                setPorterDuffColorFilter(ld.findDrawableByLayerId(android.R.id.background),
+                        getThemeAttrColor(context, R.attr.colorControlNormal), DEFAULT_MODE);
+                setPorterDuffColorFilter(ld.findDrawableByLayerId(android.R.id.secondaryProgress),
+                        getThemeAttrColor(context, R.attr.colorControlNormal), DEFAULT_MODE);
+                setPorterDuffColorFilter(ld.findDrawableByLayerId(android.R.id.progress),
+                        getThemeAttrColor(context, R.attr.colorControlActivated), DEFAULT_MODE);
             } else {
                 final boolean usedColorFilter = tintDrawableUsingColorFilter(resId, drawable);
                 if (!usedColorFilter && failIfNotKnown) {
@@ -307,6 +315,8 @@
                 tint = getDefaultColorStateList(context);
             } else if (arrayContains(TINT_CHECKABLE_BUTTON_LIST, resId)) {
                 tint = createCheckableButtonColorStateList(context);
+            } else if (resId == R.drawable.abc_seekbar_thumb_material) {
+                tint = createSeekbarThumbColorStateList(context);
             }
 
             if (tint != null) {
@@ -541,6 +551,23 @@
         return new ColorStateList(states, colors);
     }
 
+    private ColorStateList createSeekbarThumbColorStateList(Context context) {
+        final int[][] states = new int[2][];
+        final int[] colors = new int[2];
+        int i = 0;
+
+        // Disabled state
+        states[i] = ThemeUtils.DISABLED_STATE_SET;
+        colors[i] = getDisabledThemeAttrColor(context, R.attr.colorControlActivated);
+        i++;
+
+        states[i] = ThemeUtils.EMPTY_STATE_SET;
+        colors[i] = getThemeAttrColor(context, R.attr.colorControlActivated);
+        i++;
+
+        return new ColorStateList(states, colors);
+    }
+
     private static class ColorFilterLruCache extends LruCache<Integer, PorterDuffColorFilter> {
 
         public ColorFilterLruCache(int maxSize) {
@@ -602,4 +629,8 @@
 
         return filter;
     }
+
+    private static void setPorterDuffColorFilter(Drawable d, int color, PorterDuff.Mode mode) {
+        d.setColorFilter(getPorterDuffColorFilter(color, mode == null ? DEFAULT_MODE : mode));
+    }
 }
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatProgressBarHelper.java b/v7/appcompat/src/android/support/v7/widget/AppCompatProgressBarHelper.java
new file mode 100644
index 0000000..7fd8f05
--- /dev/null
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatProgressBarHelper.java
@@ -0,0 +1,151 @@
+/*
+ * 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.v7.widget;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapShader;
+import android.graphics.Shader;
+import android.graphics.drawable.AnimationDrawable;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ClipDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+import android.graphics.drawable.ShapeDrawable;
+import android.graphics.drawable.shapes.RoundRectShape;
+import android.graphics.drawable.shapes.Shape;
+import android.support.v4.graphics.drawable.DrawableWrapper;
+import android.support.v7.appcompat.R;
+import android.support.v7.internal.widget.TintManager;
+import android.support.v7.internal.widget.TintTypedArray;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.widget.CompoundButton;
+import android.widget.ProgressBar;
+
+class AppCompatProgressBarHelper {
+
+    private static final int[] TINT_ATTRS = {
+            android.R.attr.indeterminateDrawable,
+            android.R.attr.progressDrawable
+    };
+
+    private final ProgressBar mView;
+    final TintManager mTintManager;
+
+    private Bitmap mSampleTile;
+
+    AppCompatProgressBarHelper(ProgressBar view, TintManager tintManager) {
+        mView = view;
+        mTintManager = tintManager;
+    }
+
+    void loadFromAttributes(AttributeSet attrs, int defStyleAttr) {
+        TintTypedArray a = TintTypedArray.obtainStyledAttributes(mView.getContext(), attrs,
+                TINT_ATTRS, defStyleAttr, 0);
+
+        Drawable drawable = a.getDrawableIfKnown(0);
+        if (drawable != null) {
+            mView.setIndeterminateDrawable(tileifyIndeterminate(drawable));
+        }
+
+        drawable = a.getDrawableIfKnown(1);
+        if (drawable != null) {
+            mView.setProgressDrawable(tileify(drawable, false));
+        }
+
+        a.recycle();
+    }
+
+    /**
+     * Converts a drawable to a tiled version of itself. It will recursively
+     * traverse layer and state list drawables.
+     */
+    private Drawable tileify(Drawable drawable, boolean clip) {
+        if (drawable instanceof DrawableWrapper) {
+            Drawable inner = ((DrawableWrapper) drawable).getWrappedDrawable();
+            if (inner != null) {
+                inner = tileify(inner, clip);
+                ((DrawableWrapper) drawable).setWrappedDrawable(inner);
+            }
+        } else if (drawable instanceof LayerDrawable) {
+            LayerDrawable background = (LayerDrawable) drawable;
+            final int N = background.getNumberOfLayers();
+            Drawable[] outDrawables = new Drawable[N];
+
+            for (int i = 0; i < N; i++) {
+                int id = background.getId(i);
+                outDrawables[i] = tileify(background.getDrawable(i),
+                        (id == android.R.id.progress || id == android.R.id.secondaryProgress));
+            }
+            LayerDrawable newBg = new LayerDrawable(outDrawables);
+
+            for (int i = 0; i < N; i++) {
+                newBg.setId(i, background.getId(i));
+            }
+
+            return newBg;
+
+        } else if (drawable instanceof BitmapDrawable) {
+            final Bitmap tileBitmap = ((BitmapDrawable) drawable).getBitmap();
+            if (mSampleTile == null) {
+                mSampleTile = tileBitmap;
+            }
+
+            final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape());
+            final BitmapShader bitmapShader = new BitmapShader(tileBitmap,
+                    Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
+            shapeDrawable.getPaint().setShader(bitmapShader);
+            return (clip) ? new ClipDrawable(shapeDrawable, Gravity.LEFT,
+                    ClipDrawable.HORIZONTAL) : shapeDrawable;
+        }
+
+        return drawable;
+    }
+
+    /**
+     * Convert a AnimationDrawable for use as a barberpole animation.
+     * Each frame of the animation is wrapped in a ClipDrawable and
+     * given a tiling BitmapShader.
+     */
+    private Drawable tileifyIndeterminate(Drawable drawable) {
+        if (drawable instanceof AnimationDrawable) {
+            AnimationDrawable background = (AnimationDrawable) drawable;
+            final int N = background.getNumberOfFrames();
+            AnimationDrawable newBg = new AnimationDrawable();
+            newBg.setOneShot(background.isOneShot());
+
+            for (int i = 0; i < N; i++) {
+                Drawable frame = tileify(background.getFrame(i), true);
+                frame.setLevel(10000);
+                newBg.addFrame(frame, background.getDuration(i));
+            }
+            newBg.setLevel(10000);
+            drawable = newBg;
+        }
+        return drawable;
+    }
+
+    private Shape getDrawableShape() {
+        final float[] roundedCorners = new float[] { 5, 5, 5, 5, 5, 5, 5, 5 };
+        return new RoundRectShape(roundedCorners, null, null);
+    }
+
+    Bitmap getSampleTime() {
+        return mSampleTile;
+    }
+
+}
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatRatingBar.java b/v7/appcompat/src/android/support/v7/widget/AppCompatRatingBar.java
index 51811a8..0bc14ab 100644
--- a/v7/appcompat/src/android/support/v7/widget/AppCompatRatingBar.java
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatRatingBar.java
@@ -18,23 +18,10 @@
 
 import android.content.Context;
 import android.graphics.Bitmap;
-import android.graphics.BitmapShader;
-import android.graphics.Shader;
-import android.graphics.drawable.AnimationDrawable;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.ClipDrawable;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LayerDrawable;
-import android.graphics.drawable.ShapeDrawable;
-import android.graphics.drawable.shapes.RoundRectShape;
-import android.graphics.drawable.shapes.Shape;
-import android.support.v4.graphics.drawable.DrawableWrapper;
 import android.support.v4.view.ViewCompat;
 import android.support.v7.appcompat.R;
 import android.support.v7.internal.widget.TintManager;
-import android.support.v7.internal.widget.TintTypedArray;
 import android.util.AttributeSet;
-import android.view.Gravity;
 import android.widget.RatingBar;
 
 /**
@@ -45,12 +32,8 @@
  */
 public class AppCompatRatingBar extends RatingBar {
 
-    private static final int[] TINT_ATTRS = {
-            android.R.attr.indeterminateDrawable,
-            android.R.attr.progressDrawable
-    };
-
-    private Bitmap mSampleTile;
+    private AppCompatProgressBarHelper mAppCompatProgressBarHelper;
+    private TintManager mTintManager;
 
     public AppCompatRatingBar(Context context) {
         this(context, null);
@@ -63,104 +46,19 @@
     public AppCompatRatingBar(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
 
-        if (TintManager.SHOULD_BE_USED) {
-            TintTypedArray a = TintTypedArray.obtainStyledAttributes(getContext(), attrs,
-                    TINT_ATTRS, defStyleAttr, 0);
+        mTintManager = TintManager.get(context);
 
-            Drawable drawable = a.getDrawableIfKnown(0);
-            if (drawable != null) {
-                setIndeterminateDrawable(tileifyIndeterminate(drawable));
-            }
-
-            drawable = a.getDrawableIfKnown(1);
-            if (drawable != null) {
-                setProgressDrawable(tileify(drawable, false));
-            }
-
-            a.recycle();
-        }
-    }
-
-    /**
-     * Converts a drawable to a tiled version of itself. It will recursively
-     * traverse layer and state list drawables.
-     */
-    private Drawable tileify(Drawable drawable, boolean clip) {
-        if (drawable instanceof DrawableWrapper) {
-            Drawable inner = ((DrawableWrapper) drawable).getWrappedDrawable();
-            if (inner != null) {
-                inner = tileify(inner, clip);
-                ((DrawableWrapper) drawable).setWrappedDrawable(inner);
-            }
-        } else if (drawable instanceof LayerDrawable) {
-            LayerDrawable background = (LayerDrawable) drawable;
-            final int N = background.getNumberOfLayers();
-            Drawable[] outDrawables = new Drawable[N];
-
-            for (int i = 0; i < N; i++) {
-                int id = background.getId(i);
-                outDrawables[i] = tileify(background.getDrawable(i),
-                        (id == android.R.id.progress || id == android.R.id.secondaryProgress));
-            }
-            LayerDrawable newBg = new LayerDrawable(outDrawables);
-
-            for (int i = 0; i < N; i++) {
-                newBg.setId(i, background.getId(i));
-            }
-
-            return newBg;
-
-        } else if (drawable instanceof BitmapDrawable) {
-            final Bitmap tileBitmap = ((BitmapDrawable) drawable).getBitmap();
-            if (mSampleTile == null) {
-                mSampleTile = tileBitmap;
-            }
-
-            final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape());
-            final BitmapShader bitmapShader = new BitmapShader(tileBitmap,
-                    Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
-            shapeDrawable.getPaint().setShader(bitmapShader);
-            return (clip) ? new ClipDrawable(shapeDrawable, Gravity.LEFT,
-                    ClipDrawable.HORIZONTAL) : shapeDrawable;
-        }
-
-        return drawable;
-    }
-
-    /**
-     * Convert a AnimationDrawable for use as a barberpole animation.
-     * Each frame of the animation is wrapped in a ClipDrawable and
-     * given a tiling BitmapShader.
-     */
-    private Drawable tileifyIndeterminate(Drawable drawable) {
-        if (drawable instanceof AnimationDrawable) {
-            AnimationDrawable background = (AnimationDrawable) drawable;
-            final int N = background.getNumberOfFrames();
-            AnimationDrawable newBg = new AnimationDrawable();
-            newBg.setOneShot(background.isOneShot());
-
-            for (int i = 0; i < N; i++) {
-                Drawable frame = tileify(background.getFrame(i), true);
-                frame.setLevel(10000);
-                newBg.addFrame(frame, background.getDuration(i));
-            }
-            newBg.setLevel(10000);
-            drawable = newBg;
-        }
-        return drawable;
-    }
-
-    private Shape getDrawableShape() {
-        final float[] roundedCorners = new float[] { 5, 5, 5, 5, 5, 5, 5, 5 };
-        return new RoundRectShape(roundedCorners, null, null);
+        mAppCompatProgressBarHelper = new AppCompatProgressBarHelper(this, mTintManager);
+        mAppCompatProgressBarHelper.loadFromAttributes(attrs, defStyleAttr);
     }
 
     @Override
     protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 
-        if (mSampleTile != null) {
-            final int width = mSampleTile.getWidth() * getNumStars();
+        Bitmap sampleTile = mAppCompatProgressBarHelper.getSampleTime();
+        if (sampleTile != null) {
+            final int width = sampleTile.getWidth() * getNumStars();
             setMeasuredDimension(ViewCompat.resolveSizeAndState(width, widthMeasureSpec, 0),
                     getMeasuredHeight());
         }
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatSeekBar.java b/v7/appcompat/src/android/support/v7/widget/AppCompatSeekBar.java
new file mode 100644
index 0000000..86ec881
--- /dev/null
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatSeekBar.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v7.widget;
+
+import android.content.Context;
+import android.support.v7.appcompat.R;
+import android.support.v7.internal.widget.TintManager;
+import android.util.AttributeSet;
+import android.widget.SeekBar;
+
+/**
+ * A {@link SeekBar} which supports compatible features on older version of the platform.
+ *
+ * <p>This will automatically be used when you use {@link SeekBar} in your layouts.
+ * You should only need to manually use this class when writing custom views.</p>
+ */
+public class AppCompatSeekBar extends SeekBar {
+
+    private AppCompatSeekBarHelper mAppCompatSeekBarHelper;
+    private TintManager mTintManager;
+
+    public AppCompatSeekBar(Context context) {
+        this(context, null);
+    }
+
+    public AppCompatSeekBar(Context context, AttributeSet attrs) {
+        this(context, attrs, R.attr.seekBarStyle);
+    }
+
+    public AppCompatSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+
+        mTintManager = TintManager.get(context);
+
+        mAppCompatSeekBarHelper = new AppCompatSeekBarHelper(this, mTintManager);
+        mAppCompatSeekBarHelper.loadFromAttributes(attrs, defStyleAttr);
+    }
+
+}
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatSeekBarHelper.java b/v7/appcompat/src/android/support/v7/widget/AppCompatSeekBarHelper.java
new file mode 100644
index 0000000..3211942
--- /dev/null
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatSeekBarHelper.java
@@ -0,0 +1,49 @@
+/*
+ * 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.v7.widget;
+
+import android.graphics.drawable.Drawable;
+import android.support.v7.internal.widget.TintManager;
+import android.support.v7.internal.widget.TintTypedArray;
+import android.util.AttributeSet;
+import android.widget.SeekBar;
+
+class AppCompatSeekBarHelper extends AppCompatProgressBarHelper {
+
+    private static final int[] TINT_ATTRS = {
+            android.R.attr.thumb
+    };
+
+    private final SeekBar mView;
+
+    AppCompatSeekBarHelper(SeekBar view, TintManager tintManager) {
+        super(view, tintManager);
+        mView = view;
+    }
+
+    void loadFromAttributes(AttributeSet attrs, int defStyleAttr) {
+        super.loadFromAttributes(attrs, defStyleAttr);
+
+        TintTypedArray a = TintTypedArray.obtainStyledAttributes(mView.getContext(), attrs,
+                TINT_ATTRS, defStyleAttr, 0);
+        Drawable drawable = a.getDrawableIfKnown(0);
+        if (drawable != null) {
+            mView.setThumb(drawable);
+        }
+        a.recycle();
+    }
+}
diff --git a/v7/mediarouter/res/values-az-rAZ/strings.xml b/v7/mediarouter/res/values-az-rAZ/strings.xml
deleted file mode 100644
index 2f3ff74..0000000
--- a/v7/mediarouter/res/values-az-rAZ/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2013 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="5441529851481176817">"Sistem"</string>
-    <string name="mr_user_route_category_name" msgid="7498112907524977311">"Cihazlar"</string>
-    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"İştirakçılar"</string>
-    <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Cihaza qoş"</string>
-    <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Cihazları axtarır..."</string>
-    <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Bağlantını kəs"</string>
-    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Yayımı dayandır"</string>
-    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Marşrut parametrləri"</string>
-    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Göstər"</string>
-    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Fasilə ver"</string>
-</resources>
diff --git a/v7/preference/res/layout/preference_category.xml b/v7/preference/res/layout/preference_category.xml
index 0b58063..258f7da 100644
--- a/v7/preference/res/layout/preference_category.xml
+++ b/v7/preference/res/layout/preference_category.xml
@@ -20,6 +20,6 @@
     android:layout_height="wrap_content" >
     <TextView
      style="?android:attr/listSeparatorTextViewStyle"
-     android:id="@+android:id/title"
+     android:id="@android:id/title"
     />
 </FrameLayout>
diff --git a/v7/preference/res/layout/preference_information.xml b/v7/preference/res/layout/preference_information.xml
index e3be3820..5815c46 100644
--- a/v7/preference/res/layout/preference_information.xml
+++ b/v7/preference/res/layout/preference_information.xml
@@ -33,14 +33,14 @@
         android:layout_marginBottom="6sp"
         android:layout_weight="1">
 
-        <TextView android:id="@+android:id/title"
+        <TextView android:id="@android:id/title"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:singleLine="true"
             android:textAppearance="?android:attr/textAppearanceLarge"
             android:textColor="?android:attr/textColorSecondary" />
 
-        <TextView android:id="@+android:id/summary"
+        <TextView android:id="@android:id/summary"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_below="@android:id/title"
@@ -52,7 +52,7 @@
     </RelativeLayout>
 
     <!-- Preference should place its actual preference widget here. -->
-    <LinearLayout android:id="@+android:id/widget_frame"
+    <LinearLayout android:id="@android:id/widget_frame"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
         android:gravity="center_vertical"