Merge "Fix build for VDC" into mnc-ub-dev
diff --git a/design/api/current.txt b/design/api/current.txt
index d354ec0..39518ba 100644
--- a/design/api/current.txt
+++ b/design/api/current.txt
@@ -89,8 +89,8 @@
 
   public static abstract class BottomSheetBehavior.BottomSheetCallback {
     ctor public BottomSheetBehavior.BottomSheetCallback();
-    method public abstract void onSlide(float);
-    method public abstract void onStateChanged(int);
+    method public abstract void onSlide(android.view.View, float);
+    method public abstract void onStateChanged(android.view.View, int);
   }
 
   protected static class BottomSheetBehavior.SavedState extends android.view.View.BaseSavedState {
diff --git a/design/src/android/support/design/widget/BottomSheetBehavior.java b/design/src/android/support/design/widget/BottomSheetBehavior.java
index bb9fe79..aa39ddd 100644
--- a/design/src/android/support/design/widget/BottomSheetBehavior.java
+++ b/design/src/android/support/design/widget/BottomSheetBehavior.java
@@ -22,6 +22,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.support.annotation.IntDef;
+import android.support.annotation.NonNull;
 import android.support.design.R;
 import android.support.v4.view.MotionEventCompat;
 import android.support.v4.view.NestedScrollingChild;
@@ -52,19 +53,21 @@
         /**
          * Called when the bottom sheet changes its state.
          *
-         * @param newState The new state. This will be one of {@link #STATE_DRAGGING},
-         *                 {@link #STATE_SETTLING}, {@link #STATE_EXPANDED},
-         *                 {@link #STATE_COLLAPSED}, or {@link #STATE_HIDDEN}.
+         * @param bottomSheet The bottom sheet view.
+         * @param newState    The new state. This will be one of {@link #STATE_DRAGGING},
+         *                    {@link #STATE_SETTLING}, {@link #STATE_EXPANDED},
+         *                    {@link #STATE_COLLAPSED}, or {@link #STATE_HIDDEN}.
          */
-        public abstract void onStateChanged(@State int newState);
+        public abstract void onStateChanged(@NonNull View bottomSheet, @State int newState);
 
         /**
          * Called when the bottom sheet is being dragged.
          *
+         * @param bottomSheet The bottom sheet view.
          * @param slideOffset The new offset of this bottom sheet within its range, from 0 to 1
          *                    when it is moving upward, and from 0 to -1 when it moving downward.
          */
-        public abstract void onSlide(float slideOffset);
+        public abstract void onSlide(@NonNull View bottomSheet, float slideOffset);
     }
 
     /**
@@ -322,8 +325,9 @@
             return;
         }
         mState = state;
-        if (mCallback != null) {
-            mCallback.onStateChanged(state);
+        View bottomSheet = mViewRef.get();
+        if (bottomSheet != null && mCallback != null) {
+            mCallback.onStateChanged(bottomSheet, state);
         }
     }
 
@@ -434,11 +438,13 @@
     };
 
     private void dispatchOnSlide(int top) {
-        if (mCallback != null) {
+        View bottomSheet = mViewRef.get();
+        if (bottomSheet != null && mCallback != null) {
             if (top > mMaxOffset) {
-                mCallback.onSlide((float) (mMaxOffset - top) / mPeekHeight);
+                mCallback.onSlide(bottomSheet, (float) (mMaxOffset - top) / mPeekHeight);
             } else {
-                mCallback.onSlide((float) (mMaxOffset - top) / ((mMaxOffset - mMinOffset)));
+                mCallback.onSlide(bottomSheet,
+                        (float) (mMaxOffset - top) / ((mMaxOffset - mMinOffset)));
             }
         }
     }
diff --git a/design/src/android/support/design/widget/BottomSheetDialog.java b/design/src/android/support/design/widget/BottomSheetDialog.java
index 3399de0..52c4004 100644
--- a/design/src/android/support/design/widget/BottomSheetDialog.java
+++ b/design/src/android/support/design/widget/BottomSheetDialog.java
@@ -135,14 +135,15 @@
     private BottomSheetBehavior.BottomSheetCallback mBottomSheetCallback
             = new BottomSheetBehavior.BottomSheetCallback() {
         @Override
-        public void onStateChanged(@BottomSheetBehavior.State int newState) {
+        public void onStateChanged(@NonNull View bottomSheet,
+                @BottomSheetBehavior.State int newState) {
             if (newState == BottomSheetBehavior.STATE_HIDDEN) {
                 dismiss();
             }
         }
 
         @Override
-        public void onSlide(float slideOffset) {
+        public void onSlide(@NonNull View bottomSheet, float slideOffset) {
         }
     };
 
diff --git a/design/tests/src/android/support/design/widget/BottomSheetBehaviorTest.java b/design/tests/src/android/support/design/widget/BottomSheetBehaviorTest.java
index 7659c7c..65da332 100644
--- a/design/tests/src/android/support/design/widget/BottomSheetBehaviorTest.java
+++ b/design/tests/src/android/support/design/widget/BottomSheetBehaviorTest.java
@@ -19,6 +19,7 @@
 import org.hamcrest.Matcher;
 import org.junit.Test;
 
+import android.support.annotation.NonNull;
 import android.support.design.test.R;
 import android.support.test.espresso.Espresso;
 import android.support.test.espresso.IdlingResource;
@@ -55,7 +56,8 @@
         }
 
         @Override
-        public void onStateChanged(@BottomSheetBehavior.State int newState) {
+        public void onStateChanged(@NonNull View bottomSheet,
+                @BottomSheetBehavior.State int newState) {
             boolean wasIdle = mIsIdle;
             mIsIdle = isIdleState(newState);
             if (!wasIdle && mIsIdle && mResourceCallback != null) {
@@ -64,7 +66,7 @@
         }
 
         @Override
-        public void onSlide(float slideOffset) {
+        public void onSlide(@NonNull View bottomSheet, float slideOffset) {
         }
 
         @Override
diff --git a/v17/leanback/api/current.txt b/v17/leanback/api/current.txt
index 0df488f..d90f9f6 100644
--- a/v17/leanback/api/current.txt
+++ b/v17/leanback/api/current.txt
@@ -1030,9 +1030,12 @@
     method public android.content.Intent getIntent();
     method public java.util.List<android.support.v17.leanback.widget.GuidedAction> getSubActions();
     method public java.lang.CharSequence getTitle();
+    method public boolean hasAnyEditable();
+    method public boolean hasEditableActivatorView();
     method public boolean hasMultilineDescription();
     method public boolean hasNext();
     method public boolean hasSubActions();
+    method public boolean hasTextEditable();
     method public boolean infoOnly();
     method public boolean isChecked();
     method public boolean isDescriptionEditable();
@@ -1071,36 +1074,36 @@
   public static abstract class GuidedAction.BuilderBase {
     ctor public GuidedAction.BuilderBase(android.content.Context);
     method protected final void applyValues(android.support.v17.leanback.widget.GuidedAction);
-    method public abstract T build();
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> checkSetId(int);
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> checked(boolean);
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> clickAction(long);
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> description(java.lang.CharSequence);
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> description(int);
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> descriptionEditInputType(int);
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> descriptionEditable(boolean);
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> descriptionInputType(int);
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> editDescription(java.lang.CharSequence);
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> editDescription(int);
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> editInputType(int);
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> editTitle(java.lang.CharSequence);
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> editTitle(int);
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> editable(boolean);
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> enabled(boolean);
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> focusable(boolean);
+    method public B checkSetId(int);
+    method public B checked(boolean);
+    method public B clickAction(long);
+    method public B description(java.lang.CharSequence);
+    method public B description(int);
+    method public B descriptionEditInputType(int);
+    method public B descriptionEditable(boolean);
+    method public B descriptionInputType(int);
+    method public B editDescription(java.lang.CharSequence);
+    method public B editDescription(int);
+    method public B editInputType(int);
+    method public B editTitle(java.lang.CharSequence);
+    method public B editTitle(int);
+    method public B editable(boolean);
+    method public B enabled(boolean);
+    method public B focusable(boolean);
     method public android.content.Context getContext();
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> hasNext(boolean);
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> icon(android.graphics.drawable.Drawable);
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> icon(int);
-    method public deprecated android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> iconResourceId(int, android.content.Context);
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> id(long);
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> infoOnly(boolean);
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> inputType(int);
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> intent(android.content.Intent);
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> multilineDescription(boolean);
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> subActions(java.util.List<android.support.v17.leanback.widget.GuidedAction>);
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> title(java.lang.CharSequence);
-    method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> title(int);
+    method public B hasEditableActivatorView(boolean);
+    method public B hasNext(boolean);
+    method public B icon(android.graphics.drawable.Drawable);
+    method public B icon(int);
+    method public deprecated B iconResourceId(int, android.content.Context);
+    method public B id(long);
+    method public B infoOnly(boolean);
+    method public B inputType(int);
+    method public B intent(android.content.Intent);
+    method public B multilineDescription(boolean);
+    method public B subActions(java.util.List<android.support.v17.leanback.widget.GuidedAction>);
+    method public B title(java.lang.CharSequence);
+    method public B title(int);
   }
 
   public class GuidedActionEditText extends android.widget.EditText implements android.support.v17.leanback.widget.ImeKeyMonitor {
@@ -1124,6 +1127,7 @@
     method public void onAnimateItemFocused(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, boolean);
     method public void onAnimateItemPressed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, boolean);
     method public void onAnimateItemPressedCancelled(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder);
+    method public void onBindActivatorView(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction);
     method public void onBindCheckMarkView(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction);
     method public void onBindChevronView(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction);
     method public void onBindViewHolder(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction);
@@ -1137,12 +1141,14 @@
     method public int onProvideItemLayoutId();
     method public int onProvideItemLayoutId(int);
     method public int onProvideLayoutId();
+    method public boolean onUpdateActivatorView(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction);
     method public void onUpdateExpandedViewHolder(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder);
     method public void setAsButtonActions();
     method public void setEditingMode(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction, boolean);
     method public void setExpandedViewHolder(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder);
     method protected void setupImeOptions(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction);
     method public void startExpandedTransition(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder);
+    field public static final int VIEW_TYPE_DATE_PICKER = 1; // 0x1
     field public static final int VIEW_TYPE_DEFAULT = 0; // 0x0
   }
 
@@ -1160,10 +1166,32 @@
     method public android.widget.ImageView getIconView();
     method public android.widget.TextView getTitleView();
     method public boolean isInEditing();
+    method public boolean isInEditingActivatorView();
     method public boolean isInEditingDescription();
+    method public boolean isInEditingText();
+    method public boolean isInEditingTitle();
     method public boolean isSubAction();
   }
 
+  public class GuidedDatePickerAction extends android.support.v17.leanback.widget.GuidedAction {
+    ctor public GuidedDatePickerAction();
+    method public long getDate();
+    method public java.lang.String getDatePickerFormat();
+    method public void setDate(long);
+  }
+
+  public static final class GuidedDatePickerAction.Builder extends android.support.v17.leanback.widget.GuidedDatePickerAction.BuilderBase {
+    ctor public GuidedDatePickerAction.Builder(android.content.Context);
+    method public android.support.v17.leanback.widget.GuidedDatePickerAction build();
+  }
+
+  public static abstract class GuidedDatePickerAction.BuilderBase extends android.support.v17.leanback.widget.GuidedAction.BuilderBase {
+    ctor public GuidedDatePickerAction.BuilderBase(android.content.Context);
+    method protected final void applyDatePickerValues(android.support.v17.leanback.widget.GuidedDatePickerAction);
+    method public B date(long);
+    method public B datePickerFormat(java.lang.String);
+  }
+
   public class HeaderItem {
     ctor public HeaderItem(long, java.lang.String);
     ctor public HeaderItem(java.lang.String);
@@ -1945,67 +1973,47 @@
 
 package android.support.v17.leanback.widget.picker {
 
-  public class DatePicker extends android.support.v17.leanback.widget.picker.Picker {
-    ctor public DatePicker(android.content.Context, android.util.AttributeSet, int);
-    method public java.lang.String getDatePickerFormat();
-    method public java.util.Calendar getMaxDate();
-    method public java.util.Calendar getMinDate();
-    method public void setDatePickerFormat(java.lang.String);
-    method public void setMaxDate(long);
-    method public void setMinDate(long);
-    method public void updateDate(int, int, int, boolean);
-  }
-
   public class Picker extends android.widget.FrameLayout {
     ctor public Picker(android.content.Context, android.util.AttributeSet, int);
-    method public void addPickerValueListener(android.support.v17.leanback.widget.picker.Picker.PickerValueListener);
-    method public int getActiveColumn();
+    method public void addOnValueChangedListener(android.support.v17.leanback.widget.picker.Picker.PickerValueListener);
+    method public float getActivatedVisibleItemCount();
     method public android.support.v17.leanback.widget.picker.PickerColumn getColumnAt(int);
     method public int getColumnsCount();
-    method protected int getPickerId();
     method protected int getPickerItemHeightPixels();
-    method protected int getPickerItemLayoutId();
-    method protected int getPickerItemTextViewId();
-    method protected int getPickerSeparatorLayoutId();
-    method protected int getRootLayoutId();
-    method protected java.lang.String getSeparator();
-    method public float getVisiblePickerItems();
-    method public float getVisiblePickerItemsInExpand();
-    method public boolean isExpanded();
-    method public boolean isToggleExpandOnClick();
-    method public void onColumnValueChange(int, int);
-    method public void removePickerValueListener(android.support.v17.leanback.widget.picker.Picker.PickerValueListener);
-    method public void setActiveColumn(int);
-    method public void setColumns(java.util.ArrayList<android.support.v17.leanback.widget.picker.PickerColumn>);
-    method public void setExpanded(boolean);
-    method public void setToggleExpandOnClick(boolean);
-    method public void setVisiblePickerItems(float);
-    method public void setVisiblePickerItemsInExpand(float);
-    method public void updateAdapter(int);
-    method public void updateValue(int, int, boolean);
+    method public final int getPickerItemLayoutId();
+    method public final int getPickerItemTextViewId();
+    method public int getSelectedColumn();
+    method public final java.lang.CharSequence getSeparator();
+    method public float getVisibleItemCount();
+    method public void onColumnValueChanged(int, int);
+    method public void removeOnValueChangedListener(android.support.v17.leanback.widget.picker.Picker.PickerValueListener);
+    method public void setActivatedVisibleItemCount(float);
+    method public void setColumnAt(int, android.support.v17.leanback.widget.picker.PickerColumn);
+    method public void setColumnValue(int, int, boolean);
+    method public void setColumns(java.util.List<android.support.v17.leanback.widget.picker.PickerColumn>);
+    method public final void setPickerItemTextViewId(int);
+    method public void setSelectedColumn(int);
+    method public final void setSeparator(java.lang.CharSequence);
+    method public void setVisibleItemCount(float);
   }
 
   public static abstract interface Picker.PickerValueListener {
     method public abstract void onValueChanged(android.support.v17.leanback.widget.picker.Picker, int);
   }
 
-  public class PickerColumn implements android.os.Parcelable {
+  public class PickerColumn {
     ctor public PickerColumn();
-    ctor public PickerColumn(android.os.Parcel);
-    method public int describeContents();
     method public int getCurrentValue();
-    method public int getItemsCount();
+    method public java.lang.CharSequence getEntryAt(int);
+    method public java.lang.String getEntryFormat();
+    method public int getItemCount();
     method public int getMaxValue();
     method public int getMinValue();
-    method public java.lang.String getValueLabelAt(int);
-    method public java.lang.String getValueLabelFormat();
-    method public boolean setCurrentValue(int);
-    method public boolean setMaxValue(int);
-    method public boolean setMinValue(int);
-    method public void setValueLabelFormat(java.lang.String);
-    method public void setValueStaticLabels(java.lang.String[]);
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static android.os.Parcelable.Creator<android.support.v17.leanback.widget.picker.PickerColumn> CREATOR;
+    method public void setCurrentValue(int);
+    method public void setEntries(java.lang.CharSequence[]);
+    method public void setEntryFormat(java.lang.String);
+    method public void setMaxValue(int);
+    method public void setMinValue(int);
   }
 
 }
diff --git a/v17/leanback/res/layout/lb_guidance.xml b/v17/leanback/res/layout/lb_guidance.xml
index 28c0220..59f8ac5 100644
--- a/v17/leanback/res/layout/lb_guidance.xml
+++ b/v17/leanback/res/layout/lb_guidance.xml
@@ -20,6 +20,7 @@
     android:layout_height="match_parent" >
 
     <RelativeLayout
+        android:id="@+id/guidance_container"
         style="?attr/guidanceContainerStyle" >
 
         <ImageView
diff --git a/v17/leanback/res/layout/lb_guidedactions_datepicker_item.xml b/v17/leanback/res/layout/lb_guidedactions_datepicker_item.xml
new file mode 100644
index 0000000..98278d9
--- /dev/null
+++ b/v17/leanback/res/layout/lb_guidedactions_datepicker_item.xml
@@ -0,0 +1,39 @@
+<?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.
+-->
+<!-- Layout for an action item displayed in the 2 pane actions fragment. -->
+<android.support.v17.leanback.widget.NonOverlappingLinearLayoutWithForeground
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    style="?attr/guidedActionItemContainerStyle" >
+
+    <ImageView
+        android:id="@+id/guidedactions_item_icon"
+        style="?attr/guidedActionItemIconStyle"
+        tools:ignore="ContentDescription" />
+
+    <TextView
+        android:id="@+id/guidedactions_item_title"
+        android:layout_width="wrap_content"
+        android:layout_gravity="center_vertical"
+        style="?attr/guidedActionItemTitleStyle" />
+
+    <android.support.v17.leanback.widget.picker.DatePicker
+        android:id="@+id/guidedactions_activator_item"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+</android.support.v17.leanback.widget.NonOverlappingLinearLayoutWithForeground>
diff --git a/v17/leanback/res/values/styles.xml b/v17/leanback/res/values/styles.xml
index 1f7f3dd..6d7c74b 100644
--- a/v17/leanback/res/values/styles.xml
+++ b/v17/leanback/res/values/styles.xml
@@ -384,6 +384,7 @@
 
     <!-- Style for the title view in a GuidanceStylist's default layout. -->
     <style name="Widget.Leanback.GuidanceTitleStyle">
+        <item name="android:importantForAccessibility">no</item>
         <item name="android:layout_toStartOf">@id/guidance_icon</item>
         <item name="android:layout_width">wrap_content</item>
         <item name="android:layout_height">wrap_content</item>
@@ -402,6 +403,7 @@
 
     <!-- Style for the description view in a GuidanceStylist's default layout. -->
     <style name="Widget.Leanback.GuidanceDescriptionStyle">
+        <item name="android:importantForAccessibility">no</item>
         <item name="android:layout_below">@id/guidance_title</item>
         <item name="android:layout_toStartOf">@id/guidance_icon</item>
         <item name="android:layout_width">wrap_content</item>
@@ -419,6 +421,7 @@
 
     <!-- Style for the breadcrumb view in a GuidanceStylist's default layout. -->
     <style name="Widget.Leanback.GuidanceBreadcrumbStyle">
+        <item name="android:importantForAccessibility">no</item>
         <item name="android:layout_above">@id/guidance_title</item>
         <item name="android:layout_toStartOf">@id/guidance_icon</item>
         <item name="android:layout_width">wrap_content</item>
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 604fcc1..8042242 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/GuidedStepFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/GuidedStepFragment.java
@@ -1031,6 +1031,7 @@
         mAdapterGroup.addAdpter(mAdapter, mButtonAdapter);
         mAdapterGroup.addAdpter(mSubAdapter, null);
         mAdapterGroup.setEditListener(editListener);
+        mActionsStylist.setEditListener(editListener);
 
         mActionsStylist.getActionsGridView().setAdapter(mAdapter);
         if (mActionsStylist.getSubActionsGridView() != null) {
diff --git a/v17/leanback/src/android/support/v17/leanback/app/GuidedStepSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/GuidedStepSupportFragment.java
index b4110e9..b76c990 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/GuidedStepSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/GuidedStepSupportFragment.java
@@ -1033,6 +1033,7 @@
         mAdapterGroup.addAdpter(mAdapter, mButtonAdapter);
         mAdapterGroup.addAdpter(mSubAdapter, null);
         mAdapterGroup.setEditListener(editListener);
+        mActionsStylist.setEditListener(editListener);
 
         mActionsStylist.getActionsGridView().setAdapter(mAdapter);
         if (mActionsStylist.getSubActionsGridView() != null) {
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 3fcdbba..7284a53 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GuidanceStylist.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GuidanceStylist.java
@@ -20,6 +20,7 @@
 import android.graphics.drawable.Drawable;
 import android.support.annotation.NonNull;
 import android.support.v17.leanback.R;
+import android.text.TextUtils;
 import android.util.TypedValue;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -154,6 +155,7 @@
         mBreadcrumbView = (TextView) guidanceView.findViewById(R.id.guidance_breadcrumb);
         mDescriptionView = (TextView) guidanceView.findViewById(R.id.guidance_description);
         mIconView = (ImageView) guidanceView.findViewById(R.id.guidance_icon);
+        View guidanceContainer = guidanceView.findViewById(R.id.guidance_container);
 
         // We allow any of the cached subviews to be null, so that subclasses can choose not to
         // display a particular piece of information.
@@ -169,6 +171,16 @@
         if (mIconView != null) {
             mIconView.setImageDrawable(guidance.getIconDrawable());
         }
+        if (guidanceContainer != null) {
+            CharSequence contentDescription = guidanceContainer.getContentDescription();
+            if (TextUtils.isEmpty(contentDescription)) {
+                guidanceContainer.setContentDescription(new StringBuilder()
+                        .append(guidance.getBreadcrumb()).append('\n')
+                        .append(guidance.getTitle()).append('\n')
+                        .append(guidance.getDescription())
+                        .toString());
+            }
+        }
         return guidanceView;
     }
 
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 c5bf7a5..977c201 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GuidedAction.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GuidedAction.java
@@ -38,7 +38,7 @@
  * user input on selection, in which case they will be displayed with a chevron indicator.
  * <p>
  * GuidedAction recommends to use {@link Builder}. When application subclass GuidedAction, it
- * can subclass {@link BuilderBase}, implement {@link BuilderBase#build()} where it should
+ * can subclass {@link BuilderBase}, implement its own builder() method where it should
  * call {@link BuilderBase#applyValues(GuidedAction)}.
  */
 public class GuidedAction extends Action {
@@ -97,12 +97,17 @@
      */
     public static final long ACTION_ID_NO = -9;
 
+    static final int EDITING_NONE = 0;
+    static final int EDITING_TITLE = 1;
+    static final int EDITING_DESCRIPTION = 2;
+    static final int EDITING_ACTIVATOR_VIEW = 3;
+
     /**
      * Base builder class to build a {@link GuidedAction} object.  When subclass GuidedAction, you
-     * can override this BuilderBase class, implements {@link #build()} and call
+     * can override this BuilderBase class, implements your build() method which should call
      * {@link #applyValues(GuidedAction)}.  When using GuidedAction directly, use {@link Builder}.
      */
-    public abstract static class BuilderBase<T extends GuidedAction> {
+    public abstract static class BuilderBase<B extends BuilderBase> {
         private Context mContext;
         private long mId;
         private CharSequence mTitle;
@@ -114,8 +119,7 @@
         private boolean mMultilineDescription;
         private boolean mHasNext;
         private boolean mInfoOnly;
-        private boolean mEditable = false;
-        private boolean mDescriptionEditable = false;
+        private int mEditable = EDITING_NONE;
         private int mInputType = InputType.TYPE_CLASS_TEXT;
         private int mDescriptionInputType = InputType.TYPE_CLASS_TEXT;
         private int mEditInputType = InputType.TYPE_CLASS_TEXT;
@@ -143,12 +147,6 @@
         }
 
         /**
-         * Builds the GuidedAction corresponding to this Builder.
-         * @return the GuidedAction as configured through this BuilderBase.
-         */
-        public abstract T build();
-
-        /**
          * Subclass of BuilderBase should call this function to apply values.
          * @param action GuidedAction to apply BuilderBase values.
          */
@@ -164,7 +162,6 @@
             // Subclass values
             action.mIntent = mIntent;
             action.mEditable = mEditable;
-            action.mDescriptionEditable = mDescriptionEditable;
             action.mInputType = mInputType;
             action.mDescriptionInputType = mDescriptionInputType;
             action.mEditInputType = mEditInputType;
@@ -187,7 +184,7 @@
          * {@link GuidedAction#ACTION_ID_YES} {@link GuidedAction#ACTION_ID_NO}.
          * @return The same BuilderBase object.
          */
-        public BuilderBase<T> clickAction(long id) {
+        public B clickAction(long id) {
             if (id == ACTION_ID_OK) {
                 mId = ACTION_ID_OK;
                 mTitle = mContext.getString(android.R.string.ok);
@@ -207,7 +204,7 @@
                 mId = ACTION_ID_NO;
                 mTitle = mContext.getString(android.R.string.no);
             }
-            return this;
+            return (B) this;
         }
 
         /**
@@ -215,9 +212,9 @@
          * it is typically used to determine what to do when an action is clicked.
          * @param id The ID to associate with this action.
          */
-        public BuilderBase<T> id(long id) {
+        public B id(long id) {
             mId = id;
-            return this;
+            return (B) this;
         }
 
         /**
@@ -225,9 +222,9 @@
          * action to be taken on click, e.g. "Continue" or "Cancel".
          * @param title The title for this action.
          */
-        public BuilderBase<T> title(CharSequence title) {
+        public B title(CharSequence title) {
             mTitle = title;
-            return this;
+            return (B) this;
         }
 
         /**
@@ -235,9 +232,9 @@
          * action to be taken on click, e.g. "Continue" or "Cancel".
          * @param titleResourceId The resource id of title for this action.
          */
-        public BuilderBase<T> title(@StringRes int titleResourceId) {
+        public B title(@StringRes int titleResourceId) {
             mTitle = getContext().getString(titleResourceId);
-            return this;
+            return (B) this;
         }
 
         /**
@@ -245,9 +242,9 @@
          * replaces the string of title.
          * @param editTitle The optional title text to edit when TextView is activated.
          */
-        public BuilderBase<T> editTitle(CharSequence editTitle) {
+        public B editTitle(CharSequence editTitle) {
             mEditTitle = editTitle;
-            return this;
+            return (B) this;
         }
 
         /**
@@ -256,9 +253,9 @@
          * @param editTitleResourceId String resource id of the optional title text to edit when
          * TextView is activated.
          */
-        public BuilderBase<T> editTitle(@StringRes int editTitleResourceId) {
+        public B editTitle(@StringRes int editTitleResourceId) {
             mEditTitle = getContext().getString(editTitleResourceId);
-            return this;
+            return (B) this;
         }
 
         /**
@@ -266,9 +263,9 @@
          * providing extra information on what the action will do.
          * @param description The description for this action.
          */
-        public BuilderBase<T> description(CharSequence description) {
+        public B description(CharSequence description) {
             mDescription = description;
-            return this;
+            return (B) this;
         }
 
         /**
@@ -276,9 +273,9 @@
          * providing extra information on what the action will do.
          * @param descriptionResourceId String resource id of the description for this action.
          */
-        public BuilderBase<T> description(@StringRes int descriptionResourceId) {
+        public B description(@StringRes int descriptionResourceId) {
             mDescription = getContext().getString(descriptionResourceId);
-            return this;
+            return (B) this;
         }
 
         /**
@@ -286,9 +283,9 @@
          * description replaces the string of description.
          * @param description The description to edit for this action.
          */
-        public BuilderBase<T> editDescription(CharSequence description) {
+        public B editDescription(CharSequence description) {
             mEditDescription = description;
-            return this;
+            return (B) this;
         }
 
         /**
@@ -297,9 +294,9 @@
          * @param descriptionResourceId String resource id of the description to edit for this
          * action.
          */
-        public BuilderBase<T> editDescription(@StringRes int descriptionResourceId) {
+        public B editDescription(@StringRes int descriptionResourceId) {
             mEditDescription = getContext().getString(descriptionResourceId);
-            return this;
+            return (B) this;
         }
 
         /**
@@ -307,18 +304,18 @@
          * directly when the action is clicked.
          * @param intent The intent associated with this action.
          */
-        public BuilderBase<T> intent(Intent intent) {
+        public B intent(Intent intent) {
             mIntent = intent;
-            return this;
+            return (B) this;
         }
 
         /**
          * Sets the action's icon drawable.
          * @param icon The drawable for the icon associated with this action.
          */
-        public BuilderBase<T> icon(Drawable icon) {
+        public B icon(Drawable icon) {
             mIcon = icon;
-            return this;
+            return (B) this;
         }
 
         /**
@@ -330,7 +327,7 @@
          * @deprecated Use {@link #icon(int)}.
          */
         @Deprecated
-        public BuilderBase<T> iconResourceId(@DrawableRes int iconResourceId, Context context) {
+        public B iconResourceId(@DrawableRes int iconResourceId, Context context) {
             return icon(ContextCompat.getDrawable(context, iconResourceId));
         }
 
@@ -340,7 +337,7 @@
          * {@link #icon(Drawable)}.
          * @param iconResourceId The resource ID for the icon associated with this action.
          */
-        public BuilderBase<T> icon(@DrawableRes int iconResourceId) {
+        public B icon(@DrawableRes int iconResourceId) {
             return icon(ContextCompat.getDrawable(getContext(), iconResourceId));
         }
 
@@ -349,24 +346,48 @@
          * checked, or belong to a check set.
          * @param editable Whether this action is editable.
          */
-        public BuilderBase<T> editable(boolean editable) {
-            mEditable = editable;
+        public B editable(boolean editable) {
+            if (!editable && mEditable == EDITING_TITLE) {
+                mEditable = EDITING_NONE;
+                return (B) this;
+            }
+            mEditable = EDITING_TITLE;
             if (mChecked || mCheckSetId != NO_CHECK_SET) {
                 throw new IllegalArgumentException("Editable actions cannot also be checked");
             }
-            return this;
+            return (B) this;
         }
 
         /**
          * Indicates whether this action's description is editable
          * @param editable Whether this action description is editable.
          */
-        public BuilderBase<T> descriptionEditable(boolean editable) {
-            mDescriptionEditable = editable;
+        public B descriptionEditable(boolean editable) {
+            if (!editable && mEditable == EDITING_DESCRIPTION) {
+                mEditable = EDITING_NONE;
+                return (B) this;
+            }
+            mEditable = EDITING_DESCRIPTION;
             if (mChecked || mCheckSetId != NO_CHECK_SET) {
                 throw new IllegalArgumentException("Editable actions cannot also be checked");
             }
-            return this;
+            return (B) this;
+        }
+
+        /**
+         * Indicates whether this action has a view can be activated to edit, e.g. a DatePicker.
+         * @param editable Whether this action has view can be activated to edit.
+         */
+        public B hasEditableActivatorView(boolean editable) {
+            if (!editable && mEditable == EDITING_ACTIVATOR_VIEW) {
+                mEditable = EDITING_NONE;
+                return (B) this;
+            }
+            mEditable = EDITING_ACTIVATOR_VIEW;
+            if (mChecked || mCheckSetId != NO_CHECK_SET) {
+                throw new IllegalArgumentException("Editable actions cannot also be checked");
+            }
+            return (B) this;
         }
 
         /**
@@ -374,9 +395,9 @@
          *
          * @param inputType InputType for the action title not in editing.
          */
-        public BuilderBase<T> inputType(int inputType) {
+        public B inputType(int inputType) {
             mInputType = inputType;
-            return this;
+            return (B) this;
         }
 
         /**
@@ -384,9 +405,9 @@
          *
          * @param inputType InputType for the action description not in editing.
          */
-        public BuilderBase<T> descriptionInputType(int inputType) {
+        public B descriptionInputType(int inputType) {
             mDescriptionInputType = inputType;
-            return this;
+            return (B) this;
         }
 
 
@@ -395,9 +416,9 @@
          *
          * @param inputType InputType for the action title in editing.
          */
-        public BuilderBase<T> editInputType(int inputType) {
+        public B editInputType(int inputType) {
             mEditInputType = inputType;
-            return this;
+            return (B) this;
         }
 
         /**
@@ -405,9 +426,9 @@
          *
          * @param inputType InputType for the action description in editing.
          */
-        public BuilderBase<T> descriptionEditInputType(int inputType) {
+        public B descriptionEditInputType(int inputType) {
             mDescriptionEditInputType = inputType;
-            return this;
+            return (B) this;
         }
 
 
@@ -415,12 +436,12 @@
          * Indicates whether this action is initially checked.
          * @param checked Whether this action is checked.
          */
-        public BuilderBase<T> checked(boolean checked) {
+        public B checked(boolean checked) {
             mChecked = checked;
-            if (mEditable || mDescriptionEditable) {
+            if (mEditable != EDITING_NONE) {
                 throw new IllegalArgumentException("Editable actions cannot also be checked");
             }
-            return this;
+            return (B) this;
         }
 
         /**
@@ -430,12 +451,12 @@
          * @param checkSetId The check set ID, or {@link GuidedAction#NO_CHECK_SET} to indicate not
          * radio or checkbox, or {@link GuidedAction#CHECKBOX_CHECK_SET_ID} to indicate a checkbox.
          */
-        public BuilderBase<T> checkSetId(int checkSetId) {
+        public B checkSetId(int checkSetId) {
             mCheckSetId = checkSetId;
-            if (mEditable || mDescriptionEditable) {
+            if (mEditable != EDITING_NONE) {
                 throw new IllegalArgumentException("Editable actions cannot also be in check sets");
             }
-            return this;
+            return (B) this;
         }
 
         /**
@@ -443,36 +464,36 @@
          * appropriately.
          * @param multilineDescription Whether this action has a multiline description.
          */
-        public BuilderBase<T> multilineDescription(boolean multilineDescription) {
+        public B multilineDescription(boolean multilineDescription) {
             mMultilineDescription = multilineDescription;
-            return this;
+            return (B) this;
         }
 
         /**
          * Indicates whether this action has a next state and should display a chevron.
          * @param hasNext Whether this action has a next state.
          */
-        public BuilderBase<T> hasNext(boolean hasNext) {
+        public B hasNext(boolean hasNext) {
             mHasNext = hasNext;
-            return this;
+            return (B) this;
         }
 
         /**
          * Indicates whether this action is for information purposes only and cannot be clicked.
          * @param infoOnly Whether this action has a next state.
          */
-        public BuilderBase<T> infoOnly(boolean infoOnly) {
+        public B infoOnly(boolean infoOnly) {
             mInfoOnly = infoOnly;
-            return this;
+            return (B) this;
         }
 
         /**
          * Indicates whether this action is enabled.  If not enabled, an action cannot be clicked.
          * @param enabled Whether the action is enabled.
          */
-        public BuilderBase<T> enabled(boolean enabled) {
+        public B enabled(boolean enabled) {
             mEnabled = enabled;
-            return this;
+            return (B) this;
         }
 
         /**
@@ -480,9 +501,9 @@
          * @param focusable
          * @return The same BuilderBase object.
          */
-        public BuilderBase<T> focusable(boolean focusable) {
+        public B focusable(boolean focusable) {
             mFocusable = focusable;
-            return this;
+            return (B) this;
         }
 
         /**
@@ -490,16 +511,16 @@
          * @param subActions
          * @return The same BuilderBase object.
          */
-        public BuilderBase<T> subActions(List<GuidedAction> subActions) {
+        public B subActions(List<GuidedAction> subActions) {
             mSubActions = subActions;
-            return this;
+            return (B) this;
         }
     }
 
     /**
      * Builds a {@link GuidedAction} object.
      */
-    public static class Builder extends BuilderBase<GuidedAction> {
+    public static class Builder extends BuilderBase<Builder> {
 
         /**
          * @deprecated Use {@link GuidedAction.Builder#GuidedAction.Builder(Context)}.
@@ -517,7 +538,10 @@
             super(context);
         }
 
-        @Override
+        /**
+         * Builds the GuidedAction corresponding to this Builder.
+         * @return The GuidedAction as configured through this Builder.
+         */
         public GuidedAction build() {
             GuidedAction action = new GuidedAction();
             applyValues(action);
@@ -528,8 +552,7 @@
 
     private CharSequence mEditTitle;
     private CharSequence mEditDescription;
-    private boolean mEditable;
-    private boolean mDescriptionEditable;
+    private int mEditable;
     private int mInputType;
     private int mDescriptionInputType;
     private int mEditInputType;
@@ -642,11 +665,20 @@
     }
 
     /**
+     * Returns whether this action has any editable part, e.g. editable title, editable description
+     * or editable activate view.
+     * @return true if this action has any editable part, false otherwise.
+     */
+    public boolean hasAnyEditable() {
+        return mEditable != EDITING_NONE;
+    }
+
+    /**
      * Returns whether this action title is editable.
      * @return true if the action title is editable, false otherwise.
      */
     public boolean isEditable() {
-        return mEditable;
+        return mEditable == EDITING_TITLE;
     }
 
     /**
@@ -654,7 +686,23 @@
      * @return true if the action description is editable, false otherwise.
      */
     public boolean isDescriptionEditable() {
-        return mDescriptionEditable;
+        return mEditable == EDITING_DESCRIPTION;
+    }
+
+    /**
+     * Returns if this action has editable title or editable description.
+     * @return True if this action has editable title or editable description, false otherwise.
+     */
+    public boolean hasTextEditable() {
+        return mEditable == EDITING_TITLE || mEditable == EDITING_DESCRIPTION;
+    }
+
+    /**
+     * Returns whether this action can be activated to edit, e.g. a DatePicker.
+     * @return true if the action can be activated to edit.
+     */
+    public boolean hasEditableActivatorView() {
+        return mEditable == EDITING_ACTIVATOR_VIEW;
     }
 
     /**
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionAdapter.java b/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionAdapter.java
index e0fad0a..ee44656 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionAdapter.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionAdapter.java
@@ -108,9 +108,13 @@
                 GuidedActionsStylist.ViewHolder avh = (GuidedActionsStylist.ViewHolder)
                         getRecyclerView().getChildViewHolder(v);
                 GuidedAction action = avh.getAction();
-                if (action.isEditable() || action.isDescriptionEditable()) {
+                if (action.hasTextEditable()) {
                     if (DEBUG_EDIT) Log.v(TAG_EDIT, "openIme by click");
                     mGroup.openIme(GuidedActionAdapter.this, avh);
+                } else if (action.hasEditableActivatorView()) {
+                    if (DEBUG_EDIT) Log.v(TAG_EDIT, "toggle editing mode by click");
+                    getGuidedActionsStylist().setEditingMode(avh, avh.getAction(),
+                            !avh.isInEditingActivatorView());
                 } else {
                     handleCheckedActions(avh);
                     if (action.isEnabled() && !action.infoOnly()) {
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionAdapterGroup.java b/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionAdapterGroup.java
index 858a0ed..6fa3d89 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionAdapterGroup.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionAdapterGroup.java
@@ -95,7 +95,7 @@
                         (GuidedActionsStylist.ViewHolder) adapter.getGuidedActionsStylist()
                                 .getActionsGridView().findViewHolderForPosition(index);
                 if (vh != null) {
-                    if (vh.getAction().isEditable() || vh.getAction().isDescriptionEditable()) {
+                    if (vh.getAction().hasTextEditable()) {
                         if (DEBUG_EDIT) Log.v(TAG_EDIT, "openIme of next Action");
                         // open Ime on next action.
                         openIme(adapter, vh);
@@ -122,7 +122,7 @@
     public void openIme(GuidedActionAdapter adapter, GuidedActionsStylist.ViewHolder avh) {
         adapter.getGuidedActionsStylist().setEditingMode(avh, avh.getAction(), true);
         View v = avh.getEditingView();
-        if (v == null) {
+        if (v == null || !avh.isInEditingText()) {
             return;
         }
         InputMethodManager mgr = (InputMethodManager)
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 2a95dfe..835d512 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionsStylist.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionsStylist.java
@@ -30,7 +30,10 @@
 import android.support.v17.leanback.R;
 import android.support.v17.leanback.transition.TransitionHelper;
 import android.support.v17.leanback.transition.TransitionListener;
+import android.support.v17.leanback.widget.GuidedActionAdapter.EditListener;
 import android.support.v17.leanback.widget.VerticalGridView;
+import android.support.v17.leanback.widget.picker.DatePicker;
+import android.support.v17.leanback.widget.picker.Picker;
 import android.support.v4.content.ContextCompat;
 import android.support.v4.view.ViewCompat;
 import android.support.v7.widget.RecyclerView;
@@ -39,6 +42,7 @@
 import android.util.Log;
 import android.util.TypedValue;
 import android.view.animation.DecelerateInterpolator;
+import android.view.animation.LinearInterpolator;
 import android.view.inputmethod.EditorInfo;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -53,16 +57,22 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import java.util.Calendar;
 import java.util.Collections;
 import java.util.List;
 
+import static android.support.v17.leanback.widget.GuidedAction.EDITING_NONE;
+import static android.support.v17.leanback.widget.GuidedAction.EDITING_TITLE;
+import static android.support.v17.leanback.widget.GuidedAction.EDITING_DESCRIPTION;
+import static android.support.v17.leanback.widget.GuidedAction.EDITING_ACTIVATOR_VIEW;
+
 /**
  * GuidedActionsStylist is used within a {@link android.support.v17.leanback.app.GuidedStepFragment}
  * to supply the right-side panel where users can take actions. It consists of a container for the
  * list of actions, and a stationary selector view that indicates visually the location of focus.
  * GuidedActionsStylist has two different layouts: default is for normal actions including text,
- * radio, checkbox etc, the other when {@link #setAsButtonActions()} is called is recommended for
- * button actions such as "yes", "no".
+ * radio, checkbox, DatePicker, etc, the other when {@link #setAsButtonActions()} is called is
+ * recommended for button actions such as "yes", "no".
  * <p>
  * Many aspects of the base GuidedActionsStylist can be customized through theming; see the
  * theme attributes below. Note that these attributes are not set on individual elements in layout
@@ -72,8 +82,16 @@
  * <p>
  * If these hooks are insufficient, this class may also be subclassed. Subclasses may wish to
  * override the {@link #onProvideLayoutId} method to change the layout used to display the
- * list container and selector, or the {@link #onProvideItemLayoutId} method to change the layout
- * used to display each action.
+ * list container and selector; override {@link #onProvideItemLayoutId(int)} and
+ * {@link #getItemViewType(GuidedAction)} method to change the layout used to display each action.
+ * <p>
+ * To support a "click to activate" view similar to DatePicker, app needs:
+ * <li> Override {@link #onProvideItemLayoutId(int)} and {@link #getItemViewType(GuidedAction)},
+ * provides a layout id for the action.
+ * <li> The layout must include a widget with id "guidedactions_activator_item", the widget is
+ * toggled edit mode by {@link View#setActivated(boolean)}.
+ * <li> Override {@link #onBindActivatorView(ViewHolder, GuidedAction)} to populate values into View.
+ * <li> Override {@link #onUpdateActivatorView(ViewHolder, GuidedAction)} to update action.
  * <p>
  * Note: If an alternate list layout is provided, the following view IDs must be supplied:
  * <ul>
@@ -136,6 +154,11 @@
     public static final int VIEW_TYPE_DEFAULT = 0;
 
     /**
+     * ViewType for DatePicker.
+     */
+    public static final int VIEW_TYPE_DATE_PICKER = 1;
+
+    /**
      * ViewHolder caches information about the action item layouts' subviews. Subclasses of {@link
      * GuidedActionsStylist} may also wish to subclass this in order to add fields.
      * @see GuidedAction
@@ -146,11 +169,11 @@
         private View mContentView;
         private TextView mTitleView;
         private TextView mDescriptionView;
+        private View mActivatorView;
         private ImageView mIconView;
         private ImageView mCheckmarkView;
         private ImageView mChevronView;
-        private boolean mInEditing;
-        private boolean mInEditingDescription;
+        private int mEditingMode = EDITING_NONE;
         private final boolean mIsSubAction;
 
         /**
@@ -168,6 +191,7 @@
 
             mContentView = v.findViewById(R.id.guidedactions_item_content);
             mTitleView = (TextView) v.findViewById(R.id.guidedactions_item_title);
+            mActivatorView = v.findViewById(R.id.guidedactions_activator_item);
             mDescriptionView = (TextView) v.findViewById(R.id.guidedactions_item_description);
             mIconView = (ImageView) v.findViewById(R.id.guidedactions_item_icon);
             mCheckmarkView = (ImageView) v.findViewById(R.id.guidedactions_item_checkmark);
@@ -235,26 +259,56 @@
         }
 
         /**
-         * Returns true if the TextView is in editing title or description, false otherwise.
+         * Returns true if in editing title, description, or activator View, false otherwise.
          */
         public boolean isInEditing() {
-            return mInEditing;
+            return mEditingMode != EDITING_NONE;
+        }
+
+        /**
+         * Returns true if in editing title, description, so IME would be open.
+         * @return True if in editing title, description, so IME would be open, false otherwise.
+         */
+        public boolean isInEditingText() {
+            return mEditingMode == EDITING_TITLE || mEditingMode == EDITING_DESCRIPTION;
+        }
+
+        /**
+         * Returns true if the TextView is in editing title, false otherwise.
+         */
+        public boolean isInEditingTitle() {
+            return mEditingMode == EDITING_TITLE;
         }
 
         /**
          * Returns true if the TextView is in editing description, false otherwise.
          */
         public boolean isInEditingDescription() {
-            return mInEditingDescription;
+            return mEditingMode == EDITING_DESCRIPTION;
         }
 
         /**
-         * @return Current editing title view or description view or null if not in editing.
+         * Returns true if is in editing activator view with id guidedactions_activator_item, false
+         * otherwise.
+         */
+        public boolean isInEditingActivatorView() {
+            return mEditingMode == EDITING_ACTIVATOR_VIEW;
+        }
+
+        /**
+         * @return Current editing title view or description view or activator view or null if not
+         * in editing.
          */
         public View getEditingView() {
-            if (mInEditing) {
-                return mInEditingDescription ?  mDescriptionView : mTitleView;
-            } else {
+            switch(mEditingMode) {
+            case EDITING_TITLE:
+                return mTitleView;
+            case EDITING_DESCRIPTION:
+                return mDescriptionView;
+            case EDITING_ACTIVATOR_VIEW:
+                return mActivatorView;
+            case EDITING_NONE:
+            default:
                 return null;
             }
         }
@@ -297,6 +351,8 @@
     private int mVerticalPadding;
     private int mDisplayHeight;
 
+    private EditListener mEditListener;
+
     private GuidedAction mExpandedAction = null;
     private Object mExpandTransition;
 
@@ -428,6 +484,9 @@
      * @return View type that used in {@link #onProvideItemLayoutId(int)}.
      */
     public int getItemViewType(GuidedAction action) {
+        if (action instanceof GuidedDatePickerAction) {
+            return VIEW_TYPE_DATE_PICKER;
+        }
         return VIEW_TYPE_DEFAULT;
     }
 
@@ -451,19 +510,24 @@
     /**
      * Provides the resource ID of the layout defining the view for an individual guided actions.
      * Subclasses may override to provide their own customized layouts. The base implementation
-     * returns {@link android.support.v17.leanback.R.layout#lb_guidedactions_item}. If overridden,
-     * the substituted layout should contain matching IDs for any views that should be managed by
-     * the base class; this can be achieved by starting with a copy of the base layout file. Note
-     * that in order for the item to support editing, the title view should both subclass {@link
-     * android.widget.EditText} and implement {@link ImeKeyMonitor}; see {@link
-     * GuidedActionEditText}.
+     * supports:
+     * <li>{@link android.support.v17.leanback.R.layout#lb_guidedactions_item}
+     * <li>{{@link android.support.v17.leanback.R.layout#lb_guidedactions_datepicker_item}. If
+     * overridden, the substituted layout should contain matching IDs for any views that should be
+     * managed by the base class; this can be achieved by starting with a copy of the base layout
+     * file. Note that in order for the item to support editing, the title view should both subclass
+     * {@link android.widget.EditText} and implement {@link ImeKeyMonitor}; see
+     * {@link GuidedActionEditText}.
+     *
      * @param viewType View type returned by {@link #getItemViewType(GuidedAction)}
      * @return The resource ID of the layout to be inflated to define the view to display an
-     * individual GuidedAction.
+     *         individual GuidedAction.
      */
     public int onProvideItemLayoutId(int viewType) {
         if (viewType == VIEW_TYPE_DEFAULT) {
             return onProvideItemLayoutId();
+        } else if (viewType == VIEW_TYPE_DATE_PICKER) {
+            return R.layout.lb_guidedactions_datepicker_item;
         } else {
             throw new RuntimeException("ViewType " + viewType +
                     " not supported in GuidedActionsStylist");
@@ -549,6 +613,9 @@
                 vh.mDescriptionView.setMaxLines(mDescriptionMinLines);
             }
         }
+        if (vh.mActivatorView != null) {
+            onBindActivatorView(vh, action);
+        }
         setEditingMode(vh, action, false);
         if (action.isFocusable()) {
             vh.itemView.setFocusable(true);
@@ -580,8 +647,7 @@
     }
 
     public void setEditingMode(ViewHolder vh, GuidedAction action, boolean editing) {
-        if (editing != vh.mInEditing) {
-            vh.mInEditing = editing;
+        if (editing != vh.isInEditing() && !isInExpandTransition()) {
             onEditingModeChange(vh, action, editing);
         }
     }
@@ -604,12 +670,15 @@
                     descriptionView.setVisibility(View.VISIBLE);
                     descriptionView.setInputType(action.getDescriptionEditInputType());
                 }
-                vh.mInEditingDescription = true;
-            } else {
-                vh.mInEditingDescription = false;
+                vh.mEditingMode = EDITING_DESCRIPTION;
+            } else if (action.isEditable()){
                 if (titleView != null) {
                     titleView.setInputType(action.getEditInputType());
                 }
+                vh.mEditingMode = EDITING_TITLE;
+            } else if (vh.mActivatorView != null) {
+                onEditActivatorView(vh, action, editing);
+                vh.mEditingMode = EDITING_ACTIVATOR_VIEW;
             }
         } else {
             if (titleView != null) {
@@ -618,18 +687,22 @@
             if (descriptionView != null) {
                 descriptionView.setText(action.getDescription());
             }
-            if (vh.mInEditingDescription) {
+            if (vh.mEditingMode == EDITING_DESCRIPTION) {
                 if (descriptionView != null) {
                     descriptionView.setVisibility(TextUtils.isEmpty(action.getDescription()) ?
                             View.GONE : View.VISIBLE);
                     descriptionView.setInputType(action.getDescriptionInputType());
                 }
-                vh.mInEditingDescription = false;
-            } else {
+            } else if (vh.mEditingMode == EDITING_TITLE) {
                 if (titleView != null) {
                     titleView.setInputType(action.getInputType());
                 }
+            } else if (vh.mEditingMode == EDITING_ACTIVATOR_VIEW) {
+                if (vh.mActivatorView != null) {
+                    onEditActivatorView(vh, action, editing);
+                }
             }
+            vh.mEditingMode = EDITING_NONE;
         }
     }
 
@@ -716,6 +789,76 @@
     }
 
     /**
+     * Performs binding activator view value to action.  Default implementation supports
+     * GuidedDatePickerAction, subclass may override to add support of other views.
+     * @param vh ViewHolder of activator view.
+     * @param action GuidedAction to bind.
+     */
+    public void onBindActivatorView(ViewHolder vh, GuidedAction action) {
+        if (action instanceof GuidedDatePickerAction) {
+            GuidedDatePickerAction dateAction = (GuidedDatePickerAction) action;
+            DatePicker dateView = (DatePicker) vh.mActivatorView;
+            dateView.setDatePickerFormat(dateAction.getDatePickerFormat());
+            Calendar c = Calendar.getInstance();
+            c.setTimeInMillis(((GuidedDatePickerAction) action).getDate());
+            dateView.updateDate(c.get(Calendar.YEAR), c.get(Calendar.MONTH),
+                    c.get(Calendar.DAY_OF_MONTH), false);
+        }
+    }
+
+    /**
+     * Performs updating GuidedAction from activator view.  Default implementation supports
+     * GuidedDatePickerAction, subclass may override to add support of other views.
+     * @param vh ViewHolder of activator view.
+     * @param action GuidedAction to update.
+     * @return True if value has been updated, false otherwise.
+     */
+    public boolean onUpdateActivatorView(ViewHolder vh, GuidedAction action) {
+        if (action instanceof GuidedDatePickerAction) {
+            GuidedDatePickerAction dateAction = (GuidedDatePickerAction) action;
+            DatePicker dateView = (DatePicker) vh.mActivatorView;
+            if (dateAction.getDate() != dateView.getDate()) {
+                dateAction.setDate(dateView.getDate());
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Sets listener for reporting view being edited.
+     * @hide
+     */
+    public void setEditListener(EditListener listener) {
+        mEditListener = listener;
+    }
+
+    void onEditActivatorView(final ViewHolder vh, final GuidedAction action,
+            boolean editing) {
+        if (editing) {
+            vh.mActivatorView.requestFocus();
+            setExpandedViewHolder(vh);
+            vh.mActivatorView.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    if (!isInExpandTransition()) {
+                        setEditingMode(vh, action, false);
+                    }
+                }
+            });
+        } else {
+            if (onUpdateActivatorView(vh, action)) {
+                if (mEditListener != null) {
+                    mEditListener.onGuidedActionEdited(action);
+                }
+            }
+            vh.itemView.requestFocus();
+            setExpandedViewHolder(null);
+            vh.mActivatorView.setOnClickListener(null);
+        }
+    }
+
+    /**
      * Sets states of chevron view, called by {@link #onBindViewHolder(ViewHolder, GuidedAction)}.
      * Subclass may override.
      *
@@ -750,7 +893,7 @@
      * hide the other items in main list.  When null, collapse the sub actions list.
      */
     public void setExpandedViewHolder(ViewHolder avh) {
-        if (mSubActionsGridView == null || isInExpandTransition()) {
+        if (isInExpandTransition()) {
             return;
         }
         if (isExpandTransitionSupported()) {
@@ -804,12 +947,15 @@
             onUpdateExpandedViewHolder(avh);
             return;
         }
+        boolean isSubActionTransition = focusAvh.getAction().hasSubActions();
         Object set = TransitionHelper.createTransitionSet(false);
+        float slideDistance = isSubActionTransition ? focusAvh.itemView.getHeight() :
+                focusAvh.itemView.getHeight() * 0.5f;
         Object slideAndFade = TransitionHelper.createFadeAndShortSlide(Gravity.TOP | Gravity.BOTTOM,
-                (float) focusAvh.itemView.getHeight());
+                slideDistance);
         Object changeFocusItemTransform = TransitionHelper.createChangeTransform();
         Object changeFocusItemBounds = TransitionHelper.createChangeBounds(false);
-        Object fadeGrid = TransitionHelper.createFadeTransition(TransitionHelper.FADE_IN |
+        Object fade = TransitionHelper.createFadeTransition(TransitionHelper.FADE_IN |
                 TransitionHelper.FADE_OUT);
         Object changeGridBounds = TransitionHelper.createChangeBounds(false);
         if (avh == null) {
@@ -817,7 +963,7 @@
             TransitionHelper.setStartDelay(changeFocusItemTransform, 100);
             TransitionHelper.setStartDelay(changeFocusItemBounds, 100);
         } else {
-            TransitionHelper.setStartDelay(fadeGrid, 100);
+            TransitionHelper.setStartDelay(fade, 100);
             TransitionHelper.setStartDelay(changeGridBounds, 100);
             TransitionHelper.setStartDelay(changeFocusItemTransform, 50);
             TransitionHelper.setStartDelay(changeFocusItemBounds, 50);
@@ -827,19 +973,25 @@
                     .getChildViewHolder(mActionsGridView.getChildAt(i));
             if (vh == focusAvh) {
                 // going to expand/collapse this one.
-                TransitionHelper.include(changeFocusItemTransform, vh.itemView);
-                TransitionHelper.include(changeFocusItemBounds, vh.itemView);
+                if (isSubActionTransition) {
+                    TransitionHelper.include(changeFocusItemTransform, vh.itemView);
+                    TransitionHelper.include(changeFocusItemBounds, vh.itemView);
+                }
             } else {
                 // going to slide this item to top / bottom.
                 TransitionHelper.include(slideAndFade, vh.itemView);
+                TransitionHelper.exclude(fade, vh.itemView, true);
             }
         }
-        TransitionHelper.include(fadeGrid, mSubActionsGridView);
         TransitionHelper.include(changeGridBounds, mSubActionsGridView);
         TransitionHelper.addTransition(set, slideAndFade);
-        TransitionHelper.addTransition(set, changeFocusItemTransform);
-        TransitionHelper.addTransition(set, changeFocusItemBounds);
-        TransitionHelper.addTransition(set, fadeGrid);
+        // note that we don't run ChangeBounds for activating view due to the rounding problem
+        // of multiple level views ChangeBounds animation causing vertical jittering.
+        if (isSubActionTransition) {
+            TransitionHelper.addTransition(set, changeFocusItemTransform);
+            TransitionHelper.addTransition(set, changeFocusItemBounds);
+        }
+        TransitionHelper.addTransition(set, fade);
         TransitionHelper.addTransition(set, changeGridBounds);
         mExpandTransition = set;
         TransitionHelper.addTransitionListener(mExpandTransition, new TransitionListener() {
@@ -917,7 +1069,7 @@
             updateChevronAndVisibility(vh);
         }
         if (mSubActionsGridView != null) {
-            if (avh != null) {
+            if (avh != null && avh.getAction().hasSubActions()) {
                 ViewGroup.MarginLayoutParams lp =
                         (ViewGroup.MarginLayoutParams) mSubActionsGridView.getLayoutParams();
                 lp.topMargin = avh.itemView.getTop();
@@ -928,7 +1080,7 @@
                 mSubActionsGridView.setSelectedPosition(0);
                 ((GuidedActionAdapter) mSubActionsGridView.getAdapter())
                         .setActions(avh.getAction().getSubActions());
-            } else {
+            } else if (mSubActionsGridView.getVisibility() == View.VISIBLE) {
                 mSubActionsGridView.setVisibility(View.INVISIBLE);
                 ViewGroup.MarginLayoutParams lp =
                         (ViewGroup.MarginLayoutParams) mSubActionsGridView.getLayoutParams();
@@ -946,9 +1098,17 @@
             if (mExpandedAction == null) {
                 vh.itemView.setVisibility(View.VISIBLE);
                 vh.itemView.setTranslationY(0);
+                if (vh.mActivatorView != null) {
+                    vh.mActivatorView.setActivated(false);
+                }
             } else if (vh.getAction() == mExpandedAction) {
                 vh.itemView.setVisibility(View.VISIBLE);
-                vh.itemView.setTranslationY(- vh.itemView.getHeight());
+                if (vh.getAction().hasSubActions()) {
+                    vh.itemView.setTranslationY(- vh.itemView.getHeight());
+                } else if (vh.mActivatorView != null) {
+                    vh.itemView.setTranslationY(0);
+                    vh.mActivatorView.setActivated(true);
+                }
             } else {
                 vh.itemView.setVisibility(View.INVISIBLE);
                 vh.itemView.setTranslationY(0);
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/GuidedDatePickerAction.java b/v17/leanback/src/android/support/v17/leanback/widget/GuidedDatePickerAction.java
new file mode 100644
index 0000000..9daed2a
--- /dev/null
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GuidedDatePickerAction.java
@@ -0,0 +1,125 @@
+/*
+ * 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.support.v17.leanback.widget.picker.DatePicker;
+
+import java.util.Calendar;
+
+/**
+ * Subclass of GuidedAction that can choose a date.  The Action is editable by default; to make it
+ * read only, call hasEditableActivatorView(false) on the Builder.
+ */
+public class GuidedDatePickerAction extends GuidedAction {
+
+    /**
+     * Base Builder class to build GuidedDatePickerAction.  Subclass this BuilderBase when app needs
+     * to subclass GuidedDatePickerAction, implement your build() which should call
+     * {@link #applyDatePickerValues(GuidedDatePickerAction)}.  When using GuidedDatePickerAction
+     * directly, use {@link Builder}.
+     */
+    public abstract static class BuilderBase<B extends BuilderBase>
+            extends GuidedAction.BuilderBase<B> {
+
+        private String mDatePickerFormat;
+        private long mDate;
+
+        public BuilderBase(Context context) {
+            super(context);
+            Calendar c = Calendar.getInstance();
+            mDate = c.getTimeInMillis();
+            hasEditableActivatorView(true);
+        }
+
+        /**
+         * Sets format of date Picker.  When the format is not specified,
+         * a default format of current locale will be used.
+         * @param format Format of showing Date, e.g. "YMD"
+         * @return This Builder object.
+         */
+        public B datePickerFormat(String format) {
+            mDatePickerFormat = format;
+            return (B) this;
+        }
+
+        /**
+         * Sets a Date for date picker, see {@link Calendar#getTimeInMillis()}.
+         * @param date See {@link Calendar#getTimeInMillis()}.
+         * @return This Builder Object.
+         */
+        public B date(long date) {
+            mDate = date;
+            return (B) this;
+        }
+
+        /**
+         * Apply values to GuidedDatePickerAction.
+         * @param action GuidedDatePickerAction to apply values.
+         */
+        protected final void applyDatePickerValues(GuidedDatePickerAction action) {
+            super.applyValues(action);
+            action.mDatePickerFormat = mDatePickerFormat;
+            action.mDate = mDate;
+        }
+
+    }
+
+    /**
+     * Builder class to build a GuidedDatePickerAction.
+     */
+    public final static class Builder extends BuilderBase<Builder> {
+        public Builder(Context context) {
+            super(context);
+        }
+
+        /**
+         * Builds the GuidedDatePickerAction corresponding to this Builder.
+         * @return The GuidedDatePickerAction as configured through this Builder.
+         */
+        public GuidedDatePickerAction build() {
+            GuidedDatePickerAction action = new GuidedDatePickerAction();
+            applyDatePickerValues(action);
+            return action;
+        }
+    }
+
+    private String mDatePickerFormat;
+    private long mDate;
+
+    /**
+     * Returns format of date Picker or null if not specified.  When the
+     * format is not specified, a default format of current locale will be used.
+     * @return Format of showing Date, e.g. "YMD".  Returns null if using current locale's default.
+     */
+    public String getDatePickerFormat() {
+        return mDatePickerFormat;
+    }
+
+    /**
+     * Get current value of DatePicker;
+     * @return Current value of DatePicker;
+     */
+    public long getDate() {
+        return mDate;
+    }
+
+    /**
+     * Sets current value of DatePicker;
+     * @param date New value to update current value of DatePicker;
+     */
+    public void setDate(long date) {
+        mDate = date;
+    }
+}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/picker/DatePicker.java b/v17/leanback/src/android/support/v17/leanback/widget/picker/DatePicker.java
index 00c6f3c..209b7e6 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/picker/DatePicker.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/picker/DatePicker.java
@@ -39,8 +39,8 @@
  * @attr ref R.styleable#lbDatePicker_android_maxDate
  * @attr ref R.styleable#lbDatePicker_android_minDate
  * @attr ref R.styleable#lbDatePicker_datePickerFormat
+ * @hide
  */
-
 public class DatePicker extends Picker {
 
     static final String LOG_TAG = "DatePicker";
@@ -62,23 +62,20 @@
     Calendar mCurrentDate;
     Calendar mTempDate;
 
+    public DatePicker(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
     public DatePicker(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
 
         updateCurrentLocale();
+        setSeparator(mConstant.dateSeparator);
 
         final TypedArray attributesArray = context.obtainStyledAttributes(attrs,
                 R.styleable.lbDatePicker);
         String minDate = attributesArray.getString(R.styleable.lbDatePicker_android_minDate);
         String maxDate = attributesArray.getString(R.styleable.lbDatePicker_android_maxDate);
-        String datePickerFormat = attributesArray
-                .getString(R.styleable.lbDatePicker_datePickerFormat);
-        if (TextUtils.isEmpty(datePickerFormat)) {
-            datePickerFormat = new String(
-                    android.text.format.DateFormat.getDateFormatOrder(context));
-        }
-        setDatePickerFormat(datePickerFormat);
-
         mTempDate.clear();
         if (!TextUtils.isEmpty(minDate)) {
             if (!parseDate(minDate, mTempDate)) {
@@ -87,7 +84,7 @@
         } else {
             mTempDate.set(1900, 0, 1);
         }
-        setMinDate(mTempDate.getTimeInMillis());
+        mMinDate.setTimeInMillis(mTempDate.getTimeInMillis());
 
         mTempDate.clear();
         if (!TextUtils.isEmpty(maxDate)) {
@@ -97,8 +94,15 @@
         } else {
             mTempDate.set(2100, 0, 1);
         }
-        setMaxDate(mTempDate.getTimeInMillis());
+        mMaxDate.setTimeInMillis(mTempDate.getTimeInMillis());
 
+        String datePickerFormat = attributesArray
+                .getString(R.styleable.lbDatePicker_datePickerFormat);
+        if (TextUtils.isEmpty(datePickerFormat)) {
+            datePickerFormat = new String(
+                    android.text.format.DateFormat.getDateFormatOrder(context));
+        }
+        setDatePickerFormat(datePickerFormat);
     }
 
     private boolean parseDate(String date, Calendar outDate) {
@@ -112,10 +116,14 @@
     }
 
     /**
-     * Changes format of showing dates, e.g. 'YMD'.
+     * Changes format of showing dates.  For example "YMD".
      * @param datePickerFormat Format of showing dates.
      */
     public void setDatePickerFormat(String datePickerFormat) {
+        if (TextUtils.isEmpty(datePickerFormat)) {
+            datePickerFormat = new String(
+                    android.text.format.DateFormat.getDateFormatOrder(getContext()));
+        }
         datePickerFormat = datePickerFormat.toUpperCase();
         if (TextUtils.equals(mDatePickerFormat, datePickerFormat)) {
             return;
@@ -132,14 +140,14 @@
                 }
                 columns.add(mYearColumn = new PickerColumn());
                 mColYearIndex = i;
-                mYearColumn.setValueLabelFormat("%d");
+                mYearColumn.setEntryFormat("%d");
                 break;
             case 'M':
                 if (mMonthColumn != null) {
                     throw new IllegalArgumentException("datePicker format error");
                 }
                 columns.add(mMonthColumn = new PickerColumn());
-                mMonthColumn.setValueStaticLabels(mConstant.months);
+                mMonthColumn.setEntries(mConstant.months);
                 mColMonthIndex = i;
                 break;
             case 'D':
@@ -147,7 +155,7 @@
                     throw new IllegalArgumentException("datePicker format error");
                 }
                 columns.add(mDayColumn = new PickerColumn());
-                mDayColumn.setValueLabelFormat("%02d");
+                mDayColumn.setEntryFormat("%02d");
                 mColDayIndex = i;
                 break;
             default:
@@ -159,20 +167,14 @@
     }
 
     /**
-     * Get format of showing dates, e.g. 'YMD'.  Default value is from
-     * {@link android.text.format.DateFormat#getDateFormatOrder}.
+     * Get format of showing dates.  For example "YMD".  Default value is from
+     * {@link android.text.format.DateFormat#getDateFormatOrder(Context)}.
      * @return Format of showing dates.
      */
     public String getDatePickerFormat() {
         return mDatePickerFormat;
     }
 
-    @Override
-    protected String getSeparator() {
-        return mConstant.dateSeparator;
-    }
-
-
     private Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) {
         if (oldCalendar == null) {
             return Calendar.getInstance(locale);
@@ -192,13 +194,13 @@
         mCurrentDate = getCalendarForLocale(mCurrentDate, mConstant.locale);
 
         if (mMonthColumn != null) {
-            mMonthColumn.setValueStaticLabels(mConstant.months);
-            updateAdapter(mColMonthIndex);
+            mMonthColumn.setEntries(mConstant.months);
+            setColumnAt(mColMonthIndex, mMonthColumn);
         }
     }
 
     @Override
-    public void onColumnValueChange(int column, int newVal) {
+    public final void onColumnValueChanged(int column, int newVal) {
         mTempDate.setTimeInMillis(mCurrentDate.getTimeInMillis());
         // take care of wrapping of days and months to update greater fields
         int oldVal = getColumnAt(column).getCurrentValue();
@@ -248,10 +250,8 @@
      *
      * @return The minimal supported date.
      */
-    public Calendar getMinDate() {
-        final Calendar minDate = Calendar.getInstance();
-        minDate.setTimeInMillis(mMinDate.getTimeInMillis());
-        return minDate;
+    public long getMinDate() {
+        return mMinDate.getTimeInMillis();
     }
 
     /**
@@ -284,10 +284,18 @@
      *
      * @return The maximal supported date.
      */
-    public Calendar getMaxDate() {
-        final Calendar maxDate = Calendar.getInstance();
-        maxDate.setTimeInMillis(mMaxDate.getTimeInMillis());
-        return maxDate;
+    public long getMaxDate() {
+        return mMaxDate.getTimeInMillis();
+    }
+
+    /**
+     * Gets current date value in milliseconds since January 1, 1970 00:00:00 in
+     * {@link TimeZone#getDefault()} time zone.
+     *
+     * @return Current date values.
+     */
+    public long getDate() {
+        return mCurrentDate.getTimeInMillis();
     }
 
     private void setDate(int year, int month, int dayOfMonth) {
@@ -321,72 +329,88 @@
                 || mCurrentDate.get(Calendar.DAY_OF_MONTH) != month);
     }
 
+    private static boolean updateMin(PickerColumn column, int value) {
+        if (value != column.getMinValue()) {
+            column.setMinValue(value);
+            return true;
+        }
+        return false;
+    }
+
+    private static boolean updateMax(PickerColumn column, int value) {
+        if (value != column.getMaxValue()) {
+            column.setMaxValue(value);
+            return true;
+        }
+        return false;
+    }
+
     private void updateSpinners(boolean animation) {
         // set the spinner ranges respecting the min and max dates
         boolean dayRangeChanged = false;
         boolean monthRangeChanged = false;
         if (mCurrentDate.equals(mMinDate)) {
             if (mDayColumn != null) {
-                dayRangeChanged |= mDayColumn.setMinValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
-                dayRangeChanged |= mDayColumn
-                        .setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
+                dayRangeChanged |= updateMin(mDayColumn, mCurrentDate.get(Calendar.DAY_OF_MONTH));
+                dayRangeChanged |=
+                        updateMax(mDayColumn, mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
             }
             if (mMonthColumn != null) {
-                monthRangeChanged |= mMonthColumn.setMinValue(mCurrentDate.get(Calendar.MONTH));
+                monthRangeChanged |= updateMin(mMonthColumn, mCurrentDate.get(Calendar.MONTH));
                 monthRangeChanged |=
-                        mMonthColumn.setMaxValue(mCurrentDate.getActualMaximum(Calendar.MONTH));
+                        updateMax(mMonthColumn, mCurrentDate.getActualMaximum(Calendar.MONTH));
             }
         } else if (mCurrentDate.equals(mMaxDate)) {
             if (mDayColumn != null) {
-                dayRangeChanged |= mDayColumn
-                        .setMinValue(mCurrentDate.getActualMinimum(Calendar.DAY_OF_MONTH));
-                dayRangeChanged |= mDayColumn.setMaxValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
+                dayRangeChanged |=
+                        updateMin(mDayColumn, mCurrentDate.getActualMinimum(Calendar.DAY_OF_MONTH));
+                dayRangeChanged |= updateMax(mDayColumn, mCurrentDate.get(Calendar.DAY_OF_MONTH));
             }
             if (mMonthColumn != null) {
                 monthRangeChanged |=
-                        mMonthColumn.setMinValue(mCurrentDate.getActualMinimum(Calendar.MONTH));
-                monthRangeChanged |= mMonthColumn.setMaxValue(mCurrentDate.get(Calendar.MONTH));
+                        updateMin(mMonthColumn, mCurrentDate.getActualMinimum(Calendar.MONTH));
+                monthRangeChanged |= updateMax(mMonthColumn, mCurrentDate.get(Calendar.MONTH));
             }
         } else {
             if (mDayColumn != null) {
-                dayRangeChanged |= mDayColumn
-                        .setMinValue(mCurrentDate.getActualMinimum(Calendar.DAY_OF_MONTH));
-                dayRangeChanged |= mDayColumn
-                        .setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
+                dayRangeChanged |=
+                        updateMin(mDayColumn, mCurrentDate.getActualMinimum(Calendar.DAY_OF_MONTH));
+                dayRangeChanged |=
+                        updateMax(mDayColumn, mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
             }
             if (mMonthColumn != null) {
                 monthRangeChanged |=
-                        mMonthColumn.setMinValue(mCurrentDate.getActualMinimum(Calendar.MONTH));
+                        updateMin(mMonthColumn, mCurrentDate.getActualMinimum(Calendar.MONTH));
                 monthRangeChanged |=
-                        mMonthColumn.setMaxValue(mCurrentDate.getActualMaximum(Calendar.MONTH));
+                        updateMax(mMonthColumn, mCurrentDate.getActualMaximum(Calendar.MONTH));
             }
         }
 
         // year spinner range does not change based on the current date
         boolean yearRangeChanged = false;
         if (mYearColumn != null) {
-            yearRangeChanged |= mYearColumn.setMinValue(mMinDate.get(Calendar.YEAR));
-            yearRangeChanged |= mYearColumn.setMaxValue(mMaxDate.get(Calendar.YEAR));
+            yearRangeChanged |= updateMin(mYearColumn, mMinDate.get(Calendar.YEAR));
+            yearRangeChanged |= updateMax(mYearColumn, mMaxDate.get(Calendar.YEAR));
         }
 
         if (dayRangeChanged) {
-            updateAdapter(mColDayIndex);
+            setColumnAt(mColDayIndex, mDayColumn);
         }
         if (monthRangeChanged) {
-            updateAdapter(mColMonthIndex);
+            setColumnAt(mColMonthIndex, mMonthColumn);
         }
         if (yearRangeChanged) {
-            updateAdapter(mColYearIndex);
+            setColumnAt(mColYearIndex, mYearColumn);
         }
         // set the spinner values
         if (mYearColumn != null) {
-            updateValue(mColYearIndex, mCurrentDate.get(Calendar.YEAR), animation);
+            setColumnValue(mColYearIndex, mCurrentDate.get(Calendar.YEAR), animation);
         }
         if (mMonthColumn != null) {
-            updateValue(mColMonthIndex, mCurrentDate.get(Calendar.MONTH), animation);
+            setColumnValue(mColMonthIndex, mCurrentDate.get(Calendar.MONTH), animation);
         }
         if (mDayColumn != null) {
-            updateValue(mColDayIndex, mCurrentDate.get(Calendar.DAY_OF_MONTH), animation);
+            setColumnValue(mColDayIndex, mCurrentDate.get(Calendar.DAY_OF_MONTH), animation);
         }
 
     }
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/picker/Picker.java b/v17/leanback/src/android/support/v17/leanback/widget/picker/Picker.java
index 1157a11..8e5bcdc 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/picker/Picker.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/picker/Picker.java
@@ -36,28 +36,19 @@
 
 /**
  * Picker is a widget showing multiple customized {@link PickerColumn}s. The PickerColumns are
- * initialized in {@link #setColumns(ArrayList)}. Call {@link #updateAdapter(int)} if the column
- * value range or labels change. Call {@link #updateValue(int, int, boolean)} to update the current
- * value of PickerColumn.
+ * initialized in {@link #setColumns(List)}. Call {@link #setColumnAt(int, PickerColumn)} if the
+ * column value range or labels change. Call {@link #setColumnValue(int, int, boolean)} to update
+ * the current value of PickerColumn.
  * <p>
  * Picker has two states and will change height:
- * <li>{@link #isExpanded()} is true: Picker shows typically three items vertically (see
- * {@link #getVisiblePickerItemsInExpand()}}. Columns other than {@link #getActiveColumn()} still
+ * <li>{@link #isActivated()} is true: Picker shows typically three items vertically (see
+ * {@link #getActivatedVisibleItemCount()}}. Columns other than {@link #getSelectedColumn()} still
  * shows one item if the Picker is focused. On a touch screen device, the Picker will not get focus
  * so it always show three items on all columns. On a non-touch device (a TV), the Picker will show
  * three items only on currently activated column. If the Picker has focus, it will intercept DPAD
  * directions and select activated column.
- * <li>{@link #isExpanded()} is false: Picker shows one item vertically (see
- * {@link #getVisiblePickerItems()}) on all columns. The size of Picker shrinks.
- * <li>The expand mode will be toggled if the Picker has focus and {@link #isToggleExpandOnClick()}
- * is true. Summarize Typically use cases:
- * <li>On a touch screen based device, the Picker focusableInTouchMode=false. It won't get focus, it
- * wont toggle expand mode on click or touch, should call {@link #setExpanded(boolean)} with true,
- * so that user always sees three items on all columns.
- * <li>On a TV: the Picker focusable=true. It will get focus and toggle into expand mode when user
- * clicks on it, toggle can be disabled by {@link #setToggleExpandOnClick(boolean)} with false. Only
- * the activated column shows multiple items and the activated column is selected by DPAD left or
- * right.
+ * <li>{@link #isActivated()} is false: Picker shows one item vertically (see
+ * {@link #getVisibleItemCount()}) on all columns. The size of Picker shrinks.
  */
 public class Picker extends FrameLayout {
 
@@ -65,7 +56,6 @@
         public void onValueChanged(Picker picker, int column);
     }
 
-    private String mSeparator;
     private ViewGroup mRootView;
     private ViewGroup mPickerView;
     private List<VerticalGridView> mColumnViews = new ArrayList<VerticalGridView>();
@@ -79,62 +69,57 @@
     private Interpolator mDecelerateInterpolator;
     private Interpolator mAccelerateInterpolator;
     private ArrayList<PickerValueListener> mListeners;
-    private boolean mExpanded;
-    private float mVisibleItemsInExpand = 3;
+    private float mVisibleItemsActivated = 3;
     private float mVisibleItems = 1;
-    private int mActivatedColumn = 0;
-    private boolean mToggleExpandOnClick = true;
+    private int mSelectedColumn = 0;
+
+    private CharSequence mSeparator;
+    private int mPickerItemLayoutId = R.layout.lb_picker_item;
+    private int mPickerItemTextViewId = 0;
 
     /**
-     * Classes extending {@link Picker} can choose to override this method to
-     * supply the separator string
+     * Gets separator string between columns.
      */
-    protected String getSeparator() {
+    public final CharSequence getSeparator() {
         return mSeparator;
     }
 
     /**
-     * Classes extending {@link Picker} can choose to override this method to
-     * supply the {@link Picker}'s root layout id
+     * Sets separator String between Picker columns.
+     * @param seperator Separator String between Picker columns.
      */
-    protected int getRootLayoutId() {
-        return R.layout.lb_picker;
-    }
-
-    /**
-     * Classes extending {@link Picker} can choose to override this method to
-     * supply the {@link Picker}'s id from within the layout provided by
-     * {@link Picker#getRootLayoutId()}
-     */
-    protected int getPickerId() {
-        return R.id.picker;
-    }
-
-    /**
-     * Classes extending {@link Picker} can choose to override this method to
-     * supply the {@link Picker}'s separator's layout id
-     */
-    protected int getPickerSeparatorLayoutId() {
-        return R.layout.lb_picker_separator;
+    public final void setSeparator(CharSequence seperator) {
+        mSeparator = seperator;
     }
 
     /**
      * Classes extending {@link Picker} can choose to override this method to
      * supply the {@link Picker}'s item's layout id
      */
-    protected int getPickerItemLayoutId() {
-        return R.layout.lb_picker_item;
+    public final int getPickerItemLayoutId() {
+        return mPickerItemLayoutId;
     }
 
     /**
-     * Classes extending {@link Picker} can choose to override this method to
-     * supply the {@link Picker}'s item's {@link TextView}'s id from within the
+     * Returns the {@link Picker}'s item's {@link TextView}'s id from within the
      * layout provided by {@link Picker#getPickerItemLayoutId()} or 0 if the
      * layout provided by {@link Picker#getPickerItemLayoutId()} is a {link
      * TextView}.
      */
-    protected int getPickerItemTextViewId() {
-        return 0;
+    public final int getPickerItemTextViewId() {
+        return mPickerItemTextViewId;
+    }
+
+    /**
+     * Sets the {@link Picker}'s item's {@link TextView}'s id from within the
+     * layout provided by {@link Picker#getPickerItemLayoutId()} or 0 if the
+     * layout provided by {@link Picker#getPickerItemLayoutId()} is a {link
+     * TextView}.
+     * @param textViewId View id of TextView inside a Picker item, or 0 if the Picker item is a
+     *                   TextView.
+     */
+    public final void setPickerItemTextViewId(int textViewId) {
+        mPickerItemTextViewId = textViewId;
     }
 
     /**
@@ -164,15 +149,15 @@
         mAccelerateInterpolator = new AccelerateInterpolator(2.5F);
 
         LayoutInflater inflater = LayoutInflater.from(getContext());
-        mRootView = (ViewGroup) inflater.inflate(getRootLayoutId(), this, true);
-        mPickerView = (ViewGroup) mRootView.findViewById(getPickerId());
+        mRootView = (ViewGroup) inflater.inflate(R.layout.lb_picker, this, true);
+        mPickerView = (ViewGroup) mRootView.findViewById(R.id.picker);
 
     }
 
     /**
      * Get nth PickerColumn.
      * @param colIndex  Index of PickerColumn.
-     * @return PickerColumn at colIndex or null if {@link #setColumns(ArrayList)} is not called yet.
+     * @return PickerColumn at colIndex or null if {@link #setColumns(List)} is not called yet.
      */
     public PickerColumn getColumnAt(int colIndex) {
         if (mColumns == null) {
@@ -183,7 +168,7 @@
 
     /**
      * Get number of PickerColumns.
-     * @return Number of PickerColumns or 0 if {@link #setColumns(ArrayList)} is not called yet.
+     * @return Number of PickerColumns or 0 if {@link #setColumns(List)} is not called yet.
      */
     public int getColumnsCount() {
         if (mColumns == null) {
@@ -196,12 +181,12 @@
      * Set columns and create Views.
      * @param columns PickerColumns to be shown in the Picker.
      */
-    public void setColumns(ArrayList<PickerColumn> columns) {
+    public void setColumns(List<PickerColumn> columns) {
         mColumnViews.clear();
         mPickerView.removeAllViews();
         mColumns = new ArrayList<PickerColumn>(columns);
-        if (mActivatedColumn > mColumns.size() - 1) {
-            mActivatedColumn = mColumns.size() - 1;
+        if (mSelectedColumn > mColumns.size() - 1) {
+            mSelectedColumn = mColumns.size() - 1;
         }
         LayoutInflater inflater = LayoutInflater.from(getContext());
         int totalCol = getColumnsCount();
@@ -225,7 +210,7 @@
             // add a separator if not the last element
             if (i != totalCol - 1 && getSeparator() != null) {
                 TextView separator = (TextView) inflater.inflate(
-                        getPickerSeparatorLayoutId(), mPickerView, false);
+                        R.layout.lb_picker_separator, mPickerView, false);
                 separator.setText(getSeparator());
                 mPickerView.addView(separator);
             }
@@ -240,8 +225,10 @@
      * When column labels change or column range changes, call this function to re-populate the
      * selection list.
      * @param columnIndex Index of column to update.
+     * @param column New column to update.
      */
-    public void updateAdapter(int columnIndex) {
+    public void setColumnAt(int columnIndex, PickerColumn column) {
+        mColumns.set(columnIndex, column);
         VerticalGridView columnView = mColumnViews.get(columnIndex);
         PickerScrollArrayAdapter adapter = (PickerScrollArrayAdapter) columnView.getAdapter();
         if (adapter != null && !columnView.isComputingLayout()) {
@@ -255,8 +242,10 @@
      * @param value New value of the column.
      * @param runAnimation True to scroll to the value or false otherwise.
      */
-    public void updateValue(int columnIndex, int value, boolean runAnimation) {
-        if (mColumns.get(columnIndex).setCurrentValue(value)) {
+    public void setColumnValue(int columnIndex, int value, boolean runAnimation) {
+        PickerColumn column = mColumns.get(columnIndex);
+        if (column.getCurrentValue() != value) {
+            column.setCurrentValue(value);
             notifyValueChanged(columnIndex);
             VerticalGridView columnView = mColumnViews.get(columnIndex);
             if (columnView != null) {
@@ -278,14 +267,22 @@
         }
     }
 
-    public void addPickerValueListener(PickerValueListener listener) {
+    /**
+     * Register a callback to be invoked when the picker's value has changed.
+     * @param listener The callback to ad
+     */
+    public void addOnValueChangedListener(PickerValueListener listener) {
         if (mListeners == null) {
             mListeners = new ArrayList<Picker.PickerValueListener>();
         }
         mListeners.add(listener);
     }
 
-    public void removePickerValueListener(PickerValueListener listener) {
+    /**
+     * Remove a previously installed value changed callback
+     * @param listener The callback to remove.
+     */
+    public void removeOnValueChangedListener(PickerValueListener listener) {
         if (mListeners != null) {
             mListeners.remove(listener);
         }
@@ -307,7 +304,7 @@
 
     private void setOrAnimateAlpha(View view, boolean selected, int colIndex,
             boolean animate) {
-        boolean columnShownAsActivated = colIndex == mActivatedColumn || !isFocused();
+        boolean columnShownAsActivated = colIndex == mSelectedColumn || !isFocused();
         if (selected) {
             // set alpha for main item (selected) in the column
             if (columnShownAsActivated) {
@@ -344,15 +341,17 @@
 
     /**
      * Classes extending {@link Picker} can override this function to supply the
-     * behavior when a list has been scrolled.  Subclass may call {@link #updateValue(int, int,
-     * boolean)} and or {@link #updateAdapter(int)}.  Subclass should not directly call
+     * behavior when a list has been scrolled.  Subclass may call {@link #setColumnValue(int, int,
+     * boolean)} and or {@link #setColumnAt(int,PickerColumn)}.  Subclass should not directly call
      * {@link PickerColumn#setCurrentValue(int)} which does not update internal state or notify
      * listeners.
      * @param columnIndex index of which column was changed.
      * @param newValue A new value desired to be set on the column.
      */
-    public void onColumnValueChange(int columnIndex, int newValue) {
-        if (mColumns.get(columnIndex).setCurrentValue(newValue)) {
+    public void onColumnValueChanged(int columnIndex, int newValue) {
+        PickerColumn column = mColumns.get(columnIndex);
+        if (column.getCurrentValue() != newValue) {
+            column.setCurrentValue(newValue);
             notifyValueChanged(columnIndex);
         }
     }
@@ -402,7 +401,7 @@
 
         public void onBindViewHolder(ViewHolder holder, int position) {
             if (holder.textView != null && mData != null) {
-                holder.textView.setText(mData.getValueLabelAt(mData.getMinValue() + position));
+                holder.textView.setText(mData.getEntryAt(mData.getMinValue() + position));
             }
             setOrAnimateAlpha(holder.itemView,
                     (mColumnViews.get(mColIndex).getSelectedPosition() == position),
@@ -415,7 +414,7 @@
         }
 
         public int getItemCount() {
-            return mData == null ? 0 : mData.getItemsCount();
+            return mData == null ? 0 : mData.getItemCount();
         }
     }
 
@@ -432,7 +431,7 @@
             updateColumnAlpha(colIndex, true);
             if (child != null) {
                 int newValue = mColumns.get(colIndex).getMinValue() + position;
-                onColumnValueChange(colIndex, newValue);
+                onColumnValueChanged(colIndex, newValue);
             }
         }
 
@@ -440,7 +439,7 @@
 
     @Override
     public boolean dispatchKeyEvent(android.view.KeyEvent event) {
-        if (isExpanded()) {
+        if (isActivated()) {
             final int keyCode = event.getKeyCode();
             switch (keyCode) {
             case KeyEvent.KEYCODE_DPAD_LEFT:
@@ -449,20 +448,20 @@
                     if (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL?
                             keyCode == KeyEvent.KEYCODE_DPAD_LEFT :
                             keyCode == KeyEvent.KEYCODE_DPAD_RIGHT ) {
-                        if (mActivatedColumn < getColumnsCount() - 1) {
-                            setActiveColumn(mActivatedColumn + 1);
+                        if (mSelectedColumn < getColumnsCount() - 1) {
+                            setSelectedColumn(mSelectedColumn + 1);
                         }
                     } else {
-                        if (mActivatedColumn > 0) {
-                            setActiveColumn(mActivatedColumn - 1);
+                        if (mSelectedColumn > 0) {
+                            setSelectedColumn(mSelectedColumn - 1);
                         }
                     }
                 }
                 break;
             case KeyEvent.KEYCODE_DPAD_UP:
             case KeyEvent.KEYCODE_DPAD_DOWN:
-                if (event.getAction() == KeyEvent.ACTION_DOWN && mActivatedColumn >= 0) {
-                    VerticalGridView gridView = mColumnViews.get(mActivatedColumn);
+                if (event.getAction() == KeyEvent.ACTION_DOWN && mSelectedColumn >= 0) {
+                    VerticalGridView gridView = mColumnViews.get(mSelectedColumn);
                     if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
                         int newPosition = gridView.getSelectedPosition() - 1;
                         if (newPosition >= 0) {
@@ -500,90 +499,82 @@
 
     private void updateColumnSize(VerticalGridView columnView) {
         ViewGroup.LayoutParams lp = columnView.getLayoutParams();
-        lp.height = (int) (getPickerItemHeightPixels() * (isExpanded() ?
-                getVisiblePickerItemsInExpand() : getVisiblePickerItems()));
+        lp.height = (int) (getPickerItemHeightPixels() * (isActivated() ?
+                getActivatedVisibleItemCount() : getVisibleItemCount()));
         columnView.setLayoutParams(lp);
     }
 
     /**
-     * Returns number of visible items showing in a column when it's expanded, it's 3 by default.
-     * @return Number of visible items showing in a column when it's expanded.
+     * Returns number of visible items showing in a column when it's activated.  The default value
+     * is 3.
+     * @return Number of visible items showing in a column when it's activated.
      */
-    public float getVisiblePickerItemsInExpand() {
-        return mVisibleItemsInExpand;
+    public float getActivatedVisibleItemCount() {
+        return mVisibleItemsActivated;
     }
 
     /**
-     * Change number of visible items showing in a column when it's expanded.
-     * @param visiblePickerItems Number of visible items showing in a column when it's expanded.
+     * Changes number of visible items showing in a column when it's activated.  The default value
+     * is 3.
+     * @param visiblePickerItems Number of visible items showing in a column when it's activated.
      */
-    public void setVisiblePickerItemsInExpand(float visiblePickerItems) {
+    public void setActivatedVisibleItemCount(float visiblePickerItems) {
         if (visiblePickerItems <= 0) {
             throw new IllegalArgumentException();
         }
-        if (mVisibleItemsInExpand != visiblePickerItems) {
-            mVisibleItemsInExpand = visiblePickerItems;
-            if (isExpanded()) {
+        if (mVisibleItemsActivated != visiblePickerItems) {
+            mVisibleItemsActivated = visiblePickerItems;
+            if (isActivated()) {
                 updateColumnSize();
             }
         }
     }
 
     /**
-     * Returns number of visible items showing in a column when it's not expanded, it's 1 by
-     * default.
-     * @return Number of visible items showing in a column when it's not expanded.
+     * Returns number of visible items showing in a column when it's not activated.  The default
+     * value is 1.
+     * @return Number of visible items showing in a column when it's not activated.
      */
-    public float getVisiblePickerItems() {
+    public float getVisibleItemCount() {
         return 1;
     }
 
     /**
-     * Change number of visible items showing in a column when it's not expanded, it's 1 by default.
-     * @param pickerItems Number of visible items showing in a column when it's not expanded.
+     * Changes number of visible items showing in a column when it's not activated.  The default
+     * value is 1.
+     * @param pickerItems Number of visible items showing in a column when it's not activated.
      */
-    public void setVisiblePickerItems(float pickerItems) {
+    public void setVisibleItemCount(float pickerItems) {
         if (pickerItems <= 0) {
             throw new IllegalArgumentException();
         }
         if (mVisibleItems != pickerItems) {
             mVisibleItems = pickerItems;
-            if (!isExpanded()) {
+            if (!isActivated()) {
                 updateColumnSize();
             }
         }
     }
 
-    /**
-     * Change expanded state of Picker, the height LayoutParams will be changed.
-     * @see #getVisiblePickerItemsInExpand()
-     * @see #getVisiblePickerItems()
-     * @param expanded New expanded state of Picker.
-     */
-    public void setExpanded(boolean expanded) {
-        if (mExpanded != expanded) {
-            mExpanded = expanded;
+    @Override
+    public void setActivated(boolean activated) {
+        if (activated != isActivated()) {
+            super.setActivated(activated);
             updateColumnSize();
+        } else {
+            super.setActivated(activated);
         }
     }
 
     /**
-     * Returns true if the Picker is currently expanded, false otherwise.
-     * @return True if the Picker is currently expanded, false otherwise.
-     */
-    public boolean isExpanded() {
-        return mExpanded;
-    }
-
-    /**
-     * Change current activated column.  Shows multiple items on activate column if Picker has
-     * focus. Show multiple items on all column if Picker has no focus (e.g. a Touchscreen
+     * Change current selected column.  Picker shows multiple items on selected column if Picker has
+     * focus.  Picker shows multiple items on all column if Picker has no focus (e.g. a Touchscreen
      * screen).
      * @param columnIndex Index of column to activate.
      */
-    public void setActiveColumn(int columnIndex) {
-        if (mActivatedColumn != columnIndex) {
-            mActivatedColumn = columnIndex;
+    public void setSelectedColumn(int columnIndex) {
+        if (mSelectedColumn != columnIndex) {
+            mSelectedColumn = columnIndex;
             for (int i = 0; i < mColumnViews.size(); i++) {
                 updateColumnAlpha(i, true);
             }
@@ -594,35 +585,8 @@
      * Get current activated column index.
      * @return Current activated column index.
      */
-    public int getActiveColumn() {
-        return mActivatedColumn;
-    }
-
-    /**
-     * Enable or disable toggle on click when Picker has focus.
-     * @param toggleExpandOnClick True to enable toggle on click when Picker has focus, false
-     * otherwise.
-     */
-    public void setToggleExpandOnClick(boolean toggleExpandOnClick) {
-        mToggleExpandOnClick = toggleExpandOnClick;
-    }
-
-    /**
-     * Returns true if toggle on click is enabled when Picker has focus, false otherwise.
-     * @return True if toggle on click is enabled when Picker has focus, false otherwise.
-     */
-    public boolean isToggleExpandOnClick() {
-        return mToggleExpandOnClick;
-    }
-
-    @Override
-    public boolean performClick() {
-        if (isFocused() && isToggleExpandOnClick()) {
-            setExpanded(!isExpanded());
-            super.performClick();
-            return true;
-        }
-        return super.performClick();
+    public int getSelectedColumn() {
+        return mSelectedColumn;
     }
 
 }
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/picker/PickerColumn.java b/v17/leanback/src/android/support/v17/leanback/widget/picker/PickerColumn.java
index c4c0c57..f2a2c5a 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/picker/PickerColumn.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/picker/PickerColumn.java
@@ -14,54 +14,40 @@
 
 package android.support.v17.leanback.widget.picker;
 
-import android.os.Parcel;
-import android.os.Parcelable;
-
 /**
  * Picker column class used by {@link Picker}, defines a contiguous value ranges and associated
  * labels.  A PickerColumn has a minValue and maxValue to choose between.  The Picker column has
  * a current value.
- * The labels can be dynamically generated from value by {@link #setValueLabelFormat(String)} or
- * a list of static labels set by {@link #setValueStaticLabels(String[])}.
+ * The labels can be dynamically generated from value by {@link #setEntryFormat(String)} or
+ * a list of static labels set by {@link #setEntries(CharSequence[])}.
  */
-public class PickerColumn implements Parcelable {
+public class PickerColumn {
 
     private int mCurrentValue;
     private int mMinValue;
     private int mMaxValue;
-    private String[] mStaticLabels;
-    private String mValueFormat;
+    private CharSequence[] mStaticEntrys;
+    private String mEntryFormat;
 
     public PickerColumn() {
     }
 
-    public PickerColumn(Parcel source) {
-        mValueFormat = source.readString();
-        int count = source.readInt();
-        if (count > 0) {
-            mStaticLabels = new String[count];
-            source.readStringArray(mStaticLabels);
-        }
-        mCurrentValue = source.readInt();
-        mMinValue = source.readInt();
-        mMaxValue = source.readInt();
-    }
-
     /**
-     * Set string format to display label for value, e.g. "%02d".  The string format is only
-     * used when {@link #setValueStaticLabels(String[])} is not called.
-     * @param valueFormat String format to display label for value.
+     * Set string format to display label for value. For example "%02d".
+     * {@link #setEntries(CharSequence[])} overrides the format.
+     *
+     * @param valueFormat String format to display label for value between minValue and maxValue.
      */
-    public void setValueLabelFormat(String valueFormat) {
-        mValueFormat = valueFormat;
+    public void setEntryFormat(String valueFormat) {
+        mEntryFormat = valueFormat;
     }
 
     /**
-     * Return string format to display label for value, e.g. "%02d".
+     * Return string format to display label for value.  For example "%02d".
      * @return String format to display label for value.
      */
-    public String getValueLabelFormat() {
-        return mValueFormat;
+    public String getEntryFormat() {
+        return mEntryFormat;
     }
 
     /**
@@ -69,21 +55,22 @@
      * labels[labels.length - 1].
      * @param labels Static labels for each value between minValue and maxValue.
      */
-    public void setValueStaticLabels(String[] labels) {
-        mStaticLabels = labels;
+    public void setEntries(CharSequence[] labels) {
+        mStaticEntrys = labels;
     }
 
     /**
-     * Get a label for value.  The label can be static ({@link #setValueStaticLabels(String[])} or
-     * dynamically generated (@link {@link #setValueLabelFormat(String)}.
+     * Get a label for value. The label can be static ({@link #setEntries(CharSequence[])}
+     * or dynamically generated (@link {@link #setEntryFormat(String)}.
+     * 
      * @param value Value between minValue and maxValue.
      * @return Label for the value.
      */
-    public String getValueLabelAt(int value) {
-        if (mStaticLabels == null) {
-            return String.format(mValueFormat, value);
+    public CharSequence getEntryAt(int value) {
+        if (mStaticEntrys == null) {
+            return String.format(mEntryFormat, value);
         }
-        return mStaticLabels[value];
+        return mStaticEntrys[value];
     }
 
     /**
@@ -96,97 +83,49 @@
 
     /**
      * Sets current value of the Column.
-     * @return True if current value has changed.
      */
-    public boolean setCurrentValue(int value) {
-        if (mCurrentValue != value) {
-            mCurrentValue = value;
-            return true;
-        }
-        return false;
+    public void setCurrentValue(int value) {
+        mCurrentValue = value;
     }
 
     /**
-     * Get total items count between minValue(inclusive) and maxValue (inclusive).
-     * @return Total items count between minValue(inclusive) and maxValue (inclusive).
+     * Get total items count between minValue and maxValue.
+     * @return Total items count between minValue and maxValue.
      */
-    public int getItemsCount() {
+    public int getItemCount() {
         return mMaxValue - mMinValue + 1;
     }
 
     /**
-     * Returns minimal value (inclusive) of the Column.
-     * @return Minimal value (inclusive) of the Column.
+     * Returns minimal value of the Column.
+     * @return Minimal value of the Column.
      */
     public int getMinValue() {
         return mMinValue;
     }
 
     /**
-     * Returns maximum value (inclusive) of the Column.
-     * @return Maximum value (inclusive) of the Column.
+     * Returns maximum value of the Column.
+     * @return Maximum value of the Column.
      */
     public int getMaxValue() {
         return mMaxValue;
     }
 
     /**
-     * Sets minimal value (inclusive) of the Column.
+     * Sets minimal value of the Column.
      * @param minValue New minimal value to set.
-     * @return True if minimal value changes.
      */
-    public boolean setMinValue(int minValue) {
-        if (minValue != mMinValue) {
-            mMinValue = minValue;
-            return true;
-        }
-        return false;
+    public void setMinValue(int minValue) {
+        mMinValue = minValue;
     }
 
     /**
-     * Sets maximum value (inclusive) of the Column.
+     * Sets maximum value of the Column.
      * @param maxValue New maximum value to set.
-     * @return True if maximum value changes.
      */
-    public boolean setMaxValue(int maxValue) {
-        if (maxValue != mMaxValue) {
-            mMaxValue = maxValue;
-            return true;
-        }
-        return false;
-    }
-
-    public static Parcelable.Creator<PickerColumn>
-            CREATOR = new Parcelable.Creator<PickerColumn>() {
-
-                @Override
-                public PickerColumn createFromParcel(Parcel source) {
-                    return new PickerColumn(source);
-                }
-
-                @Override
-                public PickerColumn[] newArray(int size) {
-                    return new PickerColumn[size];
-                }
-            };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeString(mValueFormat);
-        if (mStaticLabels != null) {
-            dest.writeInt(mStaticLabels.length);
-            dest.writeStringArray(mStaticLabels);
-        } else {
-            dest.writeInt(0);
-        }
-        dest.writeInt(mCurrentValue);
-        dest.writeInt(mMinValue);
-        dest.writeInt(mMaxValue);
+    public void setMaxValue(int maxValue) {
+        mMaxValue = maxValue;
     }
 
 }
diff --git a/v4/api/current.txt b/v4/api/current.txt
index c9a72b1..15e7868 100644
--- a/v4/api/current.txt
+++ b/v4/api/current.txt
@@ -1106,8 +1106,8 @@
     method public static int XYZToColor(double, double, double);
     method public static void XYZToLAB(double, double, double, double[]);
     method public static int blendARGB(int, int, float);
-    method public static void blendHSL(float[], float[], float[], float);
-    method public static void blendLAB(double[], double[], double[], double);
+    method public static void blendHSL(float[], float[], float, float[]);
+    method public static void blendLAB(double[], double[], double, double[]);
     method public static double calculateContrast(int, int);
     method public static double calculateLuminance(int);
     method public static int calculateMinimumAlpha(int, int, float);
diff --git a/v4/java/android/support/v4/graphics/ColorUtils.java b/v4/java/android/support/v4/graphics/ColorUtils.java
index 2a3074e..85768f6 100644
--- a/v4/java/android/support/v4/graphics/ColorUtils.java
+++ b/v4/java/android/support/v4/graphics/ColorUtils.java
@@ -22,7 +22,6 @@
 import android.support.annotation.IntRange;
 import android.support.annotation.NonNull;
 import android.support.annotation.VisibleForTesting;
-import android.util.TypedValue;
 
 /**
  * A set of color-related utility methods, building upon those available in {@code Color}.
@@ -75,11 +74,7 @@
      */
     @FloatRange(from = 0.0, to = 1.0)
     public static double calculateLuminance(@ColorInt int color) {
-        double[] result = TEMP_ARRAY.get();
-        if (result == null) {
-            result = new double[3];
-            TEMP_ARRAY.set(result);
-        }
+        final double[] result = getTempDouble3Array();
         colorToXYZ(color, result);
         // Luminance is the Y component
         return result[1] / 100;
@@ -114,10 +109,10 @@
      * have a contrast value of at least {@code minContrastRatio} when compared to
      * {@code background}.
      *
-     * @param foreground       the foreground color.
-     * @param background       the background color. Should be opaque.
-     * @param minContrastRatio the minimum contrast ratio.
-     * @return the alpha value in the range 0-255, or -1 if no value could be calculated.
+     * @param foreground       the foreground color
+     * @param background       the opaque background color
+     * @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(@ColorInt int foreground, @ColorInt int background,
             float minContrastRatio) {
@@ -162,19 +157,19 @@
     /**
      * Convert RGB components to HSL (hue-saturation-lightness).
      * <ul>
-     * <li>hsl[0] is Hue [0 .. 360)</li>
-     * <li>hsl[1] is Saturation [0...1]</li>
-     * <li>hsl[2] is Lightness [0...1]</li>
+     * <li>outHsl[0] is Hue [0 .. 360)</li>
+     * <li>outHsl[1] is Saturation [0...1]</li>
+     * <li>outHsl[2] is Lightness [0...1]</li>
      * </ul>
      *
-     * @param r   red component value [0..255]
-     * @param g   green component value [0..255]
-     * @param b   blue component value [0..255]
-     * @param hsl 3 element array which holds the resulting HSL components.
+     * @param r      red component value [0..255]
+     * @param g      green component value [0..255]
+     * @param b      blue component value [0..255]
+     * @param outHsl 3-element array which holds the resulting HSL components
      */
     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) {
+            @NonNull float[] outHsl) {
         final float rf = r / 255f;
         final float gf = g / 255f;
         final float bf = b / 255f;
@@ -206,24 +201,24 @@
             h += 360f;
         }
 
-        hsl[0] = constrain(h, 0f, 360f);
-        hsl[1] = constrain(s, 0f, 1f);
-        hsl[2] = constrain(l, 0f, 1f);
+        outHsl[0] = constrain(h, 0f, 360f);
+        outHsl[1] = constrain(s, 0f, 1f);
+        outHsl[2] = constrain(l, 0f, 1f);
     }
 
     /**
      * Convert the ARGB color to its HSL (hue-saturation-lightness) components.
      * <ul>
-     * <li>hsl[0] is Hue [0 .. 360)</li>
-     * <li>hsl[1] is Saturation [0...1]</li>
-     * <li>hsl[2] is Lightness [0...1]</li>
+     * <li>outHsl[0] is Hue [0 .. 360)</li>
+     * <li>outHsl[1] is Saturation [0...1]</li>
+     * <li>outHsl[2] is Lightness [0...1]</li>
      * </ul>
      *
-     * @param color the ARGB color to convert. The alpha component is ignored.
-     * @param hsl 3 element array which holds the resulting HSL components.
+     * @param color  the ARGB color to convert. The alpha component is ignored
+     * @param outHsl 3-element array which holds the resulting HSL components
      */
-    public static void colorToHSL(@ColorInt int color, @NonNull float[] hsl) {
-        RGBToHSL(Color.red(color), Color.green(color), Color.blue(color), hsl);
+    public static void colorToHSL(@ColorInt int color, @NonNull float[] outHsl) {
+        RGBToHSL(Color.red(color), Color.green(color), Color.blue(color), outHsl);
     }
 
     /**
@@ -235,7 +230,7 @@
      * </ul>
      * If hsv values are out of range, they are pinned.
      *
-     * @param hsl 3 element array which holds the input HSL components.
+     * @param hsl 3-element array which holds the input HSL components
      * @return the resulting RGB color
      */
     @ColorInt
@@ -308,35 +303,35 @@
     /**
      * Convert the ARGB color to its CIE Lab representative components.
      *
-     * @param color the ARGB color to convert. The alpha component is ignored.
-     * @param result 3 element array which holds the resulting LAB components.
+     * @param color  the ARGB color to convert. The alpha component is ignored
+     * @param outLab 3-element array which holds the resulting LAB components
      */
-    public static void colorToLAB(@ColorInt int color, @NonNull double[] result) {
-        RGBToLAB(Color.red(color), Color.green(color), Color.blue(color), result);
+    public static void colorToLAB(@ColorInt int color, @NonNull double[] outLab) {
+        RGBToLAB(Color.red(color), Color.green(color), Color.blue(color), outLab);
     }
 
     /**
      * Convert RGB components to its CIE Lab representative components.
      *
      * <ul>
-     * <li>result[0] is L [0 ...1)</li>
-     * <li>result[1] is a [-128...127)</li>
-     * <li>result[2] is b [-128...127)</li>
+     * <li>outLab[0] is L [0 ...1)</li>
+     * <li>outLab[1] is a [-128...127)</li>
+     * <li>outLab[2] is b [-128...127)</li>
      * </ul>
      *
-     * @param r   red component value [0..255)
-     * @param g   green component value [0..255)
-     * @param b   blue component value [0..255)
-     * @param result 3 element array which holds the resulting LAB components.
+     * @param r      red component value [0..255]
+     * @param g      green component value [0..255]
+     * @param b      blue component value [0..255]
+     * @param outLab 3-element array which holds the resulting LAB components
      */
     public static void RGBToLAB(@IntRange(from = 0x0, to = 0xFF) int r,
             @IntRange(from = 0x0, to = 0xFF) int g, @IntRange(from = 0x0, to = 0xFF) int b,
-            @NonNull double[] result) {
+            @NonNull double[] outLab) {
         // First we convert RGB to XYZ
-        RGBToXYZ(r, g, b, result);
-        // result now contains XYZ
-        XYZToLAB(result[0], result[1], result[2], result);
-        // result now contains LAB representation
+        RGBToXYZ(r, g, b, outLab);
+        // outLab now contains XYZ
+        XYZToLAB(outLab[0], outLab[1], outLab[2], outLab);
+        // outLab now contains LAB representation
     }
 
     /**
@@ -346,16 +341,16 @@
      * 2° Standard Observer (1931).</p>
      *
      * <ul>
-     * <li>result[0] is X [0 ...95.047)</li>
-     * <li>result[1] is Y [0...100)</li>
-     * <li>result[2] is Z [0...108.883)</li>
+     * <li>outXyz[0] is X [0 ...95.047)</li>
+     * <li>outXyz[1] is Y [0...100)</li>
+     * <li>outXyz[2] is Z [0...108.883)</li>
      * </ul>
      *
-     * @param color the ARGB color to convert. The alpha component is ignored.
-     * @param result 3 element array which holds the resulting LAB components.
+     * @param color  the ARGB color to convert. The alpha component is ignored
+     * @param outXyz 3-element array which holds the resulting LAB components
      */
-    public static void colorToXYZ(@ColorInt int color, @NonNull double[] result) {
-        RGBToXYZ(Color.red(color), Color.green(color), Color.blue(color), result);
+    public static void colorToXYZ(@ColorInt int color, @NonNull double[] outXyz) {
+        RGBToXYZ(Color.red(color), Color.green(color), Color.blue(color), outXyz);
     }
 
     /**
@@ -365,21 +360,21 @@
      * 2° Standard Observer (1931).</p>
      *
      * <ul>
-     * <li>result[0] is X [0 ...95.047)</li>
-     * <li>result[1] is Y [0...100)</li>
-     * <li>result[2] is Z [0...108.883)</li>
+     * <li>outXyz[0] is X [0 ...95.047)</li>
+     * <li>outXyz[1] is Y [0...100)</li>
+     * <li>outXyz[2] is Z [0...108.883)</li>
      * </ul>
      *
-     * @param r   red component value [0..255)
-     * @param g   green component value [0..255)
-     * @param b   blue component value [0..255)
-     * @param result 3 element array which holds the resulting XYZ components.
+     * @param r      red component value [0..255]
+     * @param g      green component value [0..255]
+     * @param b      blue component value [0..255]
+     * @param outXyz 3-element array which holds the resulting XYZ components
      */
     public static void RGBToXYZ(@IntRange(from = 0x0, to = 0xFF) int r,
             @IntRange(from = 0x0, to = 0xFF) int g, @IntRange(from = 0x0, to = 0xFF) int b,
-            @NonNull double[] result) {
-        if (result.length != 3) {
-            throw new IllegalArgumentException("result must have a length of 3.");
+            @NonNull double[] outXyz) {
+        if (outXyz.length != 3) {
+            throw new IllegalArgumentException("outXyz must have a length of 3.");
         }
 
         double sr = r / 255.0;
@@ -389,9 +384,9 @@
         double sb = b / 255.0;
         sb = sb < 0.04045 ? sb / 12.92 : Math.pow((sb + 0.055) / 1.055, 2.4);
 
-        result[0] = 100 * (sr * 0.4124 + sg * 0.3576 + sb * 0.1805);
-        result[1] = 100 * (sr * 0.2126 + sg * 0.7152 + sb * 0.0722);
-        result[2] = 100 * (sr * 0.0193 + sg * 0.1192 + sb * 0.9505);
+        outXyz[0] = 100 * (sr * 0.4124 + sg * 0.3576 + sb * 0.1805);
+        outXyz[1] = 100 * (sr * 0.2126 + sg * 0.7152 + sb * 0.0722);
+        outXyz[2] = 100 * (sr * 0.0193 + sg * 0.1192 + sb * 0.9505);
     }
 
     /**
@@ -401,29 +396,29 @@
      * 2° Standard Observer (1931).</p>
      *
      * <ul>
-     * <li>result[0] is L [0 ...1)</li>
-     * <li>result[1] is a [-128...127)</li>
-     * <li>result[2] is b [-128...127)</li>
+     * <li>outLab[0] is L [0 ...1)</li>
+     * <li>outLab[1] is a [-128...127)</li>
+     * <li>outLab[2] is b [-128...127)</li>
      * </ul>
      *
-     * @param x X component value [0...95.047)
-     * @param y Y component value [0...100)
-     * @param z Z component value [0...108.883)
-     * @param result 3 element array which holds the resulting Lab components.
+     * @param x      X component value [0...95.047)
+     * @param y      Y component value [0...100)
+     * @param z      Z component value [0...108.883)
+     * @param outLab 3-element array which holds the resulting Lab components
      */
     public static void XYZToLAB(@FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_X) double x,
             @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Y) double y,
             @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Z) double z,
-            @NonNull double[] result) {
-        if (result.length != 3) {
-            throw new IllegalArgumentException("result must have a length of 3.");
+            @NonNull double[] outLab) {
+        if (outLab.length != 3) {
+            throw new IllegalArgumentException("outLab must have a length of 3.");
         }
         x = pivotXyzComponent(x / XYZ_WHITE_REFERENCE_X);
         y = pivotXyzComponent(y / XYZ_WHITE_REFERENCE_Y);
         z = pivotXyzComponent(z / XYZ_WHITE_REFERENCE_Z);
-        result[0] = Math.max(0, 116 * y - 16);
-        result[1] = 500 * (x - y);
-        result[2] = 200 * (y - z);
+        outLab[0] = Math.max(0, 116 * y - 16);
+        outLab[1] = 500 * (x - y);
+        outLab[2] = 200 * (y - z);
     }
 
     /**
@@ -433,20 +428,20 @@
      * 2° Standard Observer (1931).</p>
      *
      * <ul>
-     * <li>result[0] is X [0 ...95.047)</li>
-     * <li>result[1] is Y [0...100)</li>
-     * <li>result[2] is Z [0...108.883)</li>
+     * <li>outXyz[0] is X [0 ...95.047)</li>
+     * <li>outXyz[1] is Y [0...100)</li>
+     * <li>outXyz[2] is Z [0...108.883)</li>
      * </ul>
      *
-     * @param l L component value [0...100)
-     * @param a A component value [-128...127)
-     * @param b B component value [-128...127)
-     * @param result 3 element array which holds the resulting XYZ components.
+     * @param l      L component value [0...100)
+     * @param a      A component value [-128...127)
+     * @param b      B component value [-128...127)
+     * @param outXyz 3-element array which holds the resulting XYZ components
      */
     public static void LABToXYZ(@FloatRange(from = 0f, to = 100) final double l,
             @FloatRange(from = -128, to = 127) final double a,
             @FloatRange(from = -128, to = 127) final double b,
-            @NonNull double[] result) {
+            @NonNull double[] outXyz) {
         final double fy = (l + 16) / 116;
         final double fx = a / 500 + fy;
         final double fz = fy - b / 200;
@@ -458,9 +453,9 @@
         tmp = Math.pow(fz, 3);
         final double zr = tmp > XYZ_EPSILON ? tmp : (116 * fz - 16) / XYZ_KAPPA;
 
-        result[0] = xr * XYZ_WHITE_REFERENCE_X;
-        result[1] = yr * XYZ_WHITE_REFERENCE_Y;
-        result[2] = zr * XYZ_WHITE_REFERENCE_Z;
+        outXyz[0] = xr * XYZ_WHITE_REFERENCE_X;
+        outXyz[1] = yr * XYZ_WHITE_REFERENCE_Y;
+        outXyz[2] = zr * XYZ_WHITE_REFERENCE_Z;
     }
 
     /**
@@ -495,16 +490,16 @@
     /**
      * Converts a color from CIE Lab to its RGB representation.
      *
-     * @param l L component value [0...100)
-     * @param a A component value [-128...127)
-     * @param b B component value [-128...127)
+     * @param l L component value [0...100]
+     * @param a A component value [-128...127]
+     * @param b B component value [-128...127]
      * @return int containing the RGB representation
      */
     @ColorInt
     public static int LABToColor(@FloatRange(from = 0f, to = 100) final double l,
             @FloatRange(from = -128, to = 127) final double a,
             @FloatRange(from = -128, to = 127) final double b) {
-        final double[] result = new double[3];
+        final double[] result = getTempDouble3Array();
         LABToXYZ(l, a, b, result);
         return XYZToColor(result[0], result[1], result[2]);
     }
@@ -535,8 +530,12 @@
     /**
      * Blend between two ARGB colors using the given ratio.
      *
-     * @param ratio of which to blend. 0.0 will return {@code color1}, 0.5 will give an even blend,
-     *              1.0 will return {@code color2}.
+     * <p>A blend ratio of 0.0 will result in {@code color1}, 0.5 will give an even blend,
+     * 1.0 will result in {@code color2}.</p>
+     *
+     * @param color1 the first ARGB color
+     * @param color2 the second ARGB color
+     * @param ratio  the blend ratio of {@code color1} to {@code color2}
      */
     @ColorInt
     public static int blendARGB(@ColorInt int color1, @ColorInt int color2,
@@ -553,43 +552,46 @@
      * Blend between {@code hsl1} and {@code hsl2} using the given ratio. This will interpolate
      * the hue using the shortest angle.
      *
-     * @param hsl1 3 element array which holds the first HSL color.
-     * @param hsl2 3 element array which holds the second HSL color.
-     * @param result 3 element array which holds the resulting HSL components.
-     * @param ratio of which to blend. 0.0 will result in {@code hsl1},
-     *              0.5 will give an even blend, 1.0 will return {@code hsl2}.
+     * <p>A blend ratio of 0.0 will result in {@code hsl1}, 0.5 will give an even blend,
+     * 1.0 will result in {@code hsl2}.</p>
+     *
+     * @param hsl1      3-element array which holds the first HSL color
+     * @param hsl2      3-element array which holds the second HSL color
+     * @param ratio     the blend ratio of {@code hsl1} to {@code hsl2}
+     * @param outResult 3-element array which holds the resulting HSL components
      */
     public static void blendHSL(@NonNull float[] hsl1, @NonNull float[] hsl2,
-            @NonNull float[] result, @FloatRange(from = 0.0, to = 1.0) float ratio) {
-        if (result.length != 3) {
+            @FloatRange(from = 0.0, to = 1.0) float ratio, @NonNull float[] outResult) {
+        if (outResult.length != 3) {
             throw new IllegalArgumentException("result must have a length of 3.");
         }
         final float inverseRatio = 1 - ratio;
         // Since hue is circular we will need to interpolate carefully
-        result[0] = circularInterpolate(hsl1[0], hsl2[0], ratio);
-        result[1] = hsl1[1] * inverseRatio + hsl2[1] * ratio;
-        result[2] = hsl1[2] * inverseRatio + hsl2[2] * ratio;
+        outResult[0] = circularInterpolate(hsl1[0], hsl2[0], ratio);
+        outResult[1] = hsl1[1] * inverseRatio + hsl2[1] * ratio;
+        outResult[2] = hsl1[2] * inverseRatio + hsl2[2] * ratio;
     }
 
     /**
      * Blend between two CIE-LAB colors using the given ratio.
      *
-     * @param lab1 3 element array which holds the first LAB color.
-     * @param lab2 3 element array which holds the second LAB color.
-     * @param result 3 element array which holds the resulting LAB components.
-     * @param ratio of which to blend. 0.0 will result in {@code lab1}, 0.5 will give an even blend,
-     *              1.0 will return {@code lab2}.
+     * <p>A blend ratio of 0.0 will result in {@code lab1}, 0.5 will give an even blend,
+     * 1.0 will result in {@code lab2}.</p>
+     *
+     * @param lab1      3-element array which holds the first LAB color
+     * @param lab2      3-element array which holds the second LAB color
+     * @param ratio     the blend ratio of {@code lab1} to {@code lab2}
+     * @param outResult 3-element array which holds the resulting LAB components
      */
-    public static void blendLAB(@NonNull double[] lab1,
-            @NonNull double[] lab2, @NonNull double[] result,
-            @FloatRange(from = 0.0, to = 1.0) double ratio) {
-        if (result.length != 3) {
-            throw new IllegalArgumentException("result must have a length of 3.");
+    public static void blendLAB(@NonNull double[] lab1, @NonNull double[] lab2,
+            @FloatRange(from = 0.0, to = 1.0) double ratio, @NonNull double[] outResult) {
+        if (outResult.length != 3) {
+            throw new IllegalArgumentException("outResult must have a length of 3.");
         }
         final double inverseRatio = 1 - ratio;
-        result[0] = lab1[0] * inverseRatio + lab2[0] * ratio;
-        result[1] = lab1[1] * inverseRatio + lab2[1] * ratio;
-        result[2] = lab1[2] * inverseRatio + lab2[2] * ratio;
+        outResult[0] = lab1[0] * inverseRatio + lab2[0] * ratio;
+        outResult[1] = lab1[1] * inverseRatio + lab2[1] * ratio;
+        outResult[2] = lab1[2] * inverseRatio + lab2[2] * ratio;
     }
 
     @VisibleForTesting
@@ -604,4 +606,13 @@
         return (a + ((b - a) * f)) % 360;
     }
 
+    private static double[] getTempDouble3Array() {
+        double[] result = TEMP_ARRAY.get();
+        if (result == null) {
+            result = new double[3];
+            TEMP_ARRAY.set(result);
+        }
+        return result;
+    }
+
 }
diff --git a/v7/appcompat/res/values-ldrtl-v23/styles_base.xml b/v7/appcompat/res/values-ldrtl-v23/styles_base.xml
deleted file mode 100644
index cba56bd..0000000
--- a/v7/appcompat/res/values-ldrtl-v23/styles_base.xml
+++ /dev/null
@@ -1,22 +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>
-
-    <style name="Base.Widget.AppCompat.Spinner.Underlined" parent="android:Widget.Material.Spinner.Underlined" />
-
-</resources>
diff --git a/v7/appcompat/res/values-v23/styles_base.xml b/v7/appcompat/res/values-v23/styles_base.xml
index 3b0e55c..56563c7 100644
--- a/v7/appcompat/res/values-v23/styles_base.xml
+++ b/v7/appcompat/res/values-v23/styles_base.xml
@@ -23,4 +23,6 @@
 
     <style name="Base.Widget.AppCompat.RatingBar.Small" parent="android:Widget.Material.RatingBar.Small" />
 
+    <style name="Base.Widget.AppCompat.Spinner.Underlined" parent="android:Widget.Material.Spinner.Underlined" />
+
 </resources>