ActivityOptions.java revision 044d52934e57a337665f707aa4be1d423ee3fb29
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 listener Optional OnAnimationStartedListener to find out when the
388     * requested animation has started running.  If for some reason the animation
389     * is not executed, the callback will happen immediately.
390     * @return Returns a new ActivityOptions object that you can use to
391     * supply these options as the options Bundle when starting an activity.
392     * @hide
393     */
394    public static ActivityOptions makeThumbnailAspectScaleUpAnimation(View source,
395            Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight,
396            OnAnimationStartedListener listener) {
397        return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY,
398                targetWidth, targetHeight, listener, true);
399    }
400
401    /**
402     * Create an ActivityOptions specifying an animation where the new activity
403     * window and a thumbnail is aspect-scaled to a new location.
404     *
405     * @param source The View that this thumbnail is animating to.  This
406     * defines the coordinate space for <var>startX</var> and <var>startY</var>.
407     * @param thumbnail The bitmap that will be shown as the final thumbnail
408     * of the animation.
409     * @param startX The x end location of the bitmap, relative to <var>source</var>.
410     * @param startY The y end location of the bitmap, relative to <var>source</var>.
411     * @param listener Optional OnAnimationStartedListener to find out when the
412     * requested animation has started running.  If for some reason the animation
413     * is not executed, the callback will happen immediately.
414     * @return Returns a new ActivityOptions object that you can use to
415     * supply these options as the options Bundle when starting an activity.
416     * @hide
417     */
418    public static ActivityOptions makeThumbnailAspectScaleDownAnimation(View source,
419            Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight,
420            OnAnimationStartedListener listener) {
421        return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY,
422                targetWidth, targetHeight, listener, false);
423    }
424
425    private static ActivityOptions makeAspectScaledThumbnailAnimation(View source, Bitmap thumbnail,
426            int startX, int startY, int targetWidth, int targetHeight,
427            OnAnimationStartedListener listener, boolean scaleUp) {
428        ActivityOptions opts = new ActivityOptions();
429        opts.mPackageName = source.getContext().getPackageName();
430        opts.mAnimationType = scaleUp ? ANIM_THUMBNAIL_ASPECT_SCALE_UP :
431                ANIM_THUMBNAIL_ASPECT_SCALE_DOWN;
432        opts.mThumbnail = thumbnail;
433        int[] pts = new int[2];
434        source.getLocationOnScreen(pts);
435        opts.mStartX = pts[0] + startX;
436        opts.mStartY = pts[1] + startY;
437        opts.mWidth = targetWidth;
438        opts.mHeight = targetHeight;
439        opts.setOnAnimationStartedListener(source.getHandler(), listener);
440        return opts;
441    }
442
443    /**
444     * Create an ActivityOptions to transition between Activities using cross-Activity scene
445     * animations. This method carries the position of one shared element to the started Activity.
446     * The position of <code>sharedElement</code> will be used as the epicenter for the
447     * exit Transition. The position of the shared element in the launched Activity will be the
448     * epicenter of its entering Transition.
449     *
450     * <p>This requires {@link android.view.Window#FEATURE_ACTIVITY_TRANSITIONS} to be
451     * enabled on the calling Activity to cause an exit transition. The same must be in
452     * the called Activity to get an entering transition.</p>
453     * @param activity The Activity whose window contains the shared elements.
454     * @param sharedElement The View to transition to the started Activity.
455     * @param sharedElementName The shared element name as used in the target Activity. This
456     *                          must not be null.
457     * @return Returns a new ActivityOptions object that you can use to
458     *         supply these options as the options Bundle when starting an activity.
459     * @see android.transition.Transition#setEpicenterCallback(
460     *          android.transition.Transition.EpicenterCallback)
461     */
462    public static ActivityOptions makeSceneTransitionAnimation(Activity activity,
463            View sharedElement, String sharedElementName) {
464        return makeSceneTransitionAnimation(activity, Pair.create(sharedElement, sharedElementName));
465    }
466
467    /**
468     * Create an ActivityOptions to transition between Activities using cross-Activity scene
469     * animations. This method carries the position of multiple shared elements to the started
470     * Activity. The position of the first element in sharedElements
471     * will be used as the epicenter for the exit Transition. The position of the associated
472     * shared element in the launched Activity will be the epicenter of its entering Transition.
473     *
474     * <p>This requires {@link android.view.Window#FEATURE_ACTIVITY_TRANSITIONS} to be
475     * enabled on the calling Activity to cause an exit transition. The same must be in
476     * the called Activity to get an entering transition.</p>
477     * @param activity The Activity whose window contains the shared elements.
478     * @param sharedElements The names of the shared elements to transfer to the called
479     *                       Activity and their associated Views. The Views must each have
480     *                       a unique shared element name.
481     * @return Returns a new ActivityOptions object that you can use to
482     *         supply these options as the options Bundle when starting an activity.
483     * @see android.transition.Transition#setEpicenterCallback(
484     *          android.transition.Transition.EpicenterCallback)
485     */
486    public static ActivityOptions makeSceneTransitionAnimation(Activity activity,
487            Pair<View, String>... sharedElements) {
488        ActivityOptions opts = new ActivityOptions();
489        if (!activity.getWindow().hasFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)) {
490            opts.mAnimationType = ANIM_DEFAULT;
491            return opts;
492        }
493        opts.mAnimationType = ANIM_SCENE_TRANSITION;
494
495        ArrayList<String> names = new ArrayList<String>();
496        ArrayList<View> views = new ArrayList<View>();
497
498        if (sharedElements != null) {
499            for (int i = 0; i < sharedElements.length; i++) {
500                Pair<View, String> sharedElement = sharedElements[i];
501                String sharedElementName = sharedElement.second;
502                if (sharedElementName == null) {
503                    throw new IllegalArgumentException("Shared element name must not be null");
504                }
505                names.add(sharedElementName);
506                View view = sharedElement.first;
507                if (view == null) {
508                    throw new IllegalArgumentException("Shared element must not be null");
509                }
510                views.add(sharedElement.first);
511            }
512        }
513
514        ExitTransitionCoordinator exit = new ExitTransitionCoordinator(activity, names, names,
515                views, false);
516        opts.mTransitionReceiver = exit;
517        opts.mSharedElementNames = names;
518        opts.mIsReturning = false;
519        opts.mExitCoordinatorIndex =
520                activity.mActivityTransitionState.addExitTransitionCoordinator(exit);
521        return opts;
522    }
523
524    /** @hide */
525    public static ActivityOptions makeSceneTransitionAnimation(Activity activity,
526            ExitTransitionCoordinator exitCoordinator, ArrayList<String> sharedElementNames,
527            int resultCode, Intent resultData) {
528        ActivityOptions opts = new ActivityOptions();
529        opts.mAnimationType = ANIM_SCENE_TRANSITION;
530        opts.mSharedElementNames = sharedElementNames;
531        opts.mTransitionReceiver = exitCoordinator;
532        opts.mIsReturning = true;
533        opts.mResultCode = resultCode;
534        opts.mResultData = resultData;
535        opts.mExitCoordinatorIndex =
536                activity.mActivityTransitionState.addExitTransitionCoordinator(exitCoordinator);
537        return opts;
538    }
539
540    /**
541     * If set along with Intent.FLAG_ACTIVITY_NEW_DOCUMENT then the task being launched will not be
542     * presented to the user but will instead be only available through the recents task list.
543     * In addition, the new task wil be affiliated with the launching activity's task.
544     * Affiliated tasks are grouped together in the recents task list.
545     *
546     * <p>This behavior is not supported for activities with {@link
547     * android.R.styleable#AndroidManifestActivity_launchMode launchMode} values of
548     * <code>singleInstance</code> or <code>singleTask</code>.
549     */
550    public static ActivityOptions makeTaskLaunchBehind() {
551        final ActivityOptions opts = new ActivityOptions();
552        opts.mAnimationType = ANIM_LAUNCH_TASK_BEHIND;
553        return opts;
554    }
555
556    /** @hide */
557    public boolean getLaunchTaskBehind() {
558        return mAnimationType == ANIM_LAUNCH_TASK_BEHIND;
559    }
560
561    private ActivityOptions() {
562    }
563
564    /** @hide */
565    public ActivityOptions(Bundle opts) {
566        mPackageName = opts.getString(KEY_PACKAGE_NAME);
567        mAnimationType = opts.getInt(KEY_ANIM_TYPE);
568        switch (mAnimationType) {
569            case ANIM_CUSTOM:
570                mCustomEnterResId = opts.getInt(KEY_ANIM_ENTER_RES_ID, 0);
571                mCustomExitResId = opts.getInt(KEY_ANIM_EXIT_RES_ID, 0);
572                mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
573                        opts.getBinder(KEY_ANIM_START_LISTENER));
574                break;
575
576            case ANIM_CUSTOM_IN_PLACE:
577                mCustomInPlaceResId = opts.getInt(KEY_ANIM_IN_PLACE_RES_ID, 0);
578                break;
579
580            case ANIM_SCALE_UP:
581                mStartX = opts.getInt(KEY_ANIM_START_X, 0);
582                mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
583                mWidth = opts.getInt(KEY_ANIM_WIDTH, 0);
584                mHeight = opts.getInt(KEY_ANIM_HEIGHT, 0);
585                break;
586
587            case ANIM_THUMBNAIL_SCALE_UP:
588            case ANIM_THUMBNAIL_SCALE_DOWN:
589            case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
590            case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
591                mThumbnail = (Bitmap) opts.getParcelable(KEY_ANIM_THUMBNAIL);
592                mStartX = opts.getInt(KEY_ANIM_START_X, 0);
593                mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
594                mWidth = opts.getInt(KEY_ANIM_WIDTH, 0);
595                mHeight = opts.getInt(KEY_ANIM_HEIGHT, 0);
596                mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
597                        opts.getBinder(KEY_ANIM_START_LISTENER));
598                break;
599
600            case ANIM_SCENE_TRANSITION:
601                mTransitionReceiver = opts.getParcelable(KEY_TRANSITION_COMPLETE_LISTENER);
602                mIsReturning = opts.getBoolean(KEY_TRANSITION_IS_RETURNING, false);
603                mSharedElementNames = opts.getStringArrayList(KEY_TRANSITION_SHARED_ELEMENTS);
604                mResultData = opts.getParcelable(KEY_RESULT_DATA);
605                mResultCode = opts.getInt(KEY_RESULT_CODE);
606                mExitCoordinatorIndex = opts.getInt(KEY_EXIT_COORDINATOR_INDEX);
607                break;
608        }
609    }
610
611    /** @hide */
612    public String getPackageName() {
613        return mPackageName;
614    }
615
616    /** @hide */
617    public int getAnimationType() {
618        return mAnimationType;
619    }
620
621    /** @hide */
622    public int getCustomEnterResId() {
623        return mCustomEnterResId;
624    }
625
626    /** @hide */
627    public int getCustomExitResId() {
628        return mCustomExitResId;
629    }
630
631    /** @hide */
632    public int getCustomInPlaceResId() {
633        return mCustomInPlaceResId;
634    }
635
636    /** @hide */
637    public Bitmap getThumbnail() {
638        return mThumbnail;
639    }
640
641    /** @hide */
642    public int getStartX() {
643        return mStartX;
644    }
645
646    /** @hide */
647    public int getStartY() {
648        return mStartY;
649    }
650
651    /** @hide */
652    public int getWidth() {
653        return mWidth;
654    }
655
656    /** @hide */
657    public int getHeight() {
658        return mHeight;
659    }
660
661    /** @hide */
662    public IRemoteCallback getOnAnimationStartListener() {
663        return mAnimationStartedListener;
664    }
665
666    /** @hide */
667    public int getExitCoordinatorKey() { return mExitCoordinatorIndex; }
668
669    /** @hide */
670    public void abort() {
671        if (mAnimationStartedListener != null) {
672            try {
673                mAnimationStartedListener.sendResult(null);
674            } catch (RemoteException e) {
675            }
676        }
677    }
678
679    /** @hide */
680    public boolean isReturning() {
681        return mIsReturning;
682    }
683
684    /** @hide */
685    public ArrayList<String> getSharedElementNames() {
686        return mSharedElementNames;
687    }
688
689    /** @hide */
690    public ResultReceiver getResultReceiver() { return mTransitionReceiver; }
691
692    /** @hide */
693    public int getResultCode() { return mResultCode; }
694
695    /** @hide */
696    public Intent getResultData() { return mResultData; }
697
698    /** @hide */
699    public static void abort(Bundle options) {
700        if (options != null) {
701            (new ActivityOptions(options)).abort();
702        }
703    }
704
705    /**
706     * Update the current values in this ActivityOptions from those supplied
707     * in <var>otherOptions</var>.  Any values
708     * defined in <var>otherOptions</var> replace those in the base options.
709     */
710    public void update(ActivityOptions otherOptions) {
711        if (otherOptions.mPackageName != null) {
712            mPackageName = otherOptions.mPackageName;
713        }
714        mTransitionReceiver = null;
715        mSharedElementNames = null;
716        mIsReturning = false;
717        mResultData = null;
718        mResultCode = 0;
719        mExitCoordinatorIndex = 0;
720        mAnimationType = otherOptions.mAnimationType;
721        switch (otherOptions.mAnimationType) {
722            case ANIM_CUSTOM:
723                mCustomEnterResId = otherOptions.mCustomEnterResId;
724                mCustomExitResId = otherOptions.mCustomExitResId;
725                mThumbnail = null;
726                if (mAnimationStartedListener != null) {
727                    try {
728                        mAnimationStartedListener.sendResult(null);
729                    } catch (RemoteException e) {
730                    }
731                }
732                mAnimationStartedListener = otherOptions.mAnimationStartedListener;
733                break;
734            case ANIM_CUSTOM_IN_PLACE:
735                mCustomInPlaceResId = otherOptions.mCustomInPlaceResId;
736                break;
737            case ANIM_SCALE_UP:
738                mStartX = otherOptions.mStartX;
739                mStartY = otherOptions.mStartY;
740                mWidth = otherOptions.mWidth;
741                mHeight = otherOptions.mHeight;
742                if (mAnimationStartedListener != null) {
743                    try {
744                        mAnimationStartedListener.sendResult(null);
745                    } catch (RemoteException e) {
746                    }
747                }
748                mAnimationStartedListener = null;
749                break;
750            case ANIM_THUMBNAIL_SCALE_UP:
751            case ANIM_THUMBNAIL_SCALE_DOWN:
752            case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
753            case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
754                mThumbnail = otherOptions.mThumbnail;
755                mStartX = otherOptions.mStartX;
756                mStartY = otherOptions.mStartY;
757                mWidth = otherOptions.mWidth;
758                mHeight = otherOptions.mHeight;
759                if (mAnimationStartedListener != null) {
760                    try {
761                        mAnimationStartedListener.sendResult(null);
762                    } catch (RemoteException e) {
763                    }
764                }
765                mAnimationStartedListener = otherOptions.mAnimationStartedListener;
766                break;
767            case ANIM_SCENE_TRANSITION:
768                mTransitionReceiver = otherOptions.mTransitionReceiver;
769                mSharedElementNames = otherOptions.mSharedElementNames;
770                mIsReturning = otherOptions.mIsReturning;
771                mThumbnail = null;
772                mAnimationStartedListener = null;
773                mResultData = otherOptions.mResultData;
774                mResultCode = otherOptions.mResultCode;
775                mExitCoordinatorIndex = otherOptions.mExitCoordinatorIndex;
776                break;
777        }
778    }
779
780    /**
781     * Returns the created options as a Bundle, which can be passed to
782     * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle)
783     * Context.startActivity(Intent, Bundle)} and related methods.
784     * Note that the returned Bundle is still owned by the ActivityOptions
785     * object; you must not modify it, but can supply it to the startActivity
786     * methods that take an options Bundle.
787     */
788    public Bundle toBundle() {
789        if (mAnimationType == ANIM_DEFAULT) {
790            return null;
791        }
792        Bundle b = new Bundle();
793        if (mPackageName != null) {
794            b.putString(KEY_PACKAGE_NAME, mPackageName);
795        }
796        b.putInt(KEY_ANIM_TYPE, mAnimationType);
797        switch (mAnimationType) {
798            case ANIM_CUSTOM:
799                b.putInt(KEY_ANIM_ENTER_RES_ID, mCustomEnterResId);
800                b.putInt(KEY_ANIM_EXIT_RES_ID, mCustomExitResId);
801                b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
802                        != null ? mAnimationStartedListener.asBinder() : null);
803                break;
804            case ANIM_CUSTOM_IN_PLACE:
805                b.putInt(KEY_ANIM_IN_PLACE_RES_ID, mCustomInPlaceResId);
806                break;
807            case ANIM_SCALE_UP:
808                b.putInt(KEY_ANIM_START_X, mStartX);
809                b.putInt(KEY_ANIM_START_Y, mStartY);
810                b.putInt(KEY_ANIM_WIDTH, mWidth);
811                b.putInt(KEY_ANIM_HEIGHT, mHeight);
812                break;
813            case ANIM_THUMBNAIL_SCALE_UP:
814            case ANIM_THUMBNAIL_SCALE_DOWN:
815            case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
816            case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
817                b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
818                b.putInt(KEY_ANIM_START_X, mStartX);
819                b.putInt(KEY_ANIM_START_Y, mStartY);
820                b.putInt(KEY_ANIM_WIDTH, mWidth);
821                b.putInt(KEY_ANIM_HEIGHT, mHeight);
822                b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
823                        != null ? mAnimationStartedListener.asBinder() : null);
824                break;
825            case ANIM_SCENE_TRANSITION:
826                if (mTransitionReceiver != null) {
827                    b.putParcelable(KEY_TRANSITION_COMPLETE_LISTENER, mTransitionReceiver);
828                }
829                b.putBoolean(KEY_TRANSITION_IS_RETURNING, mIsReturning);
830                b.putStringArrayList(KEY_TRANSITION_SHARED_ELEMENTS, mSharedElementNames);
831                b.putParcelable(KEY_RESULT_DATA, mResultData);
832                b.putInt(KEY_RESULT_CODE, mResultCode);
833                b.putInt(KEY_EXIT_COORDINATOR_INDEX, mExitCoordinatorIndex);
834                break;
835        }
836
837        return b;
838    }
839
840    /**
841     * Return the filtered options only meant to be seen by the target activity itself
842     * @hide
843     */
844    public ActivityOptions forTargetActivity() {
845        if (mAnimationType == ANIM_SCENE_TRANSITION) {
846            final ActivityOptions result = new ActivityOptions();
847            result.update(this);
848            return result;
849        }
850
851        return null;
852    }
853
854}
855