Merge "Import updated SearchView assets from UX"
diff --git a/api/current.txt b/api/current.txt
index ac04dd1..c0ed81a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -543,6 +543,7 @@
     field public static final int fromAlpha = 16843210; // 0x10101ca
     field public static final int fromDegrees = 16843187; // 0x10101b3
     field public static final int fromScene = 16843741; // 0x10103dd
+    field public static final int fromSceneName = 16843774; // 0x10103fe
     field public static final int fromXDelta = 16843206; // 0x10101c6
     field public static final int fromXScale = 16843202; // 0x10101c2
     field public static final int fromYDelta = 16843208; // 0x10101c8
@@ -960,6 +961,7 @@
     field public static final int shadowRadius = 16843108; // 0x1010164
     field public static final int shape = 16843162; // 0x101019a
     field public static final int shareInterpolator = 16843195; // 0x10101bb
+    field public static final int sharedElementName = 16843776; // 0x1010400
     field public static final int sharedUserId = 16842763; // 0x101000b
     field public static final int sharedUserLabel = 16843361; // 0x1010261
     field public static final int shouldDisableView = 16843246; // 0x10101ee
@@ -1142,6 +1144,7 @@
     field public static final int toAlpha = 16843211; // 0x10101cb
     field public static final int toDegrees = 16843188; // 0x10101b4
     field public static final int toScene = 16843742; // 0x10103de
+    field public static final int toSceneName = 16843775; // 0x10103ff
     field public static final int toXDelta = 16843207; // 0x10101c7
     field public static final int toXScale = 16843203; // 0x10101c3
     field public static final int toYDelta = 16843209; // 0x10101c9
@@ -1157,6 +1160,7 @@
     field public static final int transformPivotX = 16843552; // 0x1010320
     field public static final int transformPivotY = 16843553; // 0x1010321
     field public static final int transition = 16843743; // 0x10103df
+    field public static final int transitionGroup = 16843777; // 0x1010401
     field public static final int transitionOrdering = 16843744; // 0x10103e0
     field public static final int translationX = 16843554; // 0x1010322
     field public static final int translationY = 16843555; // 0x1010323
@@ -1514,6 +1518,7 @@
     field public static final int selectAll = 16908319; // 0x102001f
     field public static final int selectTextMode = 16908333; // 0x102002d
     field public static final int selectedIcon = 16908302; // 0x102000e
+    field public static final int shared_element_name = 16908334; // 0x102002e
     field public static final int startSelectingText = 16908328; // 0x1020028
     field public static final int stopSelectingText = 16908329; // 0x1020029
     field public static final int summary = 16908304; // 0x1020010
@@ -3035,6 +3040,7 @@
     method public int getTaskId();
     method public final java.lang.CharSequence getTitle();
     method public final int getTitleColor();
+    method public android.os.Bundle getTransitionArgs();
     method public final int getVolumeControlStream();
     method public android.view.Window getWindow();
     method public android.view.WindowManager getWindowManager();
@@ -3130,6 +3136,7 @@
     method public void setContentView(android.view.View);
     method public void setContentView(android.view.View, android.view.ViewGroup.LayoutParams);
     method public final void setDefaultKeyMode(int);
+    method public void setEarlyBackgroundTransition(boolean);
     method public final void setFeatureDrawable(int, android.graphics.drawable.Drawable);
     method public final void setFeatureDrawableAlpha(int, int);
     method public final void setFeatureDrawableResource(int, int);
@@ -3170,6 +3177,7 @@
     method public boolean startNextMatchingActivity(android.content.Intent);
     method public boolean startNextMatchingActivity(android.content.Intent, android.os.Bundle);
     method public void startSearch(java.lang.String, boolean, android.os.Bundle, boolean);
+    method protected void startSharedElementTransition(android.os.Bundle);
     method public deprecated void stopManagingCursor(android.database.Cursor);
     method public void takeKeyEvents(boolean);
     method public void triggerSearch(java.lang.String, android.os.Bundle);
@@ -3340,6 +3348,7 @@
   public class ActivityOptions {
     method public static android.app.ActivityOptions makeCustomAnimation(android.content.Context, int, int);
     method public static android.app.ActivityOptions makeScaleUpAnimation(android.view.View, int, int, int, int);
+    method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.os.Bundle);
     method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int);
     method public android.os.Bundle toBundle();
     method public void update(android.app.ActivityOptions);
@@ -18378,7 +18387,7 @@
 
   public abstract class CountDownTimer {
     ctor public CountDownTimer(long, long);
-    method public final void cancel();
+    method public final synchronized void cancel();
     method public abstract void onFinish();
     method public abstract void onTick(long);
     method public final synchronized android.os.CountDownTimer start();
@@ -26682,6 +26691,7 @@
     method public android.transition.Transition addListener(android.transition.Transition.TransitionListener);
     method public android.transition.Transition addTarget(int);
     method public android.transition.Transition addTarget(android.view.View);
+    method public boolean canRemoveViews();
     method public abstract void captureEndValues(android.transition.TransitionValues);
     method public abstract void captureStartValues(android.transition.TransitionValues);
     method public android.transition.Transition clone();
@@ -28746,6 +28756,7 @@
     method public int getScrollBarStyle();
     method public final int getScrollX();
     method public final int getScrollY();
+    method public java.lang.String getSharedElementName();
     method public int getSolidColor();
     method protected int getSuggestedMinimumHeight();
     method protected int getSuggestedMinimumWidth();
@@ -28999,6 +29010,7 @@
     method public void setScrollY(int);
     method public void setScrollbarFadingEnabled(boolean);
     method public void setSelected(boolean);
+    method public void setSharedElementName(java.lang.String);
     method public void setSoundEffectsEnabled(boolean);
     method public void setSystemUiVisibility(int);
     method public void setTag(java.lang.Object);
@@ -29385,6 +29397,7 @@
     method protected boolean isChildrenDrawingOrderEnabled();
     method protected boolean isChildrenDrawnWithCacheEnabled();
     method public boolean isMotionEventSplittingEnabled();
+    method public boolean isTransitionGroup();
     method public final void layout(int, int, int, int);
     method protected void measureChild(android.view.View, int, int);
     method protected void measureChildWithMargins(android.view.View, int, int, int, int);
@@ -29430,6 +29443,7 @@
     method public void setOnHierarchyChangeListener(android.view.ViewGroup.OnHierarchyChangeListener);
     method public void setPersistentDrawingCache(int);
     method protected void setStaticTransformationsEnabled(boolean);
+    method public void setTransitionGroup(boolean);
     method public boolean shouldDelayChildPressedState();
     method public boolean showContextMenuForChild(android.view.View);
     method public android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode.Callback);
@@ -29724,7 +29738,6 @@
     method public abstract void setTitle(java.lang.CharSequence);
     method public abstract deprecated void setTitleColor(int);
     method public void setTransitionManager(android.transition.TransitionManager);
-    method public void setTransitionOptions(android.os.Bundle);
     method public void setType(int);
     method public void setUiOptions(int);
     method public void setUiOptions(int, int);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 698f06a..a8716bf 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.transition.Scene;
-import android.transition.Transition;
 import android.transition.TransitionManager;
 import android.util.ArrayMap;
 import android.util.SuperNotCalledException;
@@ -771,6 +770,7 @@
 
     private Thread mUiThread;
     final Handler mHandler = new Handler();
+    private ActivityOptions mTransitionActivityOptions;
 
     /** Return the intent that started this activity. */
     public Intent getIntent() {
@@ -3443,38 +3443,16 @@
      *
      * @throws android.content.ActivityNotFoundException
      *
-     * @see #startActivity 
+     * @see #startActivity
      */
     public void startActivityForResult(Intent intent, int requestCode) {
-        final TransitionManager tm = getWindow().getTransitionManager();
-        final Scene currScene = getWindow().getContentScene();
-        final String[] targetSceneNames = currScene != null && tm != null ?
-                tm.getTargetSceneNames(currScene) : null;
-
-        if (targetSceneNames == null || targetSceneNames.length == 0) {
-            startActivityForResult(intent, requestCode, null);
-        } else {
-            // TODO Capture the scene transition args and send along
-            final ActivityOptions opts = ActivityOptions.makeSceneTransitionAnimation(
-                    targetSceneNames, null,
-                    new ActivityOptions.OnSceneTransitionStartedListener() {
-                        @Override public void onSceneTransitionStarted(String destSceneName) {
-                            final Transition t = tm.getNamedTransition(currScene, destSceneName);
-                            // TODO Fill this in to notify the outgoing activity that it should
-                            // treat this as a sync point for the transition - the target
-                            // transition has started.
-                            Log.d(TAG, "Scene transition to scene " + destSceneName +
-                                    " transition " + t);
-                        }
-                    }, mHandler);
-            startActivityForResult(intent, requestCode, opts.toBundle());
-        }
+        startActivityForResult(intent, requestCode, null);
     }
 
     /**
      * Launch an activity for which you would like a result when it finished.
      * When this activity exits, your
-     * onActivityResult() method will be called with the given requestCode. 
+     * onActivityResult() method will be called with the given requestCode.
      * Using a negative requestCode is the same as calling 
      * {@link #startActivity} (the activity is not launched as a sub-activity).
      *
@@ -3487,9 +3465,9 @@
      *
      * <p>As a special case, if you call startActivityForResult() with a requestCode 
      * >= 0 during the initial onCreate(Bundle savedInstanceState)/onResume() of your
-     * activity, then your window will not be displayed until a result is 
-     * returned back from the started activity.  This is to avoid visible 
-     * flickering when redirecting to another activity. 
+     * activity, then your window will not be displayed until a result is
+     * returned back from the started activity.  This is to avoid visible
+     * flickering when redirecting to another activity.
      *
      * <p>This method throws {@link android.content.ActivityNotFoundException}
      * if there was no Activity found to run the given Intent.
@@ -3503,9 +3481,17 @@
      *
      * @throws android.content.ActivityNotFoundException
      *
-     * @see #startActivity 
+     * @see #startActivity
      */
     public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
+        TransitionManager tm = getContentTransitionManager();
+        if (tm != null && options != null) {
+            ActivityOptions activityOptions = new ActivityOptions(options);
+            if (activityOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
+                getWindow().startExitTransition(activityOptions);
+                options = activityOptions.toBundle();
+            }
+        }
         if (mParent == null) {
             Instrumentation.ActivityResult ar =
                 mInstrumentation.execStartActivity(
@@ -5313,7 +5299,7 @@
             mWindow.setUiOptions(info.uiOptions);
         }
         mUiThread = Thread.currentThread();
-        
+
         mMainThread = aThread;
         mInstrumentation = instr;
         mToken = token;
@@ -5335,8 +5321,40 @@
             mWindow.setContainer(mParent.getWindow());
         }
         mWindowManager = mWindow.getWindowManager();
-        mWindow.setTransitionOptions(options);
         mCurrentConfig = config;
+        mTransitionActivityOptions = null;
+        Window.SceneTransitionListener sceneTransitionListener = null;
+        if (options != null) {
+            ActivityOptions activityOptions = new ActivityOptions(options);
+            if (activityOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
+                mTransitionActivityOptions = activityOptions;
+                sceneTransitionListener = new Window.SceneTransitionListener() {
+                    @Override
+                    public void enterSharedElement(Bundle transitionArgs) {
+                        startSharedElementTransition(transitionArgs);
+                        mTransitionActivityOptions = null;
+                    }
+
+                    @Override
+                    public void nullPendingTransition() {
+                        overridePendingTransition(0, 0);
+                    }
+
+                    @Override
+                    public void convertFromTranslucent() {
+                        Activity.this.convertFromTranslucent();
+                    }
+
+                    @Override
+                    public void convertToTranslucent() {
+                        Activity.this.convertToTranslucent(null);
+                    }
+                };
+
+            }
+        }
+
+        mWindow.setTransitionOptions(mTransitionActivityOptions, sceneTransitionListener);
     }
 
     /** @hide */
@@ -5350,7 +5368,7 @@
                 com.android.internal.R.styleable.Window_windowNoDisplay, false);
         mFragments.dispatchActivityCreated();
     }
-    
+
     final void performStart() {
         mFragments.noteStateNotSaved();
         mCalled = false;
@@ -5507,7 +5525,7 @@
                     }
                 }
             }
-    
+
             mStopped = true;
         }
         mResumed = false;
@@ -5522,7 +5540,57 @@
             mLoaderManager.doDestroy();
         }
     }
-    
+
+    /**
+     * Gets the entering Activity transition args. Will be null if
+     * {@link android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle)} was
+     * not used to pass a Bundle to startActivity. The Bundle passed to that method in the
+     * calling Activity is returned here.
+     * <p>After startSharedElementTransition is called, this method will return null.</p>
+     *
+     * @return The Bundle passed into Bundle parameter of
+     *         {@link android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle)}
+     *         in the calling Activity.
+     */
+    public Bundle getTransitionArgs() {
+        if (mTransitionActivityOptions == null) {
+            return null;
+        }
+        return mTransitionActivityOptions.getSceneTransitionArgs();
+    }
+
+    /**
+     * Override to transfer a shared element from a calling Activity to this Activity.
+     * Shared elements will be made VISIBLE before this call. The Activity is responsible
+     * for transitioning the shared elements from their location to the eventual destination.
+     * The shared element will be laid out a the destination when this method is called.
+     *
+     * @param transitionArgs The same as returned from {@link #getTransitionArgs()}, this should
+     *                       contain information from the calling Activity to tell where the
+     *                       shared element should be placed.
+     */
+    protected void startSharedElementTransition(Bundle transitionArgs) {
+    }
+
+    /**
+     * Controls how the background fade is triggered when there is an entering Activity transition.
+     * If fadeEarly is true, the Window background will fade in as soon as the shared elements are
+     * ready to switch. If fadeEarly is false, the background will fade only after the calling
+     * Activity's exit transition completes. By default, the Window will fade in when the calling
+     * Activity's exit transition completes.
+     *
+     * @param fadeEarly Set to true to fade out the exiting Activity as soon as the shared elements
+     *                  are transferred. Set to false to fade out the exiting Activity as soon as
+     *                  the shared element is transferred.
+     * @see android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle)
+     */
+    public void setEarlyBackgroundTransition(boolean fadeEarly) {
+        if (mTransitionActivityOptions == null) {
+            return;
+        }
+        mWindow.setEarlyBackgroundTransition(fadeEarly);
+    }
+
     /**
      * @hide
      */
@@ -5530,7 +5598,7 @@
         return mResumed;
     }
 
-    void dispatchActivityResult(String who, int requestCode, 
+    void dispatchActivityResult(String who, int requestCode,
         int resultCode, Intent data) {
         if (false) Log.v(
             TAG, "Dispatching result: who=" + who + ", reqCode=" + requestCode
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 582ce3c..3f97c40 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -16,16 +16,21 @@
 
 package android.app;
 
+import android.animation.Animator;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IRemoteCallback;
 import android.os.RemoteException;
-import android.text.TextUtils;
+import android.transition.Transition;
+import android.util.ArrayMap;
 import android.util.Log;
 import android.view.View;
 
+import java.util.ArrayList;
+import java.util.Map;
+
 /**
  * Helper class for building an options Bundle that can be used with
  * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle)
@@ -95,34 +100,30 @@
     public static final String KEY_ANIM_START_LISTENER = "android:animStartListener";
 
     /**
-     * A string array of names for the destination scene. This defines an API in the same
-     * way that intent action or extra names do and should follow a similar convention:
-     * "com.example.scene.FOO"
-     *
-     * @hide
-     */
-    public static final String KEY_DEST_SCENE_NAMES = "android:destSceneNames";
-
-    /**
-     * A string indicating the destination scene name that was chosen by the target.
-     * Used by {@link OnSceneTransitionStartedListener}.
-     * @hide
-     */
-    public static final String KEY_DEST_SCENE_NAME_CHOSEN = "android:destSceneNameChosen";
-
-    /**
-     * Callback for when scene transition is started.
-     * @hide
-     */
-    public static final String KEY_SCENE_TRANSITION_START_LISTENER =
-            "android:sceneTransitionStartListener";
-
-    /**
      * Arguments for the scene transition about to begin.
      * @hide
      */
     public static final String KEY_SCENE_TRANSITION_ARGS = "android:sceneTransitionArgs";
 
+    /**
+     * For Activity transitions, the calling Activity's TransitionListener used to
+     * notify the called Activity when the shared element and the exit transitions
+     * complete.
+     */
+    private static final String KEY_TRANSITION_COMPLETE_LISTENER
+            = "android:transitionCompleteListener";
+
+    /**
+     * For Activity transitions, the called Activity's listener to receive calls
+     * when transitions complete.
+     */
+    private static final String KEY_TRANSITION_TARGET_LISTENER = "android:transitionTargetListener";
+
+    /**
+     * The shared element's texture ID (TODO: not used yet).
+     */
+    private static final String KEY_SHARED_ELEMENT_TEXTURE_ID = "android:sharedElementTextureId";
+
     /** @hide */
     public static final int ANIM_NONE = 0;
     /** @hide */
@@ -145,10 +146,9 @@
     private int mStartY;
     private int mStartWidth;
     private int mStartHeight;
-    private String[] mDestSceneNames;
     private Bundle mTransitionArgs;
     private IRemoteCallback mAnimationStartedListener;
-    private IRemoteCallback mSceneTransitionStartedListener;
+    private IRemoteCallback mTransitionCompleteListener;
 
     /**
      * Create an ActivityOptions specifying a custom animation to run when
@@ -215,24 +215,6 @@
         }
     }
 
-    private void setOnSceneTransitionStartedListener(Handler handler,
-            OnSceneTransitionStartedListener listener) {
-        if (listener != null) {
-            final Handler h = handler;
-            final OnSceneTransitionStartedListener l = listener;
-            mSceneTransitionStartedListener = new IRemoteCallback.Stub() {
-                @Override public void sendResult(final Bundle data) throws RemoteException {
-                    h.post(new Runnable() {
-                        public void run() {
-                            l.onSceneTransitionStarted(data != null ?
-                                    data.getString(KEY_DEST_SCENE_NAME_CHOSEN) : null);
-                        }
-                    });
-                }
-            };
-        }
-    }
-
     /**
      * Callback for use with {@link ActivityOptions#makeThumbnailScaleUpAnimation}
      * to find out when the given animation has started running.
@@ -242,13 +224,10 @@
         void onAnimationStarted();
     }
 
-    /**
-     * Callback for use with {@link ActivityOptions#makeSceneTransitionAnimation}
-     * to find out when a transition is about to begin.
-     * @hide
-     */
-    public interface OnSceneTransitionStartedListener {
-        void onSceneTransitionStarted(String destSceneName);
+    /** @hide */
+    public interface ActivityTransitionTarget {
+        void sharedElementTransitionComplete();
+        void exitTransitionComplete();
     }
 
     /**
@@ -369,18 +348,35 @@
     }
 
     /**
-     * Create an ActivityOptions specifying an animation where an activity window is asked
-     * to perform animations within the window content.
+     * Create an ActivityOptions to transition between Activities using cross-Activity animation.
+     * When visual elements are to carry between Activities, args should be used to tell the called
+     * Activity about the location and size.
      *
-     * @hide
+     * TODO: Provide facility to capture layout and bitmap of shared elements.
+     *
+     * <p>When
+     * {@link android.app.Activity#startActivities(android.content.Intent[], android.os.Bundle)}
+     * is used with the {@link #toBundle()} result, the Activity's content scene will automatically
+     * transition out by setting their visibility to {@link View#INVISIBLE}. Shared elements
+     * ({@link android.view.View#setSharedElementName(String)}) are unmodified during the
+     * transition to allow the started Activity to seamlessly take it over. ViewGroups typically
+     * don't transition out, and instead transition out their children unless they have a
+     * background. To modify this behavior, use
+     * {@link android.view.ViewGroup#setTransitionGroup(boolean)}.</p>
+     *
+     * <p>This requires {@link android.view.Window#FEATURE_CONTENT_TRANSITIONS} to be
+     * enabled on the calling Activity to cause an exit transition. The same must be in
+     * the called Activity to get an entering transition.</p>
+     *
+     * @param args Contains information for transferring a view between this Activity and the
+     *             target Activity. Will be used by the called Activity to transition the
+     *             view to its eventual destination
+     * @see android.app.Activity#startSharedElementTransition(android.os.Bundle)
      */
-    public static ActivityOptions makeSceneTransitionAnimation(String[] destSceneNames,
-            Bundle args, OnSceneTransitionStartedListener listener, Handler handler) {
+    public static ActivityOptions makeSceneTransitionAnimation(Bundle args) {
         ActivityOptions opts = new ActivityOptions();
         opts.mAnimationType = ANIM_SCENE_TRANSITION;
-        opts.mDestSceneNames = destSceneNames;
         opts.mTransitionArgs = args;
-        opts.setOnSceneTransitionStartedListener(handler, listener);
         return opts;
     }
 
@@ -416,10 +412,9 @@
                 break;
 
             case ANIM_SCENE_TRANSITION:
-                mDestSceneNames = opts.getStringArray(KEY_DEST_SCENE_NAMES);
                 mTransitionArgs = opts.getBundle(KEY_SCENE_TRANSITION_ARGS);
-                mSceneTransitionStartedListener = IRemoteCallback.Stub.asInterface(
-                        opts.getBinder(KEY_SCENE_TRANSITION_START_LISTENER));
+                mTransitionCompleteListener = IRemoteCallback.Stub.asInterface(
+                        opts.getBinder(KEY_TRANSITION_COMPLETE_LISTENER));
                 break;
         }
     }
@@ -470,11 +465,6 @@
     }
 
     /** @hide */
-    public String[] getDestSceneNames() {
-        return mDestSceneNames;
-    }
-
-    /** @hide */
     public Bundle getSceneTransitionArgs() {
         return mTransitionArgs;
     }
@@ -485,19 +475,33 @@
     }
 
     /** @hide */
-    public void dispatchSceneTransitionStarted(String destScene) {
-        if (mSceneTransitionStartedListener != null) {
-            Bundle data = null;
-            if (!TextUtils.isEmpty(destScene)) {
-                data = new Bundle();
-                data.putString(KEY_DEST_SCENE_NAME_CHOSEN, destScene);
-            }
+    public void dispatchSceneTransitionStarted(final ActivityTransitionTarget target) {
+        boolean listenerSent = false;
+        if (mTransitionCompleteListener != null) {
+            IRemoteCallback callback = new IRemoteCallback.Stub() {
+                @Override
+                public void sendResult(Bundle data) throws RemoteException {
+                    if (data == null) {
+                        target.exitTransitionComplete();
+                    } else {
+                        // TODO: Use texture id
+                        target.sharedElementTransitionComplete();
+                    }
+                }
+            };
+            Bundle bundle = new Bundle();
+            bundle.putBinder(KEY_TRANSITION_TARGET_LISTENER, callback.asBinder());
             try {
-                mSceneTransitionStartedListener.sendResult(data);
+                mTransitionCompleteListener.sendResult(bundle);
+                listenerSent = true;
             } catch (RemoteException e) {
-                Log.e(TAG, "Caught exception dispatching scene transition start", e);
+                Log.w(TAG, "Couldn't retrieve transition notifications", e);
             }
         }
+        if (!listenerSent) {
+            target.sharedElementTransitionComplete();
+            target.exitTransitionComplete();
+        }
     }
 
     /** @hide */
@@ -508,12 +512,6 @@
             } catch (RemoteException e) {
             }
         }
-        if (mSceneTransitionStartedListener != null) {
-            try {
-                mSceneTransitionStartedListener.sendResult(null);
-            } catch (RemoteException e) {
-            }
-        }
     }
 
     /** @hide */
@@ -545,9 +543,8 @@
                     }
                 }
                 mAnimationStartedListener = otherOptions.mAnimationStartedListener;
-                mSceneTransitionStartedListener = null;
+                mTransitionCompleteListener = null;
                 mTransitionArgs = null;
-                mDestSceneNames = null;
                 break;
             case ANIM_SCALE_UP:
                 mAnimationType = otherOptions.mAnimationType;
@@ -562,9 +559,8 @@
                     }
                 }
                 mAnimationStartedListener = null;
-                mSceneTransitionStartedListener = null;
+                mTransitionCompleteListener = null;
                 mTransitionArgs = null;
-                mDestSceneNames = null;
                 break;
             case ANIM_THUMBNAIL_SCALE_UP:
             case ANIM_THUMBNAIL_SCALE_DOWN:
@@ -579,20 +575,12 @@
                     }
                 }
                 mAnimationStartedListener = otherOptions.mAnimationStartedListener;
-                mSceneTransitionStartedListener = null;
+                mTransitionCompleteListener = null;
                 mTransitionArgs = null;
-                mDestSceneNames = null;
                 break;
             case ANIM_SCENE_TRANSITION:
                 mAnimationType = otherOptions.mAnimationType;
-                if (mSceneTransitionStartedListener != null) {
-                    try {
-                        mSceneTransitionStartedListener.sendResult(null);
-                    } catch (RemoteException e) {
-                    }
-                }
-                mSceneTransitionStartedListener = otherOptions.mSceneTransitionStartedListener;
-                mDestSceneNames = otherOptions.mDestSceneNames;
+                mTransitionCompleteListener = otherOptions.mTransitionCompleteListener;
                 mTransitionArgs = otherOptions.mTransitionArgs;
                 mThumbnail = null;
                 mAnimationStartedListener = null;
@@ -639,10 +627,11 @@
                 break;
             case ANIM_SCENE_TRANSITION:
                 b.putInt(KEY_ANIM_TYPE, mAnimationType);
-                b.putStringArray(KEY_DEST_SCENE_NAMES, mDestSceneNames);
                 b.putBundle(KEY_SCENE_TRANSITION_ARGS, mTransitionArgs);
-                b.putBinder(KEY_SCENE_TRANSITION_START_LISTENER, mSceneTransitionStartedListener
-                        != null ? mSceneTransitionStartedListener.asBinder() : null);
+                if (mTransitionCompleteListener != null) {
+                    b.putBinder(KEY_TRANSITION_COMPLETE_LISTENER,
+                            mTransitionCompleteListener.asBinder());
+                }
                 break;
         }
         return b;
@@ -661,4 +650,123 @@
 
         return null;
     }
+
+    /** @hide */
+    public interface SharedElementSource {
+        int getTextureId();
+    }
+
+    /**
+     * In the calling Activity when transitioning out, sets the Transition to listen for
+     * changes.
+     * @hide
+     */
+    public void setExitTransition(Transition transition, SharedElementSource sharedElementSource) {
+        mTransitionCompleteListener = new ExitTransitionListener(transition, sharedElementSource);
+    }
+
+    private static class ExitTransitionListener extends IRemoteCallback.Stub
+            implements Transition.TransitionListener, Animator.AnimatorListener {
+        private ArrayList<Animator> mSharedElementAnimators = new ArrayList<Animator>();
+        private boolean mSharedElementNotified;
+        private Transition mExitTransition;
+        private IRemoteCallback mTransitionCompleteCallback;
+        private boolean mExitComplete;
+        private SharedElementSource mSharedElementSource;
+
+        public ExitTransitionListener(Transition transition, SharedElementSource sharedElementSource) {
+            mSharedElementSource = sharedElementSource;
+            mExitTransition = transition;
+            mExitTransition.addListener(this);
+        }
+
+        @Override
+        public void sendResult(Bundle data) throws RemoteException {
+            if (data != null) {
+                mTransitionCompleteCallback = IRemoteCallback.Stub.asInterface(
+                        data.getBinder(KEY_TRANSITION_TARGET_LISTENER));
+                notifySharedElement();
+                notifyExit();
+            }
+        }
+
+        @Override
+        public void onTransitionStart(Transition transition) {
+            ArrayMap<Animator, Transition.AnimationInfo> runningAnimators
+                    = Transition.getRunningAnimators();
+            for (Map.Entry<Animator, Transition.AnimationInfo> entry : runningAnimators.entrySet()) {
+                if (entry.getValue().view.getSharedElementName() != null) {
+                    mSharedElementAnimators.add(entry.getKey());
+                    entry.getKey().addListener(this);
+                }
+            }
+            notifySharedElement();
+        }
+
+        @Override
+        public void onTransitionEnd(Transition transition) {
+            mExitComplete = true;
+            notifyExit();
+            mExitTransition.removeListener(this);
+        }
+
+        @Override
+        public void onTransitionCancel(Transition transition) {
+            mExitComplete = true;
+            notifyExit();
+            mExitTransition.removeListener(this);
+        }
+
+        @Override
+        public void onTransitionPause(Transition transition) {
+        }
+
+        @Override
+        public void onTransitionResume(Transition transition) {
+        }
+
+        @Override
+        public void onAnimationStart(Animator animation) {
+        }
+
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            mSharedElementAnimators.remove(animation);
+            notifySharedElement();
+        }
+
+        @Override
+        public void onAnimationCancel(Animator animation) {
+            mSharedElementAnimators.remove(animation);
+            notifySharedElement();
+        }
+
+        @Override
+        public void onAnimationRepeat(Animator animation) {
+        }
+
+        private void notifySharedElement() {
+            if (!mSharedElementNotified && mSharedElementAnimators.isEmpty()
+                    && mTransitionCompleteCallback != null) {
+                mSharedElementNotified = true;
+                try {
+                    Bundle bundle = new Bundle();
+                    bundle.putInt(KEY_SHARED_ELEMENT_TEXTURE_ID, mSharedElementSource.getTextureId());
+                    mTransitionCompleteCallback.sendResult(bundle);
+                } catch (RemoteException e) {
+                    Log.w(TAG, "Couldn't notify that the transition ended", e);
+                }
+            }
+        }
+
+        private void notifyExit() {
+            if (mExitComplete && mTransitionCompleteCallback != null) {
+                try {
+                    mTransitionCompleteCallback.sendResult(null);
+                } catch (RemoteException e) {
+                    Log.w(TAG, "Couldn't notify that the transition ended", e);
+                }
+            }
+        }
+    }
 }
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index bb8b184..913b273 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -398,16 +398,44 @@
             new Key<Byte>("android.quirks.usePartialResult", byte.class);
 
     /**
-     * <p>How many output streams can be allocated at
-     * the same time for each type of stream</p>
-     * <p>Video snapshot with preview callbacks requires 3
-     * processed streams (preview, record, app callbacks) and
-     * one JPEG stream (snapshot)</p>
+     * <p>The maximum numbers of different types of output streams
+     * that can be configured and used simultaneously by a camera device.</p>
+     * <p>This is a 3 element tuple that contains the max number of output simultaneous
+     * streams for raw sensor, processed (and uncompressed), and JPEG formats respectively.
+     * For example, if max raw sensor format output stream number is 1, max YUV streams
+     * number is 3, and max JPEG stream number is 2, then this tuple should be <code>(1, 3, 2)</code>.</p>
+     * <p>This lists the upper bound of the number of output streams supported by
+     * the camera device. Using more streams simultaneously may require more hardware and
+     * CPU resources that will consume more power. The image format for a output stream can
+     * be any supported format provided by {@link CameraCharacteristics#SCALER_AVAILABLE_FORMATS android.scaler.availableFormats}. The formats
+     * defined in {@link CameraCharacteristics#SCALER_AVAILABLE_FORMATS android.scaler.availableFormats} can be catergorized into the 3 stream types
+     * as below:</p>
+     * <ul>
+     * <li>JPEG-compressed format: BLOB.</li>
+     * <li>Raw formats: RAW_SENSOR and RAW_OPAQUE.</li>
+     * <li>processed, uncompressed formats: YCbCr_420_888, YCrCb_420_SP, YV12.</li>
+     * </ul>
+     *
+     * @see CameraCharacteristics#SCALER_AVAILABLE_FORMATS
      */
     public static final Key<int[]> REQUEST_MAX_NUM_OUTPUT_STREAMS =
             new Key<int[]>("android.request.maxNumOutputStreams", int[].class);
 
     /**
+     * <p>The maximum numbers of any type of input streams
+     * that can be configured and used simultaneously by a camera device.</p>
+     * <p>When set to 0, it means no input stream is supported.</p>
+     * <p>The image format for a input stream can be any supported format provided
+     * by android.scaler.availableInputFormats. When using an input stream, there must be
+     * at least one output stream configured to to receive the reprocessed images.</p>
+     * <p>For example, for Zero Shutter Lag (ZSL) still capture use case, the input
+     * stream image format will be RAW_OPAQUE, the associated output stream image format
+     * should be JPEG.</p>
+     */
+    public static final Key<Integer> REQUEST_MAX_NUM_INPUT_STREAMS =
+            new Key<Integer>("android.request.maxNumInputStreams", int.class);
+
+    /**
      * <p>Specifies the number of maximum pipeline stages a frame
      * has to go through from when it's exposed to when it's available
      * to the framework.</p>
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index da9ba5a..fd3f9b3 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -552,7 +552,8 @@
         return false;
     }
 
-    private static ArrayMap<Animator, AnimationInfo> getRunningAnimators() {
+    /** @hide */
+    public static ArrayMap<Animator, AnimationInfo> getRunningAnimators() {
         ArrayMap<Animator, AnimationInfo> runningAnimators = sRunningAnimators.get();
         if (runningAnimators == null) {
             runningAnimators = new ArrayMap<Animator, AnimationInfo>();
@@ -1077,6 +1078,9 @@
         if (view == null) {
             return;
         }
+        if (!isValidTarget(view, view.getId())) {
+            return;
+        }
         boolean isListViewItem = false;
         if (view.getParent() instanceof ListView) {
             isListViewItem = true;
@@ -1467,6 +1471,10 @@
         mCanRemoveViews = canRemoveViews;
     }
 
+    public boolean canRemoveViews() {
+        return mCanRemoveViews;
+    }
+
     @Override
     public String toString() {
         return toString("");
@@ -1629,9 +1637,10 @@
      * animation should be canceled or a new animation noop'd. The structure holds
      * information about the state that an animation is going to, to be compared to
      * end state of a new animation.
+     * @hide
      */
-    private static class AnimationInfo {
-        View view;
+    public static class AnimationInfo {
+        public View view;
         String name;
         TransitionValues values;
 
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 4b6f2b0..518908f 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -665,6 +665,7 @@
  * @attr ref android.R.styleable#View_scrollbarTrackVertical
  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
+ * @attr ref android.R.styleable#View_sharedElementName
  * @attr ref android.R.styleable#View_soundEffectsEnabled
  * @attr ref android.R.styleable#View_tag
  * @attr ref android.R.styleable#View_textAlignment
@@ -4038,6 +4039,9 @@
                 case R.styleable.View_accessibilityLiveRegion:
                     setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
                     break;
+                case R.styleable.View_sharedElementName:
+                    setSharedElementName(a.getString(attr));
+                    break;
             }
         }
 
@@ -18872,6 +18876,35 @@
     }
 
     /**
+     * Specifies that the shared name of the View to be shared with another Activity.
+     * When transitioning between Activities, the name links a UI element in the starting
+     * Activity to UI element in the called Activity. Names should be unique in the
+     * View hierarchy.
+     *
+     * @param sharedElementName The cross-Activity View identifier. The called Activity will use
+     *                 the name to match the location with a View in its layout.
+     * @see android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle)
+     */
+    public void setSharedElementName(String sharedElementName) {
+        setTagInternal(com.android.internal.R.id.shared_element_name, sharedElementName);
+    }
+
+    /**
+     * Returns the shared name of the View to be shared with another Activity.
+     * When transitioning between Activities, the name links a UI element in the starting
+     * Activity to UI element in the called Activity. Names should be unique in the
+     * View hierarchy.
+     *
+     * <p>This returns null if the View is not a shared element or the name if it is.</p>
+     *
+     * @return The name used for this View for cross-Activity transitions or null if
+     * this View has not been identified as shared.
+     */
+    public String getSharedElementName() {
+        return (String) getTag(com.android.internal.R.id.shared_element_name);
+    }
+
+    /**
      * Interface definition for a callback to be invoked when a hardware key event is
      * dispatched to this view. The callback will be invoked before the key event is
      * given to the view. This is only useful for hardware keyboards; a software input
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index b91091f..73b108f 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -360,6 +360,10 @@
      */
     static final int FLAG_ISOLATED_Z_VOLUME = 0x1000000;
 
+    static final int FLAG_IS_TRANSITION_GROUP = 0x2000000;
+
+    static final int FLAG_IS_TRANSITION_GROUP_SET = 0x4000000;
+
     /**
      * Indicates which types of drawing caches are to be kept in memory.
      * This field should be made private, so it is hidden from the SDK.
@@ -556,6 +560,9 @@
                 case R.styleable.ViewGroup_layoutMode:
                     setLayoutMode(a.getInt(attr, LAYOUT_MODE_UNDEFINED));
                     break;
+                case R.styleable.ViewGroup_transitionGroup:
+                    setTransitionGroup(a.getBoolean(attr, false));
+                    break;
             }
         }
 
@@ -2288,6 +2295,41 @@
     }
 
     /**
+     * Returns true if this ViewGroup should be considered as a single entity for removal
+     * when executing an Activity transition. If this is false, child elements will move
+     * individually during the transition.
+     * @return True if the ViewGroup should be acted on together during an Activity transition.
+     * The default value is false when the background is null and true when the background
+     * is not null.
+     * @see android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle)
+     */
+    public boolean isTransitionGroup() {
+        if ((mGroupFlags & FLAG_IS_TRANSITION_GROUP_SET) != 0) {
+            return ((mGroupFlags & FLAG_IS_TRANSITION_GROUP) != 0);
+        } else {
+            return getBackground() != null;
+        }
+    }
+
+    /**
+     * Changes whether or not this ViewGroup should be treated as a single entity during
+     * ActivityTransitions.
+     * @param isTransitionGroup Whether or not the ViewGroup should be treated as a unit
+     *                          in Activity transitions. If false, the ViewGroup won't transition,
+     *                          only its children. If true, the entire ViewGroup will transition
+     *                          together.
+     * @see android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle)
+     */
+    public void setTransitionGroup(boolean isTransitionGroup) {
+        mGroupFlags |= FLAG_IS_TRANSITION_GROUP_SET;
+        if (isTransitionGroup) {
+            mGroupFlags |= FLAG_IS_TRANSITION_GROUP;
+        } else {
+            mGroupFlags &= ~FLAG_IS_TRANSITION_GROUP;
+        }
+    }
+
+    /**
      * {@inheritDoc}
      */
     public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 1064a08..11740ab 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.ActivityOptions;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
@@ -1374,8 +1375,41 @@
     /**
      * Set options that can affect the transition behavior within this window.
      * @param options Options to set or null for none
+     * @hide
      */
-    public void setTransitionOptions(Bundle options) {
-        throw new UnsupportedOperationException();
+    public void setTransitionOptions(ActivityOptions options, SceneTransitionListener listener) {
+    }
+
+    /**
+     * A callback for Activity transitions to be told when the shared element is ready to be shown
+     * and start the transition to its target location.
+     * @hide
+     */
+    public interface SceneTransitionListener {
+        void enterSharedElement(Bundle transitionArgs);
+        void nullPendingTransition();
+        void convertFromTranslucent();
+        void convertToTranslucent();
+    }
+
+    /**
+     * Controls how the background fade is triggered. If fadeEarly is true, the Window background
+     * will fade in as soon as the shared elements are ready to switch. If fadeEarly is false,
+     * the background will fade only after the calling Activity's exit transition completes.
+     * By default, the Window will fade in when the calling Activity's exit transition completes.
+     *
+     * @param fadeEarly Set to true to fade out the exiting Activity as soon as the shared elements
+     *                  are transferred. Set to false to fade out the exiting Activity as soon as
+     *                  the shared element is transferred.
+     * @hide
+     */
+    public void setEarlyBackgroundTransition(boolean fadeEarly) {
+    }
+
+    /**
+     * Start the exit transition.
+     * @hide
+     */
+    public void startExitTransition(ActivityOptions activityOptions) {
     }
 }
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index 3116955..5d49204 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -141,7 +141,8 @@
     *needsDetach = false;
     JNIEnv* env = AndroidRuntime::getJNIEnv();
     if (env == NULL) {
-        JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL};
+        JavaVMAttachArgs args = {
+            JNI_VERSION_1_4, "JNISurfaceTextureContext", NULL };
         JavaVM* vm = AndroidRuntime::getJavaVM();
         int result = vm->AttachCurrentThread(&env, (void*) &args);
         if (result != JNI_OK) {
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index f77d66b..9526e13 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2250,6 +2250,11 @@
              view with a theme override will inherit the themed context. -->
         <attr name="theme" />
 
+        <!-- Specifies that the shared name of the View to be shared with another Activity.
+             When transitioning between Activities, the name links a UI element in the starting
+             Activity to UI element in the called Activity. Names should be unique in the
+             View hierarchy. -->
+        <attr name="sharedElementName" format="string" />
     </declare-styleable>
 
     <!-- Attributes that can be used with a {@link android.view.ViewGroup} or any
@@ -2336,6 +2341,14 @@
             <!-- Use the children's optical bounds when laying out this container. -->
             <enum name="opticalBounds" value="1" />
         </attr>
+
+        <!-- Sets whether or not this ViewGroup should be treated as a single entity
+             when doing an Activity transition. Typically, the elements inside a
+             ViewGroup are each transitioned from the scene individually. The default
+             for a ViewGroup is false unless it has a background.
+             See {@link android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle)}
+             for more information. -->
+        <attr name="transitionGroup" format="boolean" />
     </declare-styleable>
 
     <!-- A {@link android.view.ViewStub} lets you lazily include other XML layouts
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index 5c0baaa..56bb15f 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -82,4 +82,5 @@
   <item type="id" name="action_bar_spinner" />
   <item type="id" name="current_scene" />
   <item type="id" name="scene_layoutid_cache" />
+  <item type="id" name="shared_element_name" />
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index e99b5ba..722f965 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2104,6 +2104,12 @@
   <public type="attr" name="controlY1" />
   <public type="attr" name="controlX2" />
   <public type="attr" name="controlY2" />
+  <public type="attr" name="fromSceneName" />
+  <public type="attr" name="toSceneName" />
+  <public type="attr" name="sharedElementName" />
+  <public type="attr" name="transitionGroup" />
+
+  <public type="id" name="shared_element_name" />
 
   <public type="style" name="Widget.Holo.FragmentBreadCrumbs" />
   <public type="style" name="Widget.Holo.Light.FragmentBreadCrumbs" />
diff --git a/docs/html/guide/topics/renderscript/compute.jd b/docs/html/guide/topics/renderscript/compute.jd
index c62510b..297a2dc 100644
--- a/docs/html/guide/topics/renderscript/compute.jd
+++ b/docs/html/guide/topics/renderscript/compute.jd
@@ -56,7 +56,9 @@
 RenderScript kernel language used in this script. Currently, 1 is the only valid value.</li>
 
 <li>A pragma declaration (<code>#pragma rs java_package_name(com.example.app)</code>) that
-declares the package name of the Java classes reflected from this script.</li>
+declares the package name of the Java classes reflected from this script.
+Note that your .rs file must be part of your application package, and not in a
+library project.</li>
 
 <li>Some number of invokable functions. An invokable function is a single-threaded RenderScript
 function that you can call from your Java code with arbitrary arguments. These are often useful for
@@ -308,4 +310,4 @@
 <li><strong>Tear down the RenderScript context.</strong> The RenderScript context can be destroyed
 with {@link android.renderscript.RenderScript#destroy} or by allowing the RenderScript context
 object to be garbage collected. This will cause any further use of any object belonging to that
-context to throw an exception.</li> </ol>
\ No newline at end of file
+context to throw an exception.</li> </ol>
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index a0ea53c..c73d90a 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -22,6 +22,8 @@
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 import static android.view.WindowManager.LayoutParams.*;
 
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
 import android.app.ActivityOptions;
 import android.transition.Scene;
 import android.transition.Transition;
@@ -88,6 +90,7 @@
 import android.view.ViewParent;
 import android.view.ViewRootImpl;
 import android.view.ViewStub;
+import android.view.ViewTreeObserver;
 import android.view.Window;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
@@ -114,6 +117,8 @@
     private final static String TAG = "PhoneWindow";
 
     private final static boolean SWEEP_OPEN_MENU = false;
+    private static final long MAX_TRANSITION_START_WAIT = 500;
+    private static final long MAX_TRANSITION_FINISH_WAIT = 1000;
 
     /**
      * Simple callback used by the context menu and its submenus. The options
@@ -136,22 +141,21 @@
     private ViewGroup mContentParent;
 
     SurfaceHolder.Callback2 mTakeSurfaceCallback;
-    
+
     InputQueue.Callback mTakeInputQueueCallback;
-    
+
     private boolean mIsFloating;
 
     private LayoutInflater mLayoutInflater;
 
     private TextView mTitleView;
-    
+
     private ActionBarView mActionBar;
     private ActionMenuPresenterCallback mActionMenuPresenterCallback;
     private PanelMenuPresenterCallback mPanelMenuPresenterCallback;
 
     private TransitionManager mTransitionManager;
     private Scene mContentScene;
-    private Bundle mTransitionOptions;
 
     // The icon resource has been explicitly set elsewhere
     // and should not be overwritten with a default.
@@ -233,6 +237,10 @@
         }
     };
 
+    private ActivityOptions mActivityOptions;
+    private SceneTransitionListener mSceneTransitionListener;
+    private boolean mFadeEarly = true;
+
     static class WindowManagerHolder {
         static final IWindowManager sWindowManager = IWindowManager.Stub.asInterface(
                 ServiceManager.getService("window"));
@@ -303,11 +311,6 @@
     }
 
     @Override
-    public void setTransitionOptions(Bundle options) {
-        mTransitionOptions = options;
-    }
-
-    @Override
     public void setContentView(int layoutResID) {
         // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
         // decor, when theme attributes and the like are crystalized. Do not check the feature
@@ -378,26 +381,11 @@
     }
 
     private void transitionTo(Scene scene) {
-        Transition selected = null;
-        if (mTransitionOptions != null) {
-            final ActivityOptions opts = new ActivityOptions(mTransitionOptions);
-            mTransitionOptions = null;
-
-            String selectedName = null;
-            for (String sceneName : opts.getDestSceneNames()) {
-                final Transition t = mTransitionManager.getNamedTransition(sceneName, scene);
-                if (t != null) {
-                    // TODO handle args/state; inject into t/clone with params
-                    selected = t;
-                    selectedName = sceneName;
-                    break;
-                }
+        if (mContentScene == null) {
+            scene.enter();
+            if (mActivityOptions != null) {
+                new EnterScene().start();
             }
-            opts.dispatchSceneTransitionStarted(selectedName);
-        }
-
-        if (selected != null) {
-            TransitionManager.go(scene, selected);
         } else {
             mTransitionManager.transitionTo(scene);
         }
@@ -413,11 +401,11 @@
     public void takeSurface(SurfaceHolder.Callback2 callback) {
         mTakeSurfaceCallback = callback;
     }
-    
+
     public void takeInputQueue(InputQueue.Callback callback) {
         mTakeInputQueueCallback = callback;
     }
-    
+
     @Override
     public boolean isFloating() {
         return mIsFloating;
@@ -3553,6 +3541,12 @@
         return mVolumeControlStreamType;
     }
 
+    private boolean isTranslucent() {
+        TypedArray a = getWindowStyle();
+        return a.getBoolean(a.getResourceId(
+                com.android.internal.R.styleable.Window_windowIsTranslucent, 0), false);
+    }
+
     private static final class DrawableFeatureState {
         DrawableFeatureState(int _featureId) {
             featureId = _featureId;
@@ -3986,4 +3980,218 @@
     void sendCloseSystemWindows(String reason) {
         PhoneWindowManager.sendCloseSystemWindows(getContext(), reason);
     }
+
+    @Override
+    public void setTransitionOptions(ActivityOptions options, SceneTransitionListener listener) {
+        mSceneTransitionListener = listener;
+        mActivityOptions = options;
+    }
+
+    @Override
+    public void setEarlyBackgroundTransition(boolean fadeEarly) {
+        mFadeEarly = fadeEarly;
+    }
+
+    @Override
+    public void startExitTransition(ActivityOptions activityOptions) {
+        Transition transition = mTransitionManager.getNamedTransition(getContentScene(), "null");
+        if (transition == null) {
+            transition = TransitionManager.getDefaultTransition().clone();
+        }
+        activityOptions.setExitTransition(transition, new ActivityOptions.SharedElementSource() {
+            @Override
+            public int getTextureId() {
+                // TODO: move shared elements to a layer and return the texture id
+                recurseHideExitingSharedElements(mContentParent);
+                return 0;
+            }
+        });
+        ViewGroup sceneRoot = getContentScene().getSceneRoot();
+        TransitionManager.beginDelayedTransition(sceneRoot, transition);
+        recurseExitNonSharedElements(mContentParent);
+    }
+
+    private static void recurseExitNonSharedElements(ViewGroup viewGroup) {
+        int numChildren = viewGroup.getChildCount();
+        for (int i = 0; i < numChildren; i++) {
+            View child = viewGroup.getChildAt(i);
+            if (child.getSharedElementName() != null || (child.getVisibility() != View.VISIBLE)) {
+                continue;
+            }
+            if (child instanceof ViewGroup && !((ViewGroup)child).isTransitionGroup()) {
+                recurseExitNonSharedElements((ViewGroup) child);
+            } else {
+                child.setVisibility(View.INVISIBLE);
+            }
+        }
+    }
+
+    private static void recurseHideViews(ViewGroup viewGroup, ArrayList<View> nonSharedElements,
+            ArrayList<View> sharedElements) {
+        int numChildren = viewGroup.getChildCount();
+        for (int i = 0; i < numChildren; i++) {
+            View child = viewGroup.getChildAt(i);
+            if (child.getVisibility() != View.VISIBLE) {
+                continue;
+            }
+            if (child.getSharedElementName() != null) {
+                sharedElements.add(child);
+                child.setVisibility(View.INVISIBLE);
+            } else if (child instanceof ViewGroup && !((ViewGroup)child).isTransitionGroup()) {
+                recurseHideViews((ViewGroup) child, nonSharedElements, sharedElements);
+            } else {
+                nonSharedElements.add(child);
+                child.setVisibility(View.INVISIBLE);
+            }
+        }
+    }
+
+    private static void recurseHideExitingSharedElements(ViewGroup viewGroup) {
+        int numChildren = viewGroup.getChildCount();
+        for (int i = 0; i < numChildren; i++) {
+            View child = viewGroup.getChildAt(i);
+            if (child.getVisibility() != View.VISIBLE) {
+                continue;
+            }
+            if (child.getSharedElementName() != null) {
+                child.setVisibility(View.INVISIBLE);
+            } else if (child instanceof ViewGroup) {
+                ViewGroup childViewGroup = (ViewGroup) child;
+                recurseHideExitingSharedElements(childViewGroup);
+            }
+        }
+    }
+
+    /**
+     * Provides code for handling the Activity transition entering scene.
+     * When the first scene is laid out (onPreDraw), it makes views invisible.
+     * It then starts the entering transition by making non-shared elements visible. When
+     * the entering transition is started, the calling Activity is notified that
+     * this Activity is ready to receive the shared element. When the calling Activity notifies
+     * that the shared element is ready, this Activity is notified through the
+     * SceneTransitionListener.
+     *
+     * This class also takes into account fading the background -- either waiting until the
+     * shared element is ready or the calling Activity's exit transition is complete.
+     */
+    private class EnterScene implements ViewTreeObserver.OnPreDrawListener, Runnable,
+            ActivityOptions.ActivityTransitionTarget, Animator.AnimatorListener {
+        private boolean mSharedElementReadyReceived;
+        private boolean mAllDone;
+        private Handler mHandler = new Handler();
+        private boolean mEnterTransitionStarted;
+        private ArrayList<View> mSharedElements = new ArrayList<View>();
+
+        public EnterScene() {
+            mSceneTransitionListener.nullPendingTransition();
+            Drawable background = getDecorView().getBackground();
+            if (background != null) {
+                setBackgroundDrawable(null);
+                background.setAlpha(0);
+                setBackgroundDrawable(background);
+            }
+            mSceneTransitionListener.convertToTranslucent();
+        }
+
+        @Override
+        public boolean onPreDraw() {
+            ViewTreeObserver observer = mContentParent.getViewTreeObserver();
+            observer.removeOnPreDrawListener(this);
+            if (!mEnterTransitionStarted && mSceneTransitionListener != null) {
+                mEnterTransitionStarted = true;
+                ArrayList<View> enteringViews = new ArrayList<View>();
+                recurseHideViews(mContentParent, enteringViews, mSharedElements);
+                Transition transition = getTransitionManager().getNamedTransition("null",
+                        mContentScene);
+                if (transition == null) {
+                    transition = TransitionManager.getDefaultTransition().clone();
+                }
+                TransitionManager.beginDelayedTransition(mContentParent, transition);
+                for (View hidden : enteringViews) {
+                    hidden.setVisibility(View.VISIBLE);
+                }
+                observer.addOnPreDrawListener(this);
+            } else {
+                mHandler.postDelayed(this, MAX_TRANSITION_START_WAIT);
+                mActivityOptions.dispatchSceneTransitionStarted(this);
+            }
+            return true;
+        }
+
+        public void start() {
+            ViewTreeObserver observer = mContentParent.getViewTreeObserver();
+            observer.addOnPreDrawListener(this);
+        }
+
+        @Override
+        public void run() {
+            exitTransitionComplete();
+        }
+
+        @Override
+        public void sharedElementTransitionComplete() {
+            if (!mSharedElementReadyReceived) {
+                mSharedElementReadyReceived = true;
+                mHandler.removeCallbacks(this);
+                mHandler.postDelayed(this, MAX_TRANSITION_FINISH_WAIT);
+                for (View sharedElement: mSharedElements) {
+                    sharedElement.setVisibility(View.VISIBLE);
+                }
+                mSharedElements.clear();
+                mContentParent.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+                    @Override
+                    public boolean onPreDraw() {
+                        mContentParent.getViewTreeObserver().removeOnPreDrawListener(this);
+                        mSceneTransitionListener.enterSharedElement(
+                                mActivityOptions.getSceneTransitionArgs());
+                        return false;
+                    }
+                });
+                if (mFadeEarly) {
+                    fadeInBackground();
+                }
+            }
+        }
+
+        private void fadeInBackground() {
+            Drawable background = getDecorView().getBackground();
+            if (background == null) {
+                mSceneTransitionListener.convertFromTranslucent();
+            } else {
+                ObjectAnimator animator = ObjectAnimator.ofInt(background, "alpha", 255);
+                animator.addListener(this);
+                animator.start();
+            }
+        }
+
+        @Override
+        public void exitTransitionComplete() {
+            if (mAllDone) {
+                return;
+            }
+            mAllDone = true;
+            sharedElementTransitionComplete();
+            mHandler.removeCallbacks(this);
+            if (!mFadeEarly) {
+                fadeInBackground();
+            }
+        }
+
+        @Override
+        public void onAnimationStart(Animator animation) {
+        }
+
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            mSceneTransitionListener.convertFromTranslucent();
+        }
+
+        @Override
+        public void onAnimationCancel(Animator animation) {
+        }
+
+        @Override
+        public void onAnimationRepeat(Animator animation) {
+        }
+    }
 }