ActivityOptions.java revision e494c382c0caf35f225dfb55f0e3b992c14d79f5
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.app;
18
19import android.content.Context;
20import android.content.Intent;
21import android.graphics.Bitmap;
22import android.os.Bundle;
23import android.os.Handler;
24import android.os.IRemoteCallback;
25import android.os.RemoteException;
26import android.os.ResultReceiver;
27import android.util.Pair;
28import android.view.View;
29import android.view.Window;
30
31import java.util.ArrayList;
32
33/**
34 * Helper class for building an options Bundle that can be used with
35 * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle)
36 * Context.startActivity(Intent, Bundle)} and related methods.
37 */
38public class ActivityOptions {
39    private static final String TAG = "ActivityOptions";
40
41    /**
42     * The package name that created the options.
43     * @hide
44     */
45    public static final String KEY_PACKAGE_NAME = "android:packageName";
46
47    /**
48     * Type of animation that arguments specify.
49     * @hide
50     */
51    public static final String KEY_ANIM_TYPE = "android:animType";
52
53    /**
54     * Custom enter animation resource ID.
55     * @hide
56     */
57    public static final String KEY_ANIM_ENTER_RES_ID = "android:animEnterRes";
58
59    /**
60     * Custom exit animation resource ID.
61     * @hide
62     */
63    public static final String KEY_ANIM_EXIT_RES_ID = "android:animExitRes";
64
65    /**
66     * Custom in-place animation resource ID.
67     * @hide
68     */
69    public static final String KEY_ANIM_IN_PLACE_RES_ID = "android:animInPlaceRes";
70
71    /**
72     * Bitmap for thumbnail animation.
73     * @hide
74     */
75    public static final String KEY_ANIM_THUMBNAIL = "android:animThumbnail";
76
77    /**
78     * Start X position of thumbnail animation.
79     * @hide
80     */
81    public static final String KEY_ANIM_START_X = "android:animStartX";
82
83    /**
84     * Start Y position of thumbnail animation.
85     * @hide
86     */
87    public static final String KEY_ANIM_START_Y = "android:animStartY";
88
89    /**
90     * Initial width of the animation.
91     * @hide
92     */
93    public static final String KEY_ANIM_WIDTH = "android:animWidth";
94
95    /**
96     * Initial height of the animation.
97     * @hide
98     */
99    public static final String KEY_ANIM_HEIGHT = "android:animHeight";
100
101    /**
102     * Callback for when animation is started.
103     * @hide
104     */
105    public static final String KEY_ANIM_START_LISTENER = "android:animStartListener";
106
107    /**
108     * For Activity transitions, the calling Activity's TransitionListener used to
109     * notify the called Activity when the shared element and the exit transitions
110     * complete.
111     */
112    private static final String KEY_TRANSITION_COMPLETE_LISTENER
113            = "android:transitionCompleteListener";
114
115    private static final String KEY_TRANSITION_IS_RETURNING = "android:transitionIsReturning";
116    private static final String KEY_TRANSITION_SHARED_ELEMENTS = "android:sharedElementNames";
117    private static final String KEY_RESULT_DATA = "android:resultData";
118    private static final String KEY_RESULT_CODE = "android:resultCode";
119    private static final String KEY_EXIT_COORDINATOR_INDEX = "android:exitCoordinatorIndex";
120
121    /** @hide */
122    public static final int ANIM_NONE = 0;
123    /** @hide */
124    public static final int ANIM_CUSTOM = 1;
125    /** @hide */
126    public static final int ANIM_SCALE_UP = 2;
127    /** @hide */
128    public static final int ANIM_THUMBNAIL_SCALE_UP = 3;
129    /** @hide */
130    public static final int ANIM_THUMBNAIL_SCALE_DOWN = 4;
131    /** @hide */
132    public static final int ANIM_SCENE_TRANSITION = 5;
133    /** @hide */
134    public static final int ANIM_DEFAULT = 6;
135    /** @hide */
136    public static final int ANIM_LAUNCH_TASK_BEHIND = 7;
137    /** @hide */
138    public static final int ANIM_THUMBNAIL_ASPECT_SCALE_UP = 8;
139    /** @hide */
140    public static final int ANIM_THUMBNAIL_ASPECT_SCALE_DOWN = 9;
141    /** @hide */
142    public static final int ANIM_CUSTOM_IN_PLACE = 10;
143
144    private String mPackageName;
145    private int mAnimationType = ANIM_NONE;
146    private int mCustomEnterResId;
147    private int mCustomExitResId;
148    private int mCustomInPlaceResId;
149    private Bitmap mThumbnail;
150    private int mStartX;
151    private int mStartY;
152    private int mWidth;
153    private int mHeight;
154    private IRemoteCallback mAnimationStartedListener;
155    private ResultReceiver mTransitionReceiver;
156    private boolean mIsReturning;
157    private ArrayList<String> mSharedElementNames;
158    private Intent mResultData;
159    private int mResultCode;
160    private int mExitCoordinatorIndex;
161
162    /**
163     * Create an ActivityOptions specifying a custom animation to run when
164     * the activity is displayed.
165     *
166     * @param context Who is defining this.  This is the application that the
167     * animation resources will be loaded from.
168     * @param enterResId A resource ID of the animation resource to use for
169     * the incoming activity.  Use 0 for no animation.
170     * @param exitResId A resource ID of the animation resource to use for
171     * the outgoing activity.  Use 0 for no animation.
172     * @return Returns a new ActivityOptions object that you can use to
173     * supply these options as the options Bundle when starting an activity.
174     */
175    public static ActivityOptions makeCustomAnimation(Context context,
176            int enterResId, int exitResId) {
177        return makeCustomAnimation(context, enterResId, exitResId, null, null);
178    }
179
180    /**
181     * Create an ActivityOptions specifying a custom animation to run when
182     * the activity is displayed.
183     *
184     * @param context Who is defining this.  This is the application that the
185     * animation resources will be loaded from.
186     * @param enterResId A resource ID of the animation resource to use for
187     * the incoming activity.  Use 0 for no animation.
188     * @param exitResId A resource ID of the animation resource to use for
189     * the outgoing activity.  Use 0 for no animation.
190     * @param handler If <var>listener</var> is non-null this must be a valid
191     * Handler on which to dispatch the callback; otherwise it should be null.
192     * @param listener Optional OnAnimationStartedListener to find out when the
193     * requested animation has started running.  If for some reason the animation
194     * is not executed, the callback will happen immediately.
195     * @return Returns a new ActivityOptions object that you can use to
196     * supply these options as the options Bundle when starting an activity.
197     * @hide
198     */
199    public static ActivityOptions makeCustomAnimation(Context context,
200            int enterResId, int exitResId, Handler handler, OnAnimationStartedListener listener) {
201        ActivityOptions opts = new ActivityOptions();
202        opts.mPackageName = context.getPackageName();
203        opts.mAnimationType = ANIM_CUSTOM;
204        opts.mCustomEnterResId = enterResId;
205        opts.mCustomExitResId = exitResId;
206        opts.setOnAnimationStartedListener(handler, listener);
207        return opts;
208    }
209
210    /**
211     * Creates an ActivityOptions specifying a custom animation to run in place on an existing
212     * activity.
213     *
214     * @param context Who is defining this.  This is the application that the
215     * animation resources will be loaded from.
216     * @param animId A resource ID of the animation resource to use for
217     * the incoming activity.
218     * @return Returns a new ActivityOptions object that you can use to
219     * supply these options as the options Bundle when running an in-place animation.
220     * @hide
221     */
222    public static ActivityOptions makeCustomInPlaceAnimation(Context context, int animId) {
223        if (animId == 0) {
224            throw new RuntimeException("You must specify a valid animation.");
225        }
226
227        ActivityOptions opts = new ActivityOptions();
228        opts.mPackageName = context.getPackageName();
229        opts.mAnimationType = ANIM_CUSTOM_IN_PLACE;
230        opts.mCustomInPlaceResId = animId;
231        return opts;
232    }
233
234    private void setOnAnimationStartedListener(Handler handler,
235            OnAnimationStartedListener listener) {
236        if (listener != null) {
237            final Handler h = handler;
238            final OnAnimationStartedListener finalListener = listener;
239            mAnimationStartedListener = new IRemoteCallback.Stub() {
240                @Override public void sendResult(Bundle data) throws RemoteException {
241                    h.post(new Runnable() {
242                        @Override public void run() {
243                            finalListener.onAnimationStarted();
244                        }
245                    });
246                }
247            };
248        }
249    }
250
251    /**
252     * Callback for use with {@link ActivityOptions#makeThumbnailScaleUpAnimation}
253     * to find out when the given animation has started running.
254     * @hide
255     */
256    public interface OnAnimationStartedListener {
257        void onAnimationStarted();
258    }
259
260    /**
261     * Create an ActivityOptions specifying an animation where the new
262     * activity is scaled from a small originating area of the screen to
263     * its final full representation.
264     *
265     * <p>If the Intent this is being used with has not set its
266     * {@link android.content.Intent#setSourceBounds Intent.setSourceBounds},
267     * those bounds will be filled in for you based on the initial
268     * bounds passed in here.
269     *
270     * @param source The View that the new activity is animating from.  This
271     * defines the coordinate space for <var>startX</var> and <var>startY</var>.
272     * @param startX The x starting location of the new activity, relative to <var>source</var>.
273     * @param startY The y starting location of the activity, relative to <var>source</var>.
274     * @param width The initial width of the new activity.
275     * @param height The initial height of the new activity.
276     * @return Returns a new ActivityOptions object that you can use to
277     * supply these options as the options Bundle when starting an activity.
278     */
279    public static ActivityOptions makeScaleUpAnimation(View source,
280            int startX, int startY, int width, int height) {
281        ActivityOptions opts = new ActivityOptions();
282        opts.mPackageName = source.getContext().getPackageName();
283        opts.mAnimationType = ANIM_SCALE_UP;
284        int[] pts = new int[2];
285        source.getLocationOnScreen(pts);
286        opts.mStartX = pts[0] + startX;
287        opts.mStartY = pts[1] + startY;
288        opts.mWidth = width;
289        opts.mHeight = height;
290        return opts;
291    }
292
293    /**
294     * Create an ActivityOptions specifying an animation where a thumbnail
295     * is scaled from a given position to the new activity window that is
296     * being started.
297     *
298     * <p>If the Intent this is being used with has not set its
299     * {@link android.content.Intent#setSourceBounds Intent.setSourceBounds},
300     * those bounds will be filled in for you based on the initial
301     * thumbnail location and size provided here.
302     *
303     * @param source The View that this thumbnail is animating from.  This
304     * defines the coordinate space for <var>startX</var> and <var>startY</var>.
305     * @param thumbnail The bitmap that will be shown as the initial thumbnail
306     * of the animation.
307     * @param startX The x starting location of the bitmap, relative to <var>source</var>.
308     * @param startY The y starting location of the bitmap, relative to <var>source</var>.
309     * @return Returns a new ActivityOptions object that you can use to
310     * supply these options as the options Bundle when starting an activity.
311     */
312    public static ActivityOptions makeThumbnailScaleUpAnimation(View source,
313            Bitmap thumbnail, int startX, int startY) {
314        return makeThumbnailScaleUpAnimation(source, thumbnail, startX, startY, null);
315    }
316
317    /**
318     * Create an ActivityOptions specifying an animation where a thumbnail
319     * is scaled from a given position to the new activity window that is
320     * being started.
321     *
322     * @param source The View that this thumbnail is animating from.  This
323     * defines the coordinate space for <var>startX</var> and <var>startY</var>.
324     * @param thumbnail The bitmap that will be shown as the initial thumbnail
325     * of the animation.
326     * @param startX The x starting location of the bitmap, relative to <var>source</var>.
327     * @param startY The y starting location of the bitmap, relative to <var>source</var>.
328     * @param listener Optional OnAnimationStartedListener to find out when the
329     * requested animation has started running.  If for some reason the animation
330     * is not executed, the callback will happen immediately.
331     * @return Returns a new ActivityOptions object that you can use to
332     * supply these options as the options Bundle when starting an activity.
333     * @hide
334     */
335    public static ActivityOptions makeThumbnailScaleUpAnimation(View source,
336            Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
337        return makeThumbnailAnimation(source, thumbnail, startX, startY, listener, true);
338    }
339
340    /**
341     * Create an ActivityOptions specifying an animation where an activity window
342     * is scaled from a given position to a thumbnail at a specified location.
343     *
344     * @param source The View that this thumbnail is animating to.  This
345     * defines the coordinate space for <var>startX</var> and <var>startY</var>.
346     * @param thumbnail The bitmap that will be shown as the final thumbnail
347     * of the animation.
348     * @param startX The x end location of the bitmap, relative to <var>source</var>.
349     * @param startY The y end location of the bitmap, relative to <var>source</var>.
350     * @param listener Optional OnAnimationStartedListener to find out when the
351     * requested animation has started running.  If for some reason the animation
352     * is not executed, the callback will happen immediately.
353     * @return Returns a new ActivityOptions object that you can use to
354     * supply these options as the options Bundle when starting an activity.
355     * @hide
356     */
357    public static ActivityOptions makeThumbnailScaleDownAnimation(View source,
358            Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
359        return makeThumbnailAnimation(source, thumbnail, startX, startY, listener, false);
360    }
361
362    private static ActivityOptions makeThumbnailAnimation(View source,
363            Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener,
364            boolean scaleUp) {
365        ActivityOptions opts = new ActivityOptions();
366        opts.mPackageName = source.getContext().getPackageName();
367        opts.mAnimationType = scaleUp ? ANIM_THUMBNAIL_SCALE_UP : ANIM_THUMBNAIL_SCALE_DOWN;
368        opts.mThumbnail = thumbnail;
369        int[] pts = new int[2];
370        source.getLocationOnScreen(pts);
371        opts.mStartX = pts[0] + startX;
372        opts.mStartY = pts[1] + startY;
373        opts.setOnAnimationStartedListener(source.getHandler(), listener);
374        return opts;
375    }
376
377    /**
378     * Create an ActivityOptions specifying an animation where the new activity
379     * window and a thumbnail is aspect-scaled to a new location.
380     *
381     * @param source The View that this thumbnail is animating from.  This
382     * defines the coordinate space for <var>startX</var> and <var>startY</var>.
383     * @param thumbnail The bitmap that will be shown as the initial thumbnail
384     * of the animation.
385     * @param startX The x starting location of the bitmap, relative to <var>source</var>.
386     * @param startY The y starting location of the bitmap, relative to <var>source</var>.
387     * @param handler If <var>listener</var> is non-null this must be a valid
388     * Handler on which to dispatch the callback; otherwise it should be null.
389     * @param listener Optional OnAnimationStartedListener to find out when the
390     * requested animation has started running.  If for some reason the animation
391     * is not executed, the callback will happen immediately.
392     * @return Returns a new ActivityOptions object that you can use to
393     * supply these options as the options Bundle when starting an activity.
394     * @hide
395     */
396    public static ActivityOptions makeThumbnailAspectScaleUpAnimation(View source,
397            Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight,
398            Handler handler, OnAnimationStartedListener listener) {
399        return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY,
400                targetWidth, targetHeight, handler, listener, true);
401    }
402
403    /**
404     * Create an ActivityOptions specifying an animation where the new activity
405     * window and a thumbnail is aspect-scaled to a new location.
406     *
407     * @param source The View that this thumbnail is animating to.  This
408     * defines the coordinate space for <var>startX</var> and <var>startY</var>.
409     * @param thumbnail The bitmap that will be shown as the final thumbnail
410     * of the animation.
411     * @param startX The x end location of the bitmap, relative to <var>source</var>.
412     * @param startY The y end location of the bitmap, relative to <var>source</var>.
413     * @param handler If <var>listener</var> is non-null this must be a valid
414     * Handler on which to dispatch the callback; otherwise it should be null.
415     * @param listener Optional OnAnimationStartedListener to find out when the
416     * requested animation has started running.  If for some reason the animation
417     * is not executed, the callback will happen immediately.
418     * @return Returns a new ActivityOptions object that you can use to
419     * supply these options as the options Bundle when starting an activity.
420     * @hide
421     */
422    public static ActivityOptions makeThumbnailAspectScaleDownAnimation(View source,
423            Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight,
424            Handler handler, OnAnimationStartedListener listener) {
425        return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY,
426                targetWidth, targetHeight, handler, listener, false);
427    }
428
429    private static ActivityOptions makeAspectScaledThumbnailAnimation(View source, Bitmap thumbnail,
430            int startX, int startY, int targetWidth, int targetHeight,
431            Handler handler, OnAnimationStartedListener listener, boolean scaleUp) {
432        ActivityOptions opts = new ActivityOptions();
433        opts.mPackageName = source.getContext().getPackageName();
434        opts.mAnimationType = scaleUp ? ANIM_THUMBNAIL_ASPECT_SCALE_UP :
435                ANIM_THUMBNAIL_ASPECT_SCALE_DOWN;
436        opts.mThumbnail = thumbnail;
437        int[] pts = new int[2];
438        source.getLocationOnScreen(pts);
439        opts.mStartX = pts[0] + startX;
440        opts.mStartY = pts[1] + startY;
441        opts.mWidth = targetWidth;
442        opts.mHeight = targetHeight;
443        opts.setOnAnimationStartedListener(handler, listener);
444        return opts;
445    }
446
447    /**
448     * Create an ActivityOptions to transition between Activities using cross-Activity scene
449     * animations. This method carries the position of one shared element to the started Activity.
450     * The position of <code>sharedElement</code> will be used as the epicenter for the
451     * exit Transition. The position of the shared element in the launched Activity will be the
452     * epicenter of its entering Transition.
453     *
454     * <p>This requires {@link android.view.Window#FEATURE_ACTIVITY_TRANSITIONS} to be
455     * enabled on the calling Activity to cause an exit transition. The same must be in
456     * the called Activity to get an entering transition.</p>
457     * @param activity The Activity whose window contains the shared elements.
458     * @param sharedElement The View to transition to the started Activity.
459     * @param sharedElementName The shared element name as used in the target Activity. This
460     *                          must not be null.
461     * @return Returns a new ActivityOptions object that you can use to
462     *         supply these options as the options Bundle when starting an activity.
463     * @see android.transition.Transition#setEpicenterCallback(
464     *          android.transition.Transition.EpicenterCallback)
465     */
466    public static ActivityOptions makeSceneTransitionAnimation(Activity activity,
467            View sharedElement, String sharedElementName) {
468        return makeSceneTransitionAnimation(activity, Pair.create(sharedElement, sharedElementName));
469    }
470
471    /**
472     * Create an ActivityOptions to transition between Activities using cross-Activity scene
473     * animations. This method carries the position of multiple shared elements to the started
474     * Activity. The position of the first element in sharedElements
475     * will be used as the epicenter for the exit Transition. The position of the associated
476     * shared element in the launched Activity will be the epicenter of its entering Transition.
477     *
478     * <p>This requires {@link android.view.Window#FEATURE_ACTIVITY_TRANSITIONS} to be
479     * enabled on the calling Activity to cause an exit transition. The same must be in
480     * the called Activity to get an entering transition.</p>
481     * @param activity The Activity whose window contains the shared elements.
482     * @param sharedElements The names of the shared elements to transfer to the called
483     *                       Activity and their associated Views. The Views must each have
484     *                       a unique shared element name.
485     * @return Returns a new ActivityOptions object that you can use to
486     *         supply these options as the options Bundle when starting an activity.
487     * @see android.transition.Transition#setEpicenterCallback(
488     *          android.transition.Transition.EpicenterCallback)
489     */
490    public static ActivityOptions makeSceneTransitionAnimation(Activity activity,
491            Pair<View, String>... sharedElements) {
492        ActivityOptions opts = new ActivityOptions();
493        if (!activity.getWindow().hasFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)) {
494            opts.mAnimationType = ANIM_DEFAULT;
495            return opts;
496        }
497        opts.mAnimationType = ANIM_SCENE_TRANSITION;
498
499        ArrayList<String> names = new ArrayList<String>();
500        ArrayList<View> views = new ArrayList<View>();
501
502        if (sharedElements != null) {
503            for (int i = 0; i < sharedElements.length; i++) {
504                Pair<View, String> sharedElement = sharedElements[i];
505                String sharedElementName = sharedElement.second;
506                if (sharedElementName == null) {
507                    throw new IllegalArgumentException("Shared element name must not be null");
508                }
509                names.add(sharedElementName);
510                View view = sharedElement.first;
511                if (view == null) {
512                    throw new IllegalArgumentException("Shared element must not be null");
513                }
514                views.add(sharedElement.first);
515            }
516        }
517
518        ExitTransitionCoordinator exit = new ExitTransitionCoordinator(activity, names, names,
519                views, false);
520        opts.mTransitionReceiver = exit;
521        opts.mSharedElementNames = names;
522        opts.mIsReturning = false;
523        opts.mExitCoordinatorIndex =
524                activity.mActivityTransitionState.addExitTransitionCoordinator(exit);
525        return opts;
526    }
527
528    /** @hide */
529    public static ActivityOptions makeSceneTransitionAnimation(Activity activity,
530            ExitTransitionCoordinator exitCoordinator, ArrayList<String> sharedElementNames,
531            int resultCode, Intent resultData) {
532        ActivityOptions opts = new ActivityOptions();
533        opts.mAnimationType = ANIM_SCENE_TRANSITION;
534        opts.mSharedElementNames = sharedElementNames;
535        opts.mTransitionReceiver = exitCoordinator;
536        opts.mIsReturning = true;
537        opts.mResultCode = resultCode;
538        opts.mResultData = resultData;
539        opts.mExitCoordinatorIndex =
540                activity.mActivityTransitionState.addExitTransitionCoordinator(exitCoordinator);
541        return opts;
542    }
543
544    /**
545     * If set along with Intent.FLAG_ACTIVITY_NEW_DOCUMENT then the task being launched will not be
546     * presented to the user but will instead be only available through the recents task list.
547     * In addition, the new task wil be affiliated with the launching activity's task.
548     * Affiliated tasks are grouped together in the recents task list.
549     *
550     * <p>This behavior is not supported for activities with {@link
551     * android.R.styleable#AndroidManifestActivity_launchMode launchMode} values of
552     * <code>singleInstance</code> or <code>singleTask</code>.
553     */
554    public static ActivityOptions makeTaskLaunchBehind() {
555        final ActivityOptions opts = new ActivityOptions();
556        opts.mAnimationType = ANIM_LAUNCH_TASK_BEHIND;
557        return opts;
558    }
559
560    /** @hide */
561    public boolean getLaunchTaskBehind() {
562        return mAnimationType == ANIM_LAUNCH_TASK_BEHIND;
563    }
564
565    private ActivityOptions() {
566    }
567
568    /** @hide */
569    public ActivityOptions(Bundle opts) {
570        mPackageName = opts.getString(KEY_PACKAGE_NAME);
571        mAnimationType = opts.getInt(KEY_ANIM_TYPE);
572        switch (mAnimationType) {
573            case ANIM_CUSTOM:
574                mCustomEnterResId = opts.getInt(KEY_ANIM_ENTER_RES_ID, 0);
575                mCustomExitResId = opts.getInt(KEY_ANIM_EXIT_RES_ID, 0);
576                mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
577                        opts.getBinder(KEY_ANIM_START_LISTENER));
578                break;
579
580            case ANIM_CUSTOM_IN_PLACE:
581                mCustomInPlaceResId = opts.getInt(KEY_ANIM_IN_PLACE_RES_ID, 0);
582                break;
583
584            case ANIM_SCALE_UP:
585                mStartX = opts.getInt(KEY_ANIM_START_X, 0);
586                mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
587                mWidth = opts.getInt(KEY_ANIM_WIDTH, 0);
588                mHeight = opts.getInt(KEY_ANIM_HEIGHT, 0);
589                break;
590
591            case ANIM_THUMBNAIL_SCALE_UP:
592            case ANIM_THUMBNAIL_SCALE_DOWN:
593            case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
594            case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
595                mThumbnail = (Bitmap) opts.getParcelable(KEY_ANIM_THUMBNAIL);
596                mStartX = opts.getInt(KEY_ANIM_START_X, 0);
597                mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
598                mWidth = opts.getInt(KEY_ANIM_WIDTH, 0);
599                mHeight = opts.getInt(KEY_ANIM_HEIGHT, 0);
600                mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
601                        opts.getBinder(KEY_ANIM_START_LISTENER));
602                break;
603
604            case ANIM_SCENE_TRANSITION:
605                mTransitionReceiver = opts.getParcelable(KEY_TRANSITION_COMPLETE_LISTENER);
606                mIsReturning = opts.getBoolean(KEY_TRANSITION_IS_RETURNING, false);
607                mSharedElementNames = opts.getStringArrayList(KEY_TRANSITION_SHARED_ELEMENTS);
608                mResultData = opts.getParcelable(KEY_RESULT_DATA);
609                mResultCode = opts.getInt(KEY_RESULT_CODE);
610                mExitCoordinatorIndex = opts.getInt(KEY_EXIT_COORDINATOR_INDEX);
611                break;
612        }
613    }
614
615    /** @hide */
616    public String getPackageName() {
617        return mPackageName;
618    }
619
620    /** @hide */
621    public int getAnimationType() {
622        return mAnimationType;
623    }
624
625    /** @hide */
626    public int getCustomEnterResId() {
627        return mCustomEnterResId;
628    }
629
630    /** @hide */
631    public int getCustomExitResId() {
632        return mCustomExitResId;
633    }
634
635    /** @hide */
636    public int getCustomInPlaceResId() {
637        return mCustomInPlaceResId;
638    }
639
640    /** @hide */
641    public Bitmap getThumbnail() {
642        return mThumbnail;
643    }
644
645    /** @hide */
646    public int getStartX() {
647        return mStartX;
648    }
649
650    /** @hide */
651    public int getStartY() {
652        return mStartY;
653    }
654
655    /** @hide */
656    public int getWidth() {
657        return mWidth;
658    }
659
660    /** @hide */
661    public int getHeight() {
662        return mHeight;
663    }
664
665    /** @hide */
666    public IRemoteCallback getOnAnimationStartListener() {
667        return mAnimationStartedListener;
668    }
669
670    /** @hide */
671    public int getExitCoordinatorKey() { return mExitCoordinatorIndex; }
672
673    /** @hide */
674    public void abort() {
675        if (mAnimationStartedListener != null) {
676            try {
677                mAnimationStartedListener.sendResult(null);
678            } catch (RemoteException e) {
679            }
680        }
681    }
682
683    /** @hide */
684    public boolean isReturning() {
685        return mIsReturning;
686    }
687
688    /** @hide */
689    public ArrayList<String> getSharedElementNames() {
690        return mSharedElementNames;
691    }
692
693    /** @hide */
694    public ResultReceiver getResultReceiver() { return mTransitionReceiver; }
695
696    /** @hide */
697    public int getResultCode() { return mResultCode; }
698
699    /** @hide */
700    public Intent getResultData() { return mResultData; }
701
702    /** @hide */
703    public static void abort(Bundle options) {
704        if (options != null) {
705            (new ActivityOptions(options)).abort();
706        }
707    }
708
709    /**
710     * Update the current values in this ActivityOptions from those supplied
711     * in <var>otherOptions</var>.  Any values
712     * defined in <var>otherOptions</var> replace those in the base options.
713     */
714    public void update(ActivityOptions otherOptions) {
715        if (otherOptions.mPackageName != null) {
716            mPackageName = otherOptions.mPackageName;
717        }
718        mTransitionReceiver = null;
719        mSharedElementNames = null;
720        mIsReturning = false;
721        mResultData = null;
722        mResultCode = 0;
723        mExitCoordinatorIndex = 0;
724        mAnimationType = otherOptions.mAnimationType;
725        switch (otherOptions.mAnimationType) {
726            case ANIM_CUSTOM:
727                mCustomEnterResId = otherOptions.mCustomEnterResId;
728                mCustomExitResId = otherOptions.mCustomExitResId;
729                mThumbnail = null;
730                if (mAnimationStartedListener != null) {
731                    try {
732                        mAnimationStartedListener.sendResult(null);
733                    } catch (RemoteException e) {
734                    }
735                }
736                mAnimationStartedListener = otherOptions.mAnimationStartedListener;
737                break;
738            case ANIM_CUSTOM_IN_PLACE:
739                mCustomInPlaceResId = otherOptions.mCustomInPlaceResId;
740                break;
741            case ANIM_SCALE_UP:
742                mStartX = otherOptions.mStartX;
743                mStartY = otherOptions.mStartY;
744                mWidth = otherOptions.mWidth;
745                mHeight = otherOptions.mHeight;
746                if (mAnimationStartedListener != null) {
747                    try {
748                        mAnimationStartedListener.sendResult(null);
749                    } catch (RemoteException e) {
750                    }
751                }
752                mAnimationStartedListener = null;
753                break;
754            case ANIM_THUMBNAIL_SCALE_UP:
755            case ANIM_THUMBNAIL_SCALE_DOWN:
756            case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
757            case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
758                mThumbnail = otherOptions.mThumbnail;
759                mStartX = otherOptions.mStartX;
760                mStartY = otherOptions.mStartY;
761                mWidth = otherOptions.mWidth;
762                mHeight = otherOptions.mHeight;
763                if (mAnimationStartedListener != null) {
764                    try {
765                        mAnimationStartedListener.sendResult(null);
766                    } catch (RemoteException e) {
767                    }
768                }
769                mAnimationStartedListener = otherOptions.mAnimationStartedListener;
770                break;
771            case ANIM_SCENE_TRANSITION:
772                mTransitionReceiver = otherOptions.mTransitionReceiver;
773                mSharedElementNames = otherOptions.mSharedElementNames;
774                mIsReturning = otherOptions.mIsReturning;
775                mThumbnail = null;
776                mAnimationStartedListener = null;
777                mResultData = otherOptions.mResultData;
778                mResultCode = otherOptions.mResultCode;
779                mExitCoordinatorIndex = otherOptions.mExitCoordinatorIndex;
780                break;
781        }
782    }
783
784    /**
785     * Returns the created options as a Bundle, which can be passed to
786     * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle)
787     * Context.startActivity(Intent, Bundle)} and related methods.
788     * Note that the returned Bundle is still owned by the ActivityOptions
789     * object; you must not modify it, but can supply it to the startActivity
790     * methods that take an options Bundle.
791     */
792    public Bundle toBundle() {
793        if (mAnimationType == ANIM_DEFAULT) {
794            return null;
795        }
796        Bundle b = new Bundle();
797        if (mPackageName != null) {
798            b.putString(KEY_PACKAGE_NAME, mPackageName);
799        }
800        b.putInt(KEY_ANIM_TYPE, mAnimationType);
801        switch (mAnimationType) {
802            case ANIM_CUSTOM:
803                b.putInt(KEY_ANIM_ENTER_RES_ID, mCustomEnterResId);
804                b.putInt(KEY_ANIM_EXIT_RES_ID, mCustomExitResId);
805                b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
806                        != null ? mAnimationStartedListener.asBinder() : null);
807                break;
808            case ANIM_CUSTOM_IN_PLACE:
809                b.putInt(KEY_ANIM_IN_PLACE_RES_ID, mCustomInPlaceResId);
810                break;
811            case ANIM_SCALE_UP:
812                b.putInt(KEY_ANIM_START_X, mStartX);
813                b.putInt(KEY_ANIM_START_Y, mStartY);
814                b.putInt(KEY_ANIM_WIDTH, mWidth);
815                b.putInt(KEY_ANIM_HEIGHT, mHeight);
816                break;
817            case ANIM_THUMBNAIL_SCALE_UP:
818            case ANIM_THUMBNAIL_SCALE_DOWN:
819            case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
820            case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
821                b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
822                b.putInt(KEY_ANIM_START_X, mStartX);
823                b.putInt(KEY_ANIM_START_Y, mStartY);
824                b.putInt(KEY_ANIM_WIDTH, mWidth);
825                b.putInt(KEY_ANIM_HEIGHT, mHeight);
826                b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
827                        != null ? mAnimationStartedListener.asBinder() : null);
828                break;
829            case ANIM_SCENE_TRANSITION:
830                if (mTransitionReceiver != null) {
831                    b.putParcelable(KEY_TRANSITION_COMPLETE_LISTENER, mTransitionReceiver);
832                }
833                b.putBoolean(KEY_TRANSITION_IS_RETURNING, mIsReturning);
834                b.putStringArrayList(KEY_TRANSITION_SHARED_ELEMENTS, mSharedElementNames);
835                b.putParcelable(KEY_RESULT_DATA, mResultData);
836                b.putInt(KEY_RESULT_CODE, mResultCode);
837                b.putInt(KEY_EXIT_COORDINATOR_INDEX, mExitCoordinatorIndex);
838                break;
839        }
840
841        return b;
842    }
843
844    /**
845     * Return the filtered options only meant to be seen by the target activity itself
846     * @hide
847     */
848    public ActivityOptions forTargetActivity() {
849        if (mAnimationType == ANIM_SCENE_TRANSITION) {
850            final ActivityOptions result = new ActivityOptions();
851            result.update(this);
852            return result;
853        }
854
855        return null;
856    }
857
858}
859