Merge "MediaRouter: Make MediaControllerCompat.playFromUri() work" into mnc-ub-dev
diff --git a/build.gradle b/build.gradle
index 7fbe70a..fe0adb2 100644
--- a/build.gradle
+++ b/build.gradle
@@ -10,7 +10,7 @@
 }
 
 ext.supportVersion = '23.1.0'
-ext.extraVersion = 23
+ext.extraVersion = 24
 ext.supportRepoOut = ''
 ext.buildToolsVersion = '22.1.0'
 ext.buildNumber = Integer.toString(ext.extraVersion)
diff --git a/scripts/support-deps-license.sh b/scripts/support-deps-license.sh
new file mode 100755
index 0000000..55efac6
--- /dev/null
+++ b/scripts/support-deps-license.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+#
+#  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.
+#
+
+#
+# This needs to be ran from the root folder in the Android source tree
+#
+
+function parentdirname() {
+  FULL_PATH=`readlink -f $1`
+  echo `dirname $FULL_PATH`
+}
+
+function rundeps() {
+  LIB_PATH=$1
+  LIB_PARENT_PATH=`parentdirname $LIB_PATH`
+  OUTPUT_FILE=`basename $LIB_PARENT_PATH`-`basename $LIB_PATH`.log
+  make deps-license PROJ_PATH=$LIB_PATH DEP_PATH=frameworks/support > $OUTPUT_FILE
+}
+
+rundeps frameworks/support/customtabs
+rundeps frameworks/support/design
+rundeps frameworks/support/percent
+rundeps frameworks/support/recommendation
+rundeps frameworks/support/v4
+rundeps frameworks/support/v7/appcompat
+rundeps frameworks/support/v7/cardview
+rundeps frameworks/support/v7/mediarouter
+rundeps frameworks/support/v7/palette
+rundeps frameworks/support/v7/gridlayout
+rundeps frameworks/support/v7/preference
+rundeps frameworks/support/v7/recyclerview
+rundeps frameworks/support/v13
+rundeps frameworks/support/v14/preference
+rundeps frameworks/support/v17/leanback
+rundeps frameworks/support/v17/preference-leanback
diff --git a/v17/leanback/common/android/support/v17/leanback/transition/TransitionListener.java b/v17/leanback/common/android/support/v17/leanback/transition/TransitionListener.java
index 80f05ed..6a4056e 100644
--- a/v17/leanback/common/android/support/v17/leanback/transition/TransitionListener.java
+++ b/v17/leanback/common/android/support/v17/leanback/transition/TransitionListener.java
@@ -19,10 +19,20 @@
  */
 public class TransitionListener {
 
+    protected Object mImpl;
+
     public void onTransitionStart(Object transition) {
     }
 
     public void onTransitionEnd(Object transition) {
     }
 
+    public void onTransitionCancel(Object transition) {
+    }
+
+    public void onTransitionPause(Object transition) {
+    }
+
+    public void onTransitionResume(Object transition) {
+    }
 }
diff --git a/v17/leanback/kitkat/android/support/v17/leanback/transition/TransitionHelperKitkat.java b/v17/leanback/kitkat/android/support/v17/leanback/transition/TransitionHelperKitkat.java
index b4b6abe..221b84a 100644
--- a/v17/leanback/kitkat/android/support/v17/leanback/transition/TransitionHelperKitkat.java
+++ b/v17/leanback/kitkat/android/support/v17/leanback/transition/TransitionHelperKitkat.java
@@ -185,9 +185,12 @@
         ((Transition) transition).addTarget(targetView);
     }
 
-    static void setTransitionListener(Object transition, final TransitionListener listener) {
+    static void addTransitionListener(Object transition, final TransitionListener listener) {
+        if (listener == null) {
+            return;
+        }
         Transition t = (Transition) transition;
-        t.addListener(new Transition.TransitionListener() {
+        listener.mImpl = new Transition.TransitionListener() {
 
             @Override
             public void onTransitionStart(Transition transition) {
@@ -196,10 +199,12 @@
 
             @Override
             public void onTransitionResume(Transition transition) {
+                listener.onTransitionResume(transition);
             }
 
             @Override
             public void onTransitionPause(Transition transition) {
+                listener.onTransitionPause(transition);
             }
 
             @Override
@@ -209,8 +214,19 @@
 
             @Override
             public void onTransitionCancel(Transition transition) {
+                listener.onTransitionCancel(transition);
             }
-        });
+        };
+        t.addListener((Transition.TransitionListener) listener.mImpl);
+    }
+
+    static void removeTransitionListener(Object transition, final TransitionListener listener) {
+        if (listener == null || listener.mImpl == null) {
+            return;
+        }
+        Transition t = (Transition) transition;
+        t.removeListener((Transition.TransitionListener) listener.mImpl);
+        listener.mImpl = null;
     }
 
     static void runTransition(Object scene, Object transition) {
diff --git a/v17/leanback/src/android/support/v17/leanback/app/BaseFragment.java b/v17/leanback/src/android/support/v17/leanback/app/BaseFragment.java
index 5b2deac..c878a86 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/BaseFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/BaseFragment.java
@@ -30,8 +30,6 @@
     private boolean mEntranceTransitionPreparePending = false;
     private Object mEntranceTransition;
 
-    static TransitionHelper sTransitionHelper = TransitionHelper.getInstance();
-
     @Override
     public void onViewCreated(View view, Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
@@ -176,7 +174,7 @@
         if (mEntranceTransition == null) {
             return;
         }
-        sTransitionHelper.setTransitionListener(mEntranceTransition, new TransitionListener() {
+        TransitionHelper.addTransitionListener(mEntranceTransition, new TransitionListener() {
             @Override
             public void onTransitionEnd(Object transition) {
                 mEntranceTransition = null;
diff --git a/v17/leanback/src/android/support/v17/leanback/app/BaseSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/BaseSupportFragment.java
index a72bb5b..b9c7d58 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/BaseSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/BaseSupportFragment.java
@@ -32,8 +32,6 @@
     private boolean mEntranceTransitionPreparePending = false;
     private Object mEntranceTransition;
 
-    static TransitionHelper sTransitionHelper = TransitionHelper.getInstance();
-
     @Override
     public void onViewCreated(View view, Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
@@ -178,7 +176,7 @@
         if (mEntranceTransition == null) {
             return;
         }
-        sTransitionHelper.setTransitionListener(mEntranceTransition, new TransitionListener() {
+        TransitionHelper.addTransitionListener(mEntranceTransition, new TransitionListener() {
             @Override
             public void onTransitionEnd(Object transition) {
                 mEntranceTransition = null;
diff --git a/v17/leanback/src/android/support/v17/leanback/app/BrowseFragment.java b/v17/leanback/src/android/support/v17/leanback/app/BrowseFragment.java
index 7e8f02f..8c417a4 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/BrowseFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/BrowseFragment.java
@@ -425,7 +425,7 @@
                 if (mBrowseTransitionListener != null) {
                     mBrowseTransitionListener.onHeadersTransitionStart(withHeaders);
                 }
-                sTransitionHelper.runTransition(withHeaders ? mSceneWithHeaders : mSceneWithoutHeaders,
+                TransitionHelper.runTransition(withHeaders ? mSceneWithHeaders : mSceneWithoutHeaders,
                         mHeadersTransition);
                 if (mHeadersBackStackEnabled) {
                     if (!withHeaders) {
@@ -622,19 +622,19 @@
             mHeadersFragment.setBackgroundColor(mBrandColor);
         }
 
-        mSceneWithHeaders = sTransitionHelper.createScene(mBrowseFrame, new Runnable() {
+        mSceneWithHeaders = TransitionHelper.createScene(mBrowseFrame, new Runnable() {
             @Override
             public void run() {
                 showHeaders(true);
             }
         });
-        mSceneWithoutHeaders =  sTransitionHelper.createScene(mBrowseFrame, new Runnable() {
+        mSceneWithoutHeaders =  TransitionHelper.createScene(mBrowseFrame, new Runnable() {
             @Override
             public void run() {
                 showHeaders(false);
             }
         });
-        mSceneAfterEntranceTransition = sTransitionHelper.createScene(mBrowseFrame, new Runnable() {
+        mSceneAfterEntranceTransition = TransitionHelper.createScene(mBrowseFrame, new Runnable() {
             @Override
             public void run() {
                 setEntranceTransitionEndState();
@@ -644,11 +644,11 @@
     }
 
     private void createHeadersTransition() {
-        mHeadersTransition = sTransitionHelper.loadTransition(getActivity(),
+        mHeadersTransition = TransitionHelper.loadTransition(getActivity(),
                 mShowingHeaders ?
                 R.transition.lb_browse_headers_in : R.transition.lb_browse_headers_out);
 
-        sTransitionHelper.setTransitionListener(mHeadersTransition, new TransitionListener() {
+        TransitionHelper.addTransitionListener(mHeadersTransition, new TransitionListener() {
             @Override
             public void onTransitionStart(Object transition) {
             }
@@ -891,14 +891,13 @@
 
     @Override
     protected Object createEntranceTransition() {
-        return sTransitionHelper.loadTransition(getActivity(),
+        return TransitionHelper.loadTransition(getActivity(),
                 R.transition.lb_browse_entrance_transition);
     }
 
     @Override
     protected void runEntranceTransition(Object entranceTransition) {
-        sTransitionHelper.runTransition(mSceneAfterEntranceTransition,
-                entranceTransition);
+        TransitionHelper.runTransition(mSceneAfterEntranceTransition, entranceTransition);
     }
 
     @Override
diff --git a/v17/leanback/src/android/support/v17/leanback/app/BrowseSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/BrowseSupportFragment.java
index 44deec4..fa7f61e 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/BrowseSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/BrowseSupportFragment.java
@@ -427,7 +427,7 @@
                 if (mBrowseTransitionListener != null) {
                     mBrowseTransitionListener.onHeadersTransitionStart(withHeaders);
                 }
-                sTransitionHelper.runTransition(withHeaders ? mSceneWithHeaders : mSceneWithoutHeaders,
+                TransitionHelper.runTransition(withHeaders ? mSceneWithHeaders : mSceneWithoutHeaders,
                         mHeadersTransition);
                 if (mHeadersBackStackEnabled) {
                     if (!withHeaders) {
@@ -624,19 +624,19 @@
             mHeadersSupportFragment.setBackgroundColor(mBrandColor);
         }
 
-        mSceneWithHeaders = sTransitionHelper.createScene(mBrowseFrame, new Runnable() {
+        mSceneWithHeaders = TransitionHelper.createScene(mBrowseFrame, new Runnable() {
             @Override
             public void run() {
                 showHeaders(true);
             }
         });
-        mSceneWithoutHeaders =  sTransitionHelper.createScene(mBrowseFrame, new Runnable() {
+        mSceneWithoutHeaders =  TransitionHelper.createScene(mBrowseFrame, new Runnable() {
             @Override
             public void run() {
                 showHeaders(false);
             }
         });
-        mSceneAfterEntranceTransition = sTransitionHelper.createScene(mBrowseFrame, new Runnable() {
+        mSceneAfterEntranceTransition = TransitionHelper.createScene(mBrowseFrame, new Runnable() {
             @Override
             public void run() {
                 setEntranceTransitionEndState();
@@ -646,11 +646,11 @@
     }
 
     private void createHeadersTransition() {
-        mHeadersTransition = sTransitionHelper.loadTransition(getActivity(),
+        mHeadersTransition = TransitionHelper.loadTransition(getActivity(),
                 mShowingHeaders ?
                 R.transition.lb_browse_headers_in : R.transition.lb_browse_headers_out);
 
-        sTransitionHelper.setTransitionListener(mHeadersTransition, new TransitionListener() {
+        TransitionHelper.addTransitionListener(mHeadersTransition, new TransitionListener() {
             @Override
             public void onTransitionStart(Object transition) {
             }
@@ -893,14 +893,13 @@
 
     @Override
     protected Object createEntranceTransition() {
-        return sTransitionHelper.loadTransition(getActivity(),
+        return TransitionHelper.loadTransition(getActivity(),
                 R.transition.lb_browse_entrance_transition);
     }
 
     @Override
     protected void runEntranceTransition(Object entranceTransition) {
-        sTransitionHelper.runTransition(mSceneAfterEntranceTransition,
-                entranceTransition);
+        TransitionHelper.runTransition(mSceneAfterEntranceTransition, entranceTransition);
     }
 
     @Override
diff --git a/v17/leanback/src/android/support/v17/leanback/app/DetailsFragment.java b/v17/leanback/src/android/support/v17/leanback/app/DetailsFragment.java
index c786040..ddafd5f 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/DetailsFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/DetailsFragment.java
@@ -14,6 +14,7 @@
 package android.support.v17.leanback.app;
 
 import android.support.v17.leanback.R;
+import android.support.v17.leanback.transition.TransitionHelper;
 import android.support.v17.leanback.widget.BrowseFrameLayout;
 import android.support.v17.leanback.widget.DetailsOverviewRow;
 import android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter;
@@ -200,7 +201,7 @@
             }
         }
 
-        mSceneAfterEntranceTransition = sTransitionHelper.createScene(
+        mSceneAfterEntranceTransition = TransitionHelper.createScene(
                 (ViewGroup) view, new Runnable() {
             @Override
             public void run() {
@@ -401,14 +402,13 @@
 
     @Override
     protected Object createEntranceTransition() {
-        return sTransitionHelper.loadTransition(getActivity(),
+        return TransitionHelper.loadTransition(getActivity(),
                 R.transition.lb_details_enter_transition);
     }
 
     @Override
     protected void runEntranceTransition(Object entranceTransition) {
-        sTransitionHelper.runTransition(mSceneAfterEntranceTransition,
-                entranceTransition);
+        TransitionHelper.runTransition(mSceneAfterEntranceTransition, entranceTransition);
     }
 
     @Override
diff --git a/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragment.java
index fbce207..7532d79 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragment.java
@@ -16,6 +16,7 @@
 package android.support.v17.leanback.app;
 
 import android.support.v17.leanback.R;
+import android.support.v17.leanback.transition.TransitionHelper;
 import android.support.v17.leanback.widget.BrowseFrameLayout;
 import android.support.v17.leanback.widget.DetailsOverviewRow;
 import android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter;
@@ -202,7 +203,7 @@
             }
         }
 
-        mSceneAfterEntranceTransition = sTransitionHelper.createScene(
+        mSceneAfterEntranceTransition = TransitionHelper.createScene(
                 (ViewGroup) view, new Runnable() {
             @Override
             public void run() {
@@ -403,14 +404,13 @@
 
     @Override
     protected Object createEntranceTransition() {
-        return sTransitionHelper.loadTransition(getActivity(),
+        return TransitionHelper.loadTransition(getActivity(),
                 R.transition.lb_details_enter_transition);
     }
 
     @Override
     protected void runEntranceTransition(Object entranceTransition) {
-        sTransitionHelper.runTransition(mSceneAfterEntranceTransition,
-                entranceTransition);
+        TransitionHelper.runTransition(mSceneAfterEntranceTransition, entranceTransition);
     }
 
     @Override
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 daab9ac..f985d55 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/GuidedStepFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/GuidedStepFragment.java
@@ -471,26 +471,25 @@
      */
     protected void onProvideFragmentTransitions() {
         if (Build.VERSION.SDK_INT >= 21) {
-            TransitionHelper helper = TransitionHelper.getInstance();
             if (getUiStyle() == UI_STYLE_DEFAULT) {
-                Object enterTransition = helper.createFadeAndShortSlide(Gravity.END);
-                helper.exclude(enterTransition, R.id.guidedactions_background, true);
-                helper.exclude(enterTransition, R.id.guidedactions_selector, true);
-                TransitionHelper.getInstance().setEnterTransition(this, enterTransition);
-                Object exitTransition = helper.createFadeAndShortSlide(Gravity.START);
-                helper.exclude(exitTransition, R.id.guidedactions_background, true);
-                helper.exclude(exitTransition, R.id.guidedactions_selector, true);
-                TransitionHelper.getInstance().setExitTransition(this, exitTransition);
+                Object enterTransition = TransitionHelper.createFadeAndShortSlide(Gravity.END);
+                TransitionHelper.exclude(enterTransition, R.id.guidedactions_background, true);
+                TransitionHelper.exclude(enterTransition, R.id.guidedactions_selector, true);
+                TransitionHelper.setEnterTransition(this, enterTransition);
+                Object exitTransition = TransitionHelper.createFadeAndShortSlide(Gravity.START);
+                TransitionHelper.exclude(exitTransition, R.id.guidedactions_background, true);
+                TransitionHelper.exclude(exitTransition, R.id.guidedactions_selector, true);
+                TransitionHelper.setExitTransition(this, exitTransition);
             } else if (getUiStyle() == UI_STYLE_ENTRANCE) {
-                Object enterTransition = helper.createFadeAndShortSlide(Gravity.END |
+                Object enterTransition = TransitionHelper.createFadeAndShortSlide(Gravity.END |
                         Gravity.START);
-                helper.include(enterTransition, R.id.content_fragment);
-                helper.include(enterTransition, R.id.action_fragment);
-                TransitionHelper.getInstance().setEnterTransition(this, enterTransition);
+                TransitionHelper.include(enterTransition, R.id.content_fragment);
+                TransitionHelper.include(enterTransition, R.id.action_fragment);
+                TransitionHelper.setEnterTransition(this, enterTransition);
                 // exit transition is unchanged, same as UI_STYLE_DEFAULT
             } else if (getUiStyle() == UI_STYLE_ACTIVITY_ROOT) {
                 // for Activity root, we dont need enter transition, use activity transition
-                TransitionHelper.getInstance().setEnterTransition(this, null);
+                TransitionHelper.setEnterTransition(this, null);
                 // exit transition is unchanged, same as UI_STYLE_DEFAULT
             }
         }
@@ -511,10 +510,9 @@
          */
         protected void onProvideFragmentTransitions() {
             if (Build.VERSION.SDK_INT >= 21) {
-                TransitionHelper helper = TransitionHelper.getInstance();
-                Object enterTransition = helper.createFadeTransition(
+                Object enterTransition = TransitionHelper.createFadeTransition(
                         TransitionHelper.FADE_IN|TransitionHelper.FADE_OUT);
-                TransitionHelper.getInstance().setEnterTransition(this, enterTransition);
+                TransitionHelper.setEnterTransition(this, enterTransition);
             }
         }
 
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 577133d..10c8a72 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/GuidedStepSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/GuidedStepSupportFragment.java
@@ -473,26 +473,25 @@
      */
     protected void onProvideFragmentTransitions() {
         if (Build.VERSION.SDK_INT >= 21) {
-            TransitionHelper helper = TransitionHelper.getInstance();
             if (getUiStyle() == UI_STYLE_DEFAULT) {
-                Object enterTransition = helper.createFadeAndShortSlide(Gravity.END);
-                helper.exclude(enterTransition, R.id.guidedactions_background, true);
-                helper.exclude(enterTransition, R.id.guidedactions_selector, true);
-                TransitionHelper.getInstance().setEnterTransition(this, enterTransition);
-                Object exitTransition = helper.createFadeAndShortSlide(Gravity.START);
-                helper.exclude(exitTransition, R.id.guidedactions_background, true);
-                helper.exclude(exitTransition, R.id.guidedactions_selector, true);
-                TransitionHelper.getInstance().setExitTransition(this, exitTransition);
+                Object enterTransition = TransitionHelper.createFadeAndShortSlide(Gravity.END);
+                TransitionHelper.exclude(enterTransition, R.id.guidedactions_background, true);
+                TransitionHelper.exclude(enterTransition, R.id.guidedactions_selector, true);
+                TransitionHelper.setEnterTransition(this, enterTransition);
+                Object exitTransition = TransitionHelper.createFadeAndShortSlide(Gravity.START);
+                TransitionHelper.exclude(exitTransition, R.id.guidedactions_background, true);
+                TransitionHelper.exclude(exitTransition, R.id.guidedactions_selector, true);
+                TransitionHelper.setExitTransition(this, exitTransition);
             } else if (getUiStyle() == UI_STYLE_ENTRANCE) {
-                Object enterTransition = helper.createFadeAndShortSlide(Gravity.END |
+                Object enterTransition = TransitionHelper.createFadeAndShortSlide(Gravity.END |
                         Gravity.START);
-                helper.include(enterTransition, R.id.content_fragment);
-                helper.include(enterTransition, R.id.action_fragment);
-                TransitionHelper.getInstance().setEnterTransition(this, enterTransition);
+                TransitionHelper.include(enterTransition, R.id.content_fragment);
+                TransitionHelper.include(enterTransition, R.id.action_fragment);
+                TransitionHelper.setEnterTransition(this, enterTransition);
                 // exit transition is unchanged, same as UI_STYLE_DEFAULT
             } else if (getUiStyle() == UI_STYLE_ACTIVITY_ROOT) {
                 // for Activity root, we dont need enter transition, use activity transition
-                TransitionHelper.getInstance().setEnterTransition(this, null);
+                TransitionHelper.setEnterTransition(this, null);
                 // exit transition is unchanged, same as UI_STYLE_DEFAULT
             }
         }
@@ -513,10 +512,9 @@
          */
         protected void onProvideFragmentTransitions() {
             if (Build.VERSION.SDK_INT >= 21) {
-                TransitionHelper helper = TransitionHelper.getInstance();
-                Object enterTransition = helper.createFadeTransition(
+                Object enterTransition = TransitionHelper.createFadeTransition(
                         TransitionHelper.FADE_IN|TransitionHelper.FADE_OUT);
-                TransitionHelper.getInstance().setEnterTransition(this, enterTransition);
+                TransitionHelper.setEnterTransition(this, enterTransition);
             }
         }
 
diff --git a/v17/leanback/src/android/support/v17/leanback/app/VerticalGridFragment.java b/v17/leanback/src/android/support/v17/leanback/app/VerticalGridFragment.java
index c7d55b9..3e51989 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/VerticalGridFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/VerticalGridFragment.java
@@ -15,6 +15,7 @@
 
 import android.support.annotation.ColorInt;
 import android.support.v17.leanback.R;
+import android.support.v17.leanback.transition.TransitionHelper;
 import android.support.v17.leanback.widget.BrowseFrameLayout;
 import android.support.v17.leanback.widget.OnChildLaidOutListener;
 import android.support.v17.leanback.widget.OnItemViewClickedListener;
@@ -171,7 +172,7 @@
         gridDock.addView(mGridViewHolder.view);
         mGridViewHolder.getGridView().setOnChildLaidOutListener(mChildLaidOutListener);
 
-        mSceneAfterEntranceTransition = sTransitionHelper.createScene(gridDock, new Runnable() {
+        mSceneAfterEntranceTransition = TransitionHelper.createScene(gridDock, new Runnable() {
             @Override
             public void run() {
                 setEntranceTransitionState(true);
@@ -223,14 +224,13 @@
 
     @Override
     protected Object createEntranceTransition() {
-        return sTransitionHelper.loadTransition(getActivity(),
+        return TransitionHelper.loadTransition(getActivity(),
                 R.transition.lb_vertical_grid_entrance_transition);
     }
 
     @Override
     protected void runEntranceTransition(Object entranceTransition) {
-        sTransitionHelper.runTransition(mSceneAfterEntranceTransition,
-                entranceTransition);
+        TransitionHelper.runTransition(mSceneAfterEntranceTransition, entranceTransition);
     }
 
     void setEntranceTransitionState(boolean afterTransition) {
diff --git a/v17/leanback/src/android/support/v17/leanback/app/VerticalGridSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/VerticalGridSupportFragment.java
index 33fe6fc..eb0b337 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/VerticalGridSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/VerticalGridSupportFragment.java
@@ -17,6 +17,7 @@
 
 import android.support.annotation.ColorInt;
 import android.support.v17.leanback.R;
+import android.support.v17.leanback.transition.TransitionHelper;
 import android.support.v17.leanback.widget.BrowseFrameLayout;
 import android.support.v17.leanback.widget.OnChildLaidOutListener;
 import android.support.v17.leanback.widget.OnItemViewClickedListener;
@@ -173,7 +174,7 @@
         gridDock.addView(mGridViewHolder.view);
         mGridViewHolder.getGridView().setOnChildLaidOutListener(mChildLaidOutListener);
 
-        mSceneAfterEntranceTransition = sTransitionHelper.createScene(gridDock, new Runnable() {
+        mSceneAfterEntranceTransition = TransitionHelper.createScene(gridDock, new Runnable() {
             @Override
             public void run() {
                 setEntranceTransitionState(true);
@@ -225,14 +226,13 @@
 
     @Override
     protected Object createEntranceTransition() {
-        return sTransitionHelper.loadTransition(getActivity(),
+        return TransitionHelper.loadTransition(getActivity(),
                 R.transition.lb_vertical_grid_entrance_transition);
     }
 
     @Override
     protected void runEntranceTransition(Object entranceTransition) {
-        sTransitionHelper.runTransition(mSceneAfterEntranceTransition,
-                entranceTransition);
+        TransitionHelper.runTransition(mSceneAfterEntranceTransition, entranceTransition);
     }
 
     void setEntranceTransitionState(boolean afterTransition) {
diff --git a/v17/leanback/src/android/support/v17/leanback/transition/LeanbackTransitionHelper.java b/v17/leanback/src/android/support/v17/leanback/transition/LeanbackTransitionHelper.java
index f7451d4..47495cb 100644
--- a/v17/leanback/src/android/support/v17/leanback/transition/LeanbackTransitionHelper.java
+++ b/v17/leanback/src/android/support/v17/leanback/transition/LeanbackTransitionHelper.java
@@ -30,9 +30,9 @@
 
     static interface LeanbackTransitionHelperVersion {
 
-        public Object loadTitleInTransition(Context context, TransitionHelper helper);
+        public Object loadTitleInTransition(Context context);
 
-        public Object loadTitleOutTransition(Context context, TransitionHelper helper);
+        public Object loadTitleOutTransition(Context context);
     }
 
     /*
@@ -42,12 +42,12 @@
     static class LeanbackTransitionHelperKitKatImpl implements LeanbackTransitionHelperVersion {
 
         @Override
-        public Object loadTitleInTransition(Context context, TransitionHelper helper) {
+        public Object loadTitleInTransition(Context context) {
             return LeanbackTransitionHelperKitKat.loadTitleInTransition(context);
         }
 
         @Override
-        public Object loadTitleOutTransition(Context context, TransitionHelper helper) {
+        public Object loadTitleOutTransition(Context context) {
             return LeanbackTransitionHelperKitKat.loadTitleOutTransition(context);
         }
     }
@@ -58,13 +58,13 @@
     static class LeanbackTransitionHelperDefault implements LeanbackTransitionHelperVersion {
 
         @Override
-        public Object loadTitleInTransition(Context context, TransitionHelper helper) {
-            return helper.loadTransition(context, R.transition.lb_title_in);
+        public Object loadTitleInTransition(Context context) {
+            return TransitionHelper.loadTransition(context, R.transition.lb_title_in);
         }
 
         @Override
-        public Object loadTitleOutTransition(Context context, TransitionHelper helper) {
-            return helper.loadTransition(context, R.transition.lb_title_out);
+        public Object loadTitleOutTransition(Context context) {
+            return TransitionHelper.loadTransition(context, R.transition.lb_title_out);
         }
     }
 
@@ -81,11 +81,11 @@
         }
     }
 
-    static public Object loadTitleInTransition(Context context, TransitionHelper helper) {
-        return sImpl.loadTitleInTransition(context, helper);
+    static public Object loadTitleInTransition(Context context) {
+        return sImpl.loadTitleInTransition(context);
     }
 
-    static public Object loadTitleOutTransition(Context context, TransitionHelper helper) {
-        return sImpl.loadTitleOutTransition(context, helper);
+    static public Object loadTitleOutTransition(Context context) {
+        return sImpl.loadTitleOutTransition(context);
     }
 }
diff --git a/v17/leanback/src/android/support/v17/leanback/transition/TransitionHelper.java b/v17/leanback/src/android/support/v17/leanback/transition/TransitionHelper.java
index 941616a..98fb06f 100644
--- a/v17/leanback/src/android/support/v17/leanback/transition/TransitionHelper.java
+++ b/v17/leanback/src/android/support/v17/leanback/transition/TransitionHelper.java
@@ -20,6 +20,8 @@
 import android.view.ViewGroup;
 import android.view.Window;
 
+import java.util.ArrayList;
+
 /**
  * Helper for view transitions.
  * @hide
@@ -34,8 +36,7 @@
     public static final int SLIDE_RIGHT = Gravity.RIGHT;
     public static final int SLIDE_BOTTOM = Gravity.BOTTOM;
 
-    private final static TransitionHelper sHelper = new TransitionHelper();
-    TransitionHelperVersionImpl mImpl;
+    private static TransitionHelperVersionImpl sImpl;
 
     /**
      * Gets whether the system supports Transition animations.
@@ -109,7 +110,9 @@
 
         public void addTransition(Object transitionSet, Object transition);
 
-        public void setTransitionListener(Object transition, TransitionListener listener);
+        public void addTransitionListener(Object transition, TransitionListener listener);
+
+        public void removeTransitionListener(Object transition, TransitionListener listener);
 
         public void runTransition(Object scene, Object transition);
 
@@ -146,7 +149,7 @@
     static class TransitionHelperStubImpl implements TransitionHelperVersionImpl {
 
         private static class TransitionStub {
-            TransitionListener mTransitionListener;
+            ArrayList<TransitionListener> mTransitionListeners;
         }
 
         public void setEnterTransition(android.app.Fragment fragment, Object transition) {
@@ -289,22 +292,38 @@
         }
 
         @Override
-        public void setTransitionListener(Object transition, TransitionListener listener) {
-            ((TransitionStub) transition).mTransitionListener = listener;
+        public void addTransitionListener(Object transition, TransitionListener listener) {
+            TransitionStub stub = (TransitionStub) transition;
+            if (stub.mTransitionListeners == null) {
+                stub.mTransitionListeners = new ArrayList<TransitionListener>();
+            }
+            stub.mTransitionListeners.add(listener);
+        }
+
+        @Override
+        public void removeTransitionListener(Object transition, TransitionListener listener) {
+            TransitionStub stub = (TransitionStub) transition;
+            if (stub.mTransitionListeners != null) {
+                stub.mTransitionListeners.remove(listener);
+            }
         }
 
         @Override
         public void runTransition(Object scene, Object transition) {
             TransitionStub transitionStub = (TransitionStub) transition;
-            if (transitionStub != null && transitionStub.mTransitionListener != null) {
-                transitionStub.mTransitionListener.onTransitionStart(transition);
+            if (transitionStub != null && transitionStub.mTransitionListeners != null) {
+                for (int i = 0, size = transitionStub.mTransitionListeners.size(); i < size; i++) {
+                    transitionStub.mTransitionListeners.get(i).onTransitionStart(transition);
+                }
             }
             Runnable r = ((Runnable) scene);
             if (r != null) {
                 r.run();
             }
-            if (transitionStub != null && transitionStub.mTransitionListener != null) {
-                transitionStub.mTransitionListener.onTransitionEnd(transition);
+            if (transitionStub != null && transitionStub.mTransitionListeners != null) {
+                for (int i = 0, size = transitionStub.mTransitionListeners.size(); i < size; i++) {
+                    transitionStub.mTransitionListeners.get(i).onTransitionEnd(transition);
+                }
             }
         }
 
@@ -438,8 +457,13 @@
         }
 
         @Override
-        public void setTransitionListener(Object transition, TransitionListener listener) {
-            TransitionHelperKitkat.setTransitionListener(transition, listener);
+        public void addTransitionListener(Object transition, TransitionListener listener) {
+            TransitionHelperKitkat.addTransitionListener(transition, listener);
+        }
+
+        @Override
+        public void removeTransitionListener(Object transition, TransitionListener listener) {
+            TransitionHelperKitkat.removeTransitionListener(transition, listener);
         }
 
         @Override
@@ -539,181 +563,180 @@
         }
     }
 
-    /**
-     * Returns the TransitionHelper that can be used to perform Transition
-     * animations.
-     */
-    public static TransitionHelper getInstance() {
-        return sHelper;
-    }
-
-    private TransitionHelper() {
+    static {
         if (Build.VERSION.SDK_INT >= 21) {
-            mImpl = new TransitionHelperApi21Impl();
+            sImpl = new TransitionHelperApi21Impl();
         } else  if (systemSupportsTransitions()) {
-            mImpl = new TransitionHelperKitkatImpl();
+            sImpl = new TransitionHelperKitkatImpl();
         } else {
-            mImpl = new TransitionHelperStubImpl();
+            sImpl = new TransitionHelperStubImpl();
         }
     }
 
-    public Object getSharedElementEnterTransition(Window window) {
-        return mImpl.getSharedElementEnterTransition(window);
+    public static Object getSharedElementEnterTransition(Window window) {
+        return sImpl.getSharedElementEnterTransition(window);
     }
 
-    public Object getSharedElementReturnTransition(Window window) {
-        return mImpl.getSharedElementReturnTransition(window);
+    public static Object getSharedElementReturnTransition(Window window) {
+        return sImpl.getSharedElementReturnTransition(window);
     }
 
-    public Object getSharedElementExitTransition(Window window) {
-        return mImpl.getSharedElementExitTransition(window);
+    public static Object getSharedElementExitTransition(Window window) {
+        return sImpl.getSharedElementExitTransition(window);
     }
 
-    public Object getSharedElementReenterTransition(Window window) {
-        return mImpl.getSharedElementReenterTransition(window);
+    public static Object getSharedElementReenterTransition(Window window) {
+        return sImpl.getSharedElementReenterTransition(window);
     }
 
-    public Object getEnterTransition(Window window) {
-        return mImpl.getEnterTransition(window);
+    public static Object getEnterTransition(Window window) {
+        return sImpl.getEnterTransition(window);
     }
 
-    public Object getReturnTransition(Window window) {
-        return mImpl.getReturnTransition(window);
+    public static Object getReturnTransition(Window window) {
+        return sImpl.getReturnTransition(window);
     }
 
-    public Object getExitTransition(Window window) {
-        return mImpl.getExitTransition(window);
+    public static Object getExitTransition(Window window) {
+        return sImpl.getExitTransition(window);
     }
 
-    public Object getReenterTransition(Window window) {
-        return mImpl.getReenterTransition(window);
+    public static Object getReenterTransition(Window window) {
+        return sImpl.getReenterTransition(window);
     }
 
-    public Object createScene(ViewGroup sceneRoot, Runnable r) {
-        return mImpl.createScene(sceneRoot, r);
+    public static Object createScene(ViewGroup sceneRoot, Runnable r) {
+        return sImpl.createScene(sceneRoot, r);
     }
 
-    public Object createChangeBounds(boolean reparent) {
-        return mImpl.createChangeBounds(reparent);
+    public static Object createChangeBounds(boolean reparent) {
+        return sImpl.createChangeBounds(reparent);
     }
 
-    public void setChangeBoundsStartDelay(Object changeBounds, View view, int startDelay) {
-        mImpl.setChangeBoundsStartDelay(changeBounds, view, startDelay);
+    public static void setChangeBoundsStartDelay(Object changeBounds, View view, int startDelay) {
+        sImpl.setChangeBoundsStartDelay(changeBounds, view, startDelay);
     }
 
-    public void setChangeBoundsStartDelay(Object changeBounds, int viewId, int startDelay) {
-        mImpl.setChangeBoundsStartDelay(changeBounds, viewId, startDelay);
+    public static void setChangeBoundsStartDelay(Object changeBounds, int viewId, int startDelay) {
+        sImpl.setChangeBoundsStartDelay(changeBounds, viewId, startDelay);
     }
 
-    public void setChangeBoundsStartDelay(Object changeBounds, String className, int startDelay) {
-        mImpl.setChangeBoundsStartDelay(changeBounds, className, startDelay);
+    public static void setChangeBoundsStartDelay(Object changeBounds, String className,
+            int startDelay) {
+        sImpl.setChangeBoundsStartDelay(changeBounds, className, startDelay);
     }
 
-    public void setChangeBoundsDefaultStartDelay(Object changeBounds, int startDelay) {
-        mImpl.setChangeBoundsDefaultStartDelay(changeBounds, startDelay);
+    public static void setChangeBoundsDefaultStartDelay(Object changeBounds, int startDelay) {
+        sImpl.setChangeBoundsDefaultStartDelay(changeBounds, startDelay);
     }
 
-    public Object createTransitionSet(boolean sequential) {
-        return mImpl.createTransitionSet(sequential);
+    public static Object createTransitionSet(boolean sequential) {
+        return sImpl.createTransitionSet(sequential);
     }
 
-    public Object createSlide(int slideEdge) {
-        return mImpl.createSlide(slideEdge);
+    public static Object createSlide(int slideEdge) {
+        return sImpl.createSlide(slideEdge);
     }
 
-    public Object createScale() {
-        return mImpl.createScale();
+    public static Object createScale() {
+        return sImpl.createScale();
     }
 
-    public void addTransition(Object transitionSet, Object transition) {
-        mImpl.addTransition(transitionSet, transition);
+    public static void addTransition(Object transitionSet, Object transition) {
+        sImpl.addTransition(transitionSet, transition);
     }
 
-    public void exclude(Object transition, int targetId, boolean exclude) {
-        mImpl.exclude(transition, targetId, exclude);
+    public static void exclude(Object transition, int targetId, boolean exclude) {
+        sImpl.exclude(transition, targetId, exclude);
     }
 
-    public void exclude(Object transition, View targetView, boolean exclude) {
-        mImpl.exclude(transition, targetView, exclude);
+    public static void exclude(Object transition, View targetView, boolean exclude) {
+        sImpl.exclude(transition, targetView, exclude);
     }
 
-    public void excludeChildren(Object transition, int targetId, boolean exclude) {
-        mImpl.excludeChildren(transition, targetId, exclude);
+    public static void excludeChildren(Object transition, int targetId, boolean exclude) {
+        sImpl.excludeChildren(transition, targetId, exclude);
     }
 
-    public void excludeChildren(Object transition, View targetView, boolean exclude) {
-        mImpl.excludeChildren(transition, targetView, exclude);
+    public static void excludeChildren(Object transition, View targetView, boolean exclude) {
+        sImpl.excludeChildren(transition, targetView, exclude);
     }
 
-    public void include(Object transition, int targetId) {
-        mImpl.include(transition, targetId);
+    public static void include(Object transition, int targetId) {
+        sImpl.include(transition, targetId);
     }
 
-    public void include(Object transition, View targetView) {
-        mImpl.include(transition, targetView);
+    public static void include(Object transition, View targetView) {
+        sImpl.include(transition, targetView);
     }
 
-    public void setStartDelay(Object transition, long startDelay) {
-        mImpl.setStartDelay(transition, startDelay);
+    public static void setStartDelay(Object transition, long startDelay) {
+        sImpl.setStartDelay(transition, startDelay);
     }
 
-    public void setDuration(Object transition, long duration) {
-        mImpl.setDuration(transition, duration);
+    public static void setDuration(Object transition, long duration) {
+        sImpl.setDuration(transition, duration);
     }
 
-    public Object createAutoTransition() {
-        return mImpl.createAutoTransition();
+    public static Object createAutoTransition() {
+        return sImpl.createAutoTransition();
     }
 
-    public Object createFadeTransition(int fadeMode) {
-        return mImpl.createFadeTransition(fadeMode);
+    public static Object createFadeTransition(int fadeMode) {
+        return sImpl.createFadeTransition(fadeMode);
     }
 
-    public void setTransitionListener(Object transition, TransitionListener listener) {
-        mImpl.setTransitionListener(transition, listener);
+    public static void addTransitionListener(Object transition, TransitionListener listener) {
+        sImpl.addTransitionListener(transition, listener);
     }
 
-    public void runTransition(Object scene, Object transition) {
-        mImpl.runTransition(scene, transition);
+    public static void removeTransitionListener(Object transition, TransitionListener listener) {
+        sImpl.removeTransitionListener(transition, listener);
     }
 
-    public void setInterpolator(Object transition, Object timeInterpolator) {
-        mImpl.setInterpolator(transition, timeInterpolator);
+    public static void runTransition(Object scene, Object transition) {
+        sImpl.runTransition(scene, transition);
     }
 
-    public void addTarget(Object transition, View view) {
-        mImpl.addTarget(transition, view);
+    public static void setInterpolator(Object transition, Object timeInterpolator) {
+        sImpl.setInterpolator(transition, timeInterpolator);
     }
 
-    public Object createDefaultInterpolator(Context context) {
-        return mImpl.createDefaultInterpolator(context);
+    public static void addTarget(Object transition, View view) {
+        sImpl.addTarget(transition, view);
     }
 
-    public Object loadTransition(Context context, int resId) {
-        return mImpl.loadTransition(context, resId);
+    public static Object createDefaultInterpolator(Context context) {
+        return sImpl.createDefaultInterpolator(context);
     }
 
-    public void setEnterTransition(android.app.Fragment fragment, Object transition) {
-        mImpl.setEnterTransition(fragment, transition);
+    public static Object loadTransition(Context context, int resId) {
+        return sImpl.loadTransition(context, resId);
     }
 
-    public void setExitTransition(android.app.Fragment fragment, Object transition) {
-        mImpl.setExitTransition(fragment, transition);
+    public static void setEnterTransition(android.app.Fragment fragment, Object transition) {
+        sImpl.setEnterTransition(fragment, transition);
     }
 
-    public void setEnterTransition(android.support.v4.app.Fragment fragment, Object transition) {
+    public static void setExitTransition(android.app.Fragment fragment, Object transition) {
+        sImpl.setExitTransition(fragment, transition);
+    }
+
+    public static void setEnterTransition(android.support.v4.app.Fragment fragment,
+            Object transition) {
         fragment.setEnterTransition(transition);
     }
 
-    public void setExitTransition(android.support.v4.app.Fragment fragment, Object transition) {
+    public static void setExitTransition(android.support.v4.app.Fragment fragment,
+            Object transition) {
         fragment.setExitTransition(transition);
     }
 
-    public Object createFadeAndShortSlide(int edge) {
-        return mImpl.createFadeAndShortSlide(edge);
+    public static Object createFadeAndShortSlide(int edge) {
+        return sImpl.createFadeAndShortSlide(edge);
     }
 
-    public void setTransitionGroup(ViewGroup viewGroup, boolean transitionGroup) {
-        mImpl.setTransitionGroup(viewGroup, transitionGroup);
+    public static void setTransitionGroup(ViewGroup viewGroup, boolean transitionGroup) {
+        sImpl.setTransitionGroup(viewGroup, transitionGroup);
     }
 }
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/DetailsOverviewSharedElementHelper.java b/v17/leanback/src/android/support/v17/leanback/widget/DetailsOverviewSharedElementHelper.java
index 410aa28..cac7d9e 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/DetailsOverviewSharedElementHelper.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/DetailsOverviewSharedElementHelper.java
@@ -232,11 +232,10 @@
                     Log.d(TAG, "setTransitionName "+mViewHolder.mOverviewFrame);
                 }
                 ViewCompat.setTransitionName(mViewHolder.mOverviewFrame, mSharedElementName);
-                final TransitionHelper transitionHelper = TransitionHelper.getInstance();
-                Object transition = transitionHelper.getSharedElementEnterTransition(
+                Object transition = TransitionHelper.getSharedElementEnterTransition(
                         mActivityToRunTransition.getWindow());
                 if (transition != null) {
-                    transitionHelper.setTransitionListener(transition, new TransitionListener() {
+                    TransitionHelper.addTransitionListener(transition, new TransitionListener() {
                         @Override
                         public void onTransitionEnd(Object transition) {
                             if (DEBUG) {
@@ -247,7 +246,7 @@
                             if (mViewHolder.mActionsRow.isFocused()) {
                                 mViewHolder.mActionsRow.requestFocus();
                             }
-                            transitionHelper.setTransitionListener(transition, null);
+                            TransitionHelper.removeTransitionListener(transition, this);
                         }
                     });
                 }
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/FullWidthDetailsOverviewSharedElementHelper.java b/v17/leanback/src/android/support/v17/leanback/widget/FullWidthDetailsOverviewSharedElementHelper.java
index 857c4d9..a9fe9ec 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/FullWidthDetailsOverviewSharedElementHelper.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/FullWidthDetailsOverviewSharedElementHelper.java
@@ -76,8 +76,7 @@
         if (DEBUG) {
             Log.d(TAG, "postponeEnterTransition " + mActivityToRunTransition);
         }
-        Object transition = TransitionHelper.getInstance()
-                .getSharedElementEnterTransition(activity.getWindow());
+        Object transition = TransitionHelper.getSharedElementEnterTransition(activity.getWindow());
         setAutoStartSharedElementTransition(transition != null);
         ActivityCompat.postponeEnterTransition(mActivityToRunTransition);
         if (timeoutMs > 0) {
@@ -140,11 +139,10 @@
                 }
                 ViewCompat.setTransitionName(mViewHolder.getLogoViewHolder().view,
                         mSharedElementName);
-                final TransitionHelper transitionHelper = TransitionHelper.getInstance();
-                Object transition = transitionHelper.getSharedElementEnterTransition(
+                Object transition = TransitionHelper.getSharedElementEnterTransition(
                         mActivityToRunTransition.getWindow());
                 if (transition != null) {
-                    transitionHelper.setTransitionListener(transition, new TransitionListener() {
+                    TransitionHelper.addTransitionListener(transition, new TransitionListener() {
                         @Override
                         public void onTransitionEnd(Object transition) {
                             if (DEBUG) {
@@ -155,7 +153,7 @@
                             if (mViewHolder.getActionsRow().isFocused()) {
                                 mViewHolder.getActionsRow().requestFocus();
                             }
-                            transitionHelper.setTransitionListener(transition, null);
+                            TransitionHelper.removeTransitionListener(transition, this);
                         }
                     });
                 }
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ListRowPresenter.java b/v17/leanback/src/android/support/v17/leanback/widget/ListRowPresenter.java
index 737492b..5540f78 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/ListRowPresenter.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ListRowPresenter.java
@@ -100,8 +100,7 @@
         @Override
         protected void onCreate(ItemBridgeAdapter.ViewHolder viewHolder) {
             if (viewHolder.itemView instanceof ViewGroup) {
-                TransitionHelper.getInstance().setTransitionGroup((ViewGroup) viewHolder.itemView,
-                        true);
+                TransitionHelper.setTransitionGroup((ViewGroup) viewHolder.itemView, true);
             }
             if (mShadowOverlayHelper != null) {
                 mShadowOverlayHelper.onViewCreated(viewHolder.itemView);
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/TitleHelper.java b/v17/leanback/src/android/support/v17/leanback/widget/TitleHelper.java
index c61087b..9282bb1 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/TitleHelper.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/TitleHelper.java
@@ -36,8 +36,6 @@
     private Object mSceneWithTitle;
     private Object mSceneWithoutTitle;
 
-    static TransitionHelper sTransitionHelper = TransitionHelper.getInstance();
-
     // When moving focus off the TitleView, this focus search listener assumes that the view that
     // should take focus comes before the TitleView in a focus search starting at the scene root.
     private final BrowseFrameLayout.OnFocusSearchListener mOnFocusSearchListener =
@@ -68,16 +66,16 @@
 
     private void createTransitions() {
         mTitleUpTransition = LeanbackTransitionHelper.loadTitleOutTransition(
-                mSceneRoot.getContext(), sTransitionHelper);
+                mSceneRoot.getContext());
         mTitleDownTransition = LeanbackTransitionHelper.loadTitleInTransition(
-                mSceneRoot.getContext(), sTransitionHelper);
-        mSceneWithTitle = sTransitionHelper.createScene(mSceneRoot, new Runnable() {
+                mSceneRoot.getContext());
+        mSceneWithTitle = TransitionHelper.createScene(mSceneRoot, new Runnable() {
             @Override
             public void run() {
                 mTitleView.setVisibility(View.VISIBLE);
             }
         });
-        mSceneWithoutTitle = sTransitionHelper.createScene(mSceneRoot, new Runnable() {
+        mSceneWithoutTitle = TransitionHelper.createScene(mSceneRoot, new Runnable() {
             @Override
             public void run() {
                 mTitleView.setVisibility(View.INVISIBLE);
@@ -90,9 +88,9 @@
      */
     public void showTitle(boolean show) {
         if (show) {
-            sTransitionHelper.runTransition(mSceneWithTitle, mTitleDownTransition);
+            TransitionHelper.runTransition(mSceneWithTitle, mTitleDownTransition);
         } else {
-            sTransitionHelper.runTransition(mSceneWithoutTitle, mTitleUpTransition);
+            TransitionHelper.runTransition(mSceneWithoutTitle, mTitleUpTransition);
         }
     }
 
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/VerticalGridPresenter.java b/v17/leanback/src/android/support/v17/leanback/widget/VerticalGridPresenter.java
index 3e9d289..7af5ea0 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/VerticalGridPresenter.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/VerticalGridPresenter.java
@@ -34,7 +34,7 @@
         @Override
         protected void onCreate(ItemBridgeAdapter.ViewHolder viewHolder) {
             if (viewHolder.itemView instanceof ViewGroup) {
-                TransitionHelper.getInstance().setTransitionGroup((ViewGroup) viewHolder.itemView,
+                TransitionHelper.setTransitionGroup((ViewGroup) viewHolder.itemView,
                         true);
             }
             if (mShadowOverlayHelper != null) {
diff --git a/v4/java/android/support/v4/view/ActionProvider.java b/v4/java/android/support/v4/view/ActionProvider.java
index d195a3a..070ea46 100644
--- a/v4/java/android/support/v4/view/ActionProvider.java
+++ b/v4/java/android/support/v4/view/ActionProvider.java
@@ -60,6 +60,63 @@
  * </code></pre>
  * </li></ul></p>
  *
+ * <h3>Creating a custom action provider</h3>
+ *
+ * <p>To create a custom action provider, extend ActionProvider and implement
+ * its callback methods as necessary. In particular, implement the following
+ * methods:</p>
+ *
+ * <dl>
+ * <dt>{@link #ActionProvider ActionProvider()} constructor</dt>
+ * <dd>This constructor is passed the application context. You should
+ * save the context in a member field to use in the other callback methods.</dd>
+ *
+ * <dt>{@link #onCreateActionView onCreateActionView(MenuItem)}</dt>
+ * <dd>The system calls this method when the action provider is created.
+ * You define the action provider's layout through the implementation of this
+ * method. Use the context acquired
+ * from the constructor to instantiate a {@link android.view.LayoutInflater} and
+ * inflate your action provider's layout from an XML resource, then hook up
+ * event listeners for the view's components. For example:
+ *
+ *<pre>
+ * public View onCreateActionView(MenuItem forItem) {
+ *     // Inflate the action provider to be shown on the action bar.
+ *     LayoutInflater layoutInflater = LayoutInflater.from(mContext);
+ *     View providerView =
+ *         layoutInflater.inflate(R.layout.my_action_provider, null);
+ *     ImageButton button =
+ *         (ImageButton) providerView.findViewById(R.id.button);
+ *     button.setOnClickListener(new View.OnClickListener() {
+ *         &#64;Override
+ *         public void onClick(View v) {
+ *             // Do something...
+ *         }
+ *     });
+ *     return providerView;
+ * }</pre>
+ * </dd>
+ *
+ * <dt>{@link #onPerformDefaultAction onPerformDefaultAction()}</dt>
+ * <dd><p>The system calls this method when the user selects a menu item from the action
+ * overflow. The action provider should perform a default action for the
+ * menu item. The system does not call this method if the menu item opens a submenu.</p>
+ *
+ * <p>If your action provider presents a submenu through the
+ * {@link #onPrepareSubMenu onPrepareSubMenu()} callback, the submenu
+ * appears even if the action provider is in the overflow menu.
+ * Thus, the system never calls {@link #onPerformDefaultAction
+ * onPerformDefaultAction()} if there is a submenu.</p>
+ *
+ * <p class="note"> <strong>Note:</strong> An activity or a fragment that
+ * implements <code>onOptionsItemSelected()</code> can override the action
+ * provider's default behavior (unless it uses a submenu) by handling the
+ * item-selected event and returning <code>true</code>. In this case, the
+ * system does not call
+ * {@link #onPerformDefaultAction onPerformDefaultAction()}.</p></dd>
+ * </dl>
+ *
+ *
  * @see android.support.v4.view.MenuItemCompat#setActionProvider(android.view.MenuItem, ActionProvider)
  * @see android.support.v4.view.MenuItemCompat#getActionProvider(android.view.MenuItem)
  */
diff --git a/v7/appcompat/src/android/support/v7/widget/ShareActionProvider.java b/v7/appcompat/src/android/support/v7/widget/ShareActionProvider.java
index 7b8b8e8..51d192a 100644
--- a/v7/appcompat/src/android/support/v7/widget/ShareActionProvider.java
+++ b/v7/appcompat/src/android/support/v7/widget/ShareActionProvider.java
@@ -36,51 +36,92 @@
 import android.view.View;
 
 /**
- * This is a provider for a share action. It is responsible for creating views
- * that enable data sharing and also to show a sub menu with sharing activities
- * if the hosting item is placed on the overflow menu.
+ * Provides a share action, which is suitable for an activity's app bar. Creates
+ * views that enable data sharing. If the provider appears in the
+ * overflow menu, it creates a submenu with the appropriate sharing
+ * actions.
  *
- * <p class="note"><strong>Note:</strong> This class is included in the <a
- * href="{@docRoot}tools/extras/support-library.html">support library</a> for compatibility
- * with API level 7 and higher. If you're developing your app for API level 14 and higher
- * <em>only</em>, you should instead use the framework {@link android.widget.ShareActionProvider}
- * class.</p>
+ * <h3 id="add-share-action">Adding a share action</h3>
  *
- * <p>
- * Here is how to use the action provider with custom backing file in a {@link MenuItem}:
- * </p>
- * <pre><code>
- *  // In {@link android.app.Activity#onCreateOptionsMenu Activity.onCreateOptionsMenu()}
- *  public boolean onCreateOptionsMenu(Menu menu) {
- *      // Get the menu item.
- *      MenuItem menuItem = menu.findItem(R.id.my_menu_item);
- *      // Get the provider and hold onto it to set/change the share intent.
- *      mShareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(menuItem);
- *      // Set history different from the default before getting the action
- *      // view since a call to {@link android.support.v4.view.MenuItemCompat#getActionView(android.view.MenuItem) MenuItemCompat.getActionView()} calls
- *      // {@link ActionProvider#onCreateActionView()} which uses the backing file name. Omit this
- *      // line if using the default share history file is desired.
- *      mShareActionProvider.setShareHistoryFileName("custom_share_history.xml");
- *      . . .
- *  }
+ * <p>To add a "share" action to your activity, put a
+ * <code>ShareActionProvider</code> in the app bar's menu resource. For
+ * example:</p>
  *
- *  // Somewhere in the application.
- *  public void doShare(Intent shareIntent) {
- *      // When you want to share set the share intent.
- *      mShareActionProvider.setShareIntent(shareIntent);
- *  }
- * </code></pre>
- * <p>
- * <strong>Note:</strong> While the sample snippet demonstrates how to use this provider
- * in the context of a menu item, the use of the provider is not limited to menu items.
- * </p>
+ * <pre>
+ * &lt;item android:id="&#64;+id/action_share"
+ *      android:title="&#64;string/share"
+ *      app:showAsAction="ifRoom"
+ *      app:actionProviderClass="android.support.v7.widget.ShareActionProvider"/&gt;
+ * </pre>
  *
- * <div class="special reference">
- * <h3>Developer Guides</h3>
+ * <p>You do not need to specify an icon, since the
+ * <code>ShareActionProvider</code> widget takes care of its own appearance and
+ * behavior. However, you do need to specify a title with
+ * <code>android:title</code>, in case the action ends up in the overflow
+ * menu.</p>
  *
- * <p>For information about how to use {@link ShareActionProvider}, see the
- * <a href="{@docRoot}guide/topics/ui/actionbar.html#ActionProvider">Action Bar</a> API guide.</p>
- * </div>
+ * <p>Next, set up the intent that contains the content your activity is
+ * able to share. You should create this intent in your handler for
+ * {@link android.app.Activity#onCreateOptionsMenu onCreateOptionsMenu()},
+ * and update it every time the shareable content changes. To set up the
+ * intent:</p>
+ *
+ * <ol>
+ * <li>Get a reference to the ShareActionProvider by calling {@link
+ * android.view.MenuItem#getActionProvider getActionProvider()} and
+ * passing the share action's {@link android.view.MenuItem}. For
+ * example:
+ *
+ * <pre>
+ * MenuItem shareItem = menu.findItem(R.id.action_share);
+ * ShareActionProvider myShareActionProvider =
+ *     (ShareActionProvider) MenuItemCompat.getActionProvider(shareItem);</pre></li>
+ *
+ * <li>Create an intent with the {@link android.content.Intent#ACTION_SEND}
+ * action, and attach the content shared by the activity. For example, the
+ * following intent shares an image:
+ *
+ * <pre>
+ * Intent myShareIntent = new Intent(Intent.ACTION_SEND);
+ * myShareIntent.setType("image/*");
+ * myShareIntent.putExtra(Intent.EXTRA_STREAM, myImageUri);</pre></li>
+ *
+ * <li>Call {@link #setShareIntent setShareIntent()} to attach this intent to
+ * the action provider:
+ *
+ * <pre>
+ * myShareActionProvider.setShareIntent(myShareIntent);
+ * </pre></li>
+ *
+ * <li>When the content changes, modify the intent or create a new one,
+ * and call {@link #setShareIntent setShareIntent()} again. For example:
+ *
+ * <pre>
+ * // Image has changed! Update the intent:
+ * myShareIntent.putExtra(Intent.EXTRA_STREAM, myNewImageUri);
+ * myShareActionProvider.setShareIntent(myShareIntent);</pre></li>
+ * </ol>
+ *
+ * <h3 id="rankings">Share target rankings</h3>
+ *
+ * <p>The share action provider retains a ranking for each share target,
+ * based on how often the user chooses each one. The more often a user
+ * chooses a target, the higher its rank; the
+ * most-commonly used target appears in the app bar as the default target.</p>
+ *
+ * <p>By default, the target ranking information is stored in a private
+ * file with the name specified by {@link
+ * #DEFAULT_SHARE_HISTORY_FILE_NAME}. Ordinarily, the share action provider stores
+ * all the history in this single file. However, using a single set of
+ * rankings may not make sense if the
+ * share action provider is used for different kinds of content. For
+ * example, if the activity sometimes shares images and sometimes shares
+ * contacts, you would want to maintain two different sets of rankings.</p>
+ *
+ * <p>To set the history file, call {@link #setShareHistoryFileName
+ * setShareHistoryFileName()} and pass the name of an XML file. The file
+ * you specify is used until the next time you call {@link
+ * #setShareHistoryFileName setShareHistoryFileName()}.</p>
  *
  * @see ActionProvider
  */
diff --git a/v7/palette/src/main/java/android/support/v7/graphics/Palette.java b/v7/palette/src/main/java/android/support/v7/graphics/Palette.java
index 55bd1ca..f0e9b8e 100644
--- a/v7/palette/src/main/java/android/support/v7/graphics/Palette.java
+++ b/v7/palette/src/main/java/android/support/v7/graphics/Palette.java
@@ -524,7 +524,7 @@
         }
 
         /**
-         * Add a filter to be able to have fine grained controlled over the colors which are
+         * Add a filter to be able to have fine grained control over which colors are
          * allowed in the resulting palette.
          *
          * @param filter filter to add.
diff --git a/v7/preference/src/android/support/v7/preference/Preference.java b/v7/preference/src/android/support/v7/preference/Preference.java
index 84ab3b3..aa37ac8 100644
--- a/v7/preference/src/android/support/v7/preference/Preference.java
+++ b/v7/preference/src/android/support/v7/preference/Preference.java
@@ -517,8 +517,11 @@
             setEnabledStateOnViews(holder.itemView, true);
         }
 
-        holder.setDividerAllowedAbove(isSelectable());
-        holder.setDividerAllowedBelow(isSelectable());
+        final boolean selectable = isSelectable();
+        holder.itemView.setFocusable(selectable);
+
+        holder.setDividerAllowedAbove(selectable);
+        holder.setDividerAllowedBelow(selectable);
     }
 
     /**