Home | History | Annotate | Download | only in app
      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 
     17 package android.app;
     18 
     19 import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
     20 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
     21 
     22 import android.annotation.Nullable;
     23 import android.annotation.TestApi;
     24 import android.content.Context;
     25 import android.content.Intent;
     26 import android.graphics.Bitmap;
     27 import android.graphics.Rect;
     28 import android.os.Bundle;
     29 import android.os.Handler;
     30 import android.os.IRemoteCallback;
     31 import android.os.Parcelable;
     32 import android.os.RemoteException;
     33 import android.os.ResultReceiver;
     34 import android.util.Pair;
     35 import android.util.Slog;
     36 import android.view.AppTransitionAnimationSpec;
     37 import android.view.View;
     38 import android.view.Window;
     39 
     40 import java.util.ArrayList;
     41 
     42 /**
     43  * Helper class for building an options Bundle that can be used with
     44  * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle)
     45  * Context.startActivity(Intent, Bundle)} and related methods.
     46  */
     47 public class ActivityOptions {
     48     private static final String TAG = "ActivityOptions";
     49 
     50     /**
     51      * A long in the extras delivered by {@link #requestUsageTimeReport} that contains
     52      * the total time (in ms) the user spent in the app flow.
     53      */
     54     public static final String EXTRA_USAGE_TIME_REPORT = "android.activity.usage_time";
     55 
     56     /**
     57      * A Bundle in the extras delivered by {@link #requestUsageTimeReport} that contains
     58      * detailed information about the time spent in each package associated with the app;
     59      * each key is a package name, whose value is a long containing the time (in ms).
     60      */
     61     public static final String EXTRA_USAGE_TIME_REPORT_PACKAGES = "android.usage_time_packages";
     62 
     63     /**
     64      * The package name that created the options.
     65      * @hide
     66      */
     67     public static final String KEY_PACKAGE_NAME = "android:activity.packageName";
     68 
     69     /**
     70      * The bounds (window size) that the activity should be launched in. Set to null explicitly for
     71      * full screen. If the key is not found, previous bounds will be preserved.
     72      * NOTE: This value is ignored on devices that don't have
     73      * {@link android.content.pm.PackageManager#FEATURE_FREEFORM_WINDOW_MANAGEMENT} or
     74      * {@link android.content.pm.PackageManager#FEATURE_PICTURE_IN_PICTURE} enabled.
     75      * @hide
     76      */
     77     public static final String KEY_LAUNCH_BOUNDS = "android:activity.launchBounds";
     78 
     79     /**
     80      * Type of animation that arguments specify.
     81      * @hide
     82      */
     83     public static final String KEY_ANIM_TYPE = "android:activity.animType";
     84 
     85     /**
     86      * Custom enter animation resource ID.
     87      * @hide
     88      */
     89     public static final String KEY_ANIM_ENTER_RES_ID = "android:activity.animEnterRes";
     90 
     91     /**
     92      * Custom exit animation resource ID.
     93      * @hide
     94      */
     95     public static final String KEY_ANIM_EXIT_RES_ID = "android:activity.animExitRes";
     96 
     97     /**
     98      * Custom in-place animation resource ID.
     99      * @hide
    100      */
    101     public static final String KEY_ANIM_IN_PLACE_RES_ID = "android:activity.animInPlaceRes";
    102 
    103     /**
    104      * Bitmap for thumbnail animation.
    105      * @hide
    106      */
    107     public static final String KEY_ANIM_THUMBNAIL = "android:activity.animThumbnail";
    108 
    109     /**
    110      * Start X position of thumbnail animation.
    111      * @hide
    112      */
    113     public static final String KEY_ANIM_START_X = "android:activity.animStartX";
    114 
    115     /**
    116      * Start Y position of thumbnail animation.
    117      * @hide
    118      */
    119     public static final String KEY_ANIM_START_Y = "android:activity.animStartY";
    120 
    121     /**
    122      * Initial width of the animation.
    123      * @hide
    124      */
    125     public static final String KEY_ANIM_WIDTH = "android:activity.animWidth";
    126 
    127     /**
    128      * Initial height of the animation.
    129      * @hide
    130      */
    131     public static final String KEY_ANIM_HEIGHT = "android:activity.animHeight";
    132 
    133     /**
    134      * Callback for when animation is started.
    135      * @hide
    136      */
    137     public static final String KEY_ANIM_START_LISTENER = "android:activity.animStartListener";
    138 
    139     /**
    140      * Callback for when the last frame of the animation is played.
    141      * @hide
    142      */
    143     private static final String KEY_ANIMATION_FINISHED_LISTENER =
    144             "android:activity.animationFinishedListener";
    145 
    146     /**
    147      * Descriptions of app transition animations to be played during the activity launch.
    148      */
    149     private static final String KEY_ANIM_SPECS = "android:activity.animSpecs";
    150 
    151     /**
    152      * The stack id the activity should be launched into.
    153      * @hide
    154      */
    155     private static final String KEY_LAUNCH_STACK_ID = "android.activity.launchStackId";
    156 
    157     /**
    158      * The task id the activity should be launched into.
    159      * @hide
    160      */
    161     private static final String KEY_LAUNCH_TASK_ID = "android.activity.launchTaskId";
    162 
    163     /**
    164      * See {@link #setTaskOverlay}.
    165      * @hide
    166      */
    167     private static final String KEY_TASK_OVERLAY = "android.activity.taskOverlay";
    168 
    169     /**
    170      * Where the docked stack should be positioned.
    171      * @hide
    172      */
    173     private static final String KEY_DOCK_CREATE_MODE = "android:activity.dockCreateMode";
    174 
    175     /**
    176      * For Activity transitions, the calling Activity's TransitionListener used to
    177      * notify the called Activity when the shared element and the exit transitions
    178      * complete.
    179      */
    180     private static final String KEY_TRANSITION_COMPLETE_LISTENER
    181             = "android:activity.transitionCompleteListener";
    182 
    183     private static final String KEY_TRANSITION_IS_RETURNING
    184             = "android:activity.transitionIsReturning";
    185     private static final String KEY_TRANSITION_SHARED_ELEMENTS
    186             = "android:activity.sharedElementNames";
    187     private static final String KEY_RESULT_DATA = "android:activity.resultData";
    188     private static final String KEY_RESULT_CODE = "android:activity.resultCode";
    189     private static final String KEY_EXIT_COORDINATOR_INDEX
    190             = "android:activity.exitCoordinatorIndex";
    191 
    192     private static final String KEY_USAGE_TIME_REPORT = "android:activity.usageTimeReport";
    193 
    194     /** @hide */
    195     public static final int ANIM_NONE = 0;
    196     /** @hide */
    197     public static final int ANIM_CUSTOM = 1;
    198     /** @hide */
    199     public static final int ANIM_SCALE_UP = 2;
    200     /** @hide */
    201     public static final int ANIM_THUMBNAIL_SCALE_UP = 3;
    202     /** @hide */
    203     public static final int ANIM_THUMBNAIL_SCALE_DOWN = 4;
    204     /** @hide */
    205     public static final int ANIM_SCENE_TRANSITION = 5;
    206     /** @hide */
    207     public static final int ANIM_DEFAULT = 6;
    208     /** @hide */
    209     public static final int ANIM_LAUNCH_TASK_BEHIND = 7;
    210     /** @hide */
    211     public static final int ANIM_THUMBNAIL_ASPECT_SCALE_UP = 8;
    212     /** @hide */
    213     public static final int ANIM_THUMBNAIL_ASPECT_SCALE_DOWN = 9;
    214     /** @hide */
    215     public static final int ANIM_CUSTOM_IN_PLACE = 10;
    216     /** @hide */
    217     public static final int ANIM_CLIP_REVEAL = 11;
    218 
    219     private String mPackageName;
    220     private Rect mLaunchBounds;
    221     private int mAnimationType = ANIM_NONE;
    222     private int mCustomEnterResId;
    223     private int mCustomExitResId;
    224     private int mCustomInPlaceResId;
    225     private Bitmap mThumbnail;
    226     private int mStartX;
    227     private int mStartY;
    228     private int mWidth;
    229     private int mHeight;
    230     private IRemoteCallback mAnimationStartedListener;
    231     private IRemoteCallback mAnimationFinishedListener;
    232     private ResultReceiver mTransitionReceiver;
    233     private boolean mIsReturning;
    234     private ArrayList<String> mSharedElementNames;
    235     private Intent mResultData;
    236     private int mResultCode;
    237     private int mExitCoordinatorIndex;
    238     private PendingIntent mUsageTimeReport;
    239     private int mLaunchStackId = INVALID_STACK_ID;
    240     private int mLaunchTaskId = -1;
    241     private int mDockCreateMode = DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
    242     private boolean mTaskOverlay;
    243     private AppTransitionAnimationSpec mAnimSpecs[];
    244 
    245     /**
    246      * Create an ActivityOptions specifying a custom animation to run when
    247      * the activity is displayed.
    248      *
    249      * @param context Who is defining this.  This is the application that the
    250      * animation resources will be loaded from.
    251      * @param enterResId A resource ID of the animation resource to use for
    252      * the incoming activity.  Use 0 for no animation.
    253      * @param exitResId A resource ID of the animation resource to use for
    254      * the outgoing activity.  Use 0 for no animation.
    255      * @return Returns a new ActivityOptions object that you can use to
    256      * supply these options as the options Bundle when starting an activity.
    257      */
    258     public static ActivityOptions makeCustomAnimation(Context context,
    259             int enterResId, int exitResId) {
    260         return makeCustomAnimation(context, enterResId, exitResId, null, null);
    261     }
    262 
    263     /**
    264      * Create an ActivityOptions specifying a custom animation to run when
    265      * the activity is displayed.
    266      *
    267      * @param context Who is defining this.  This is the application that the
    268      * animation resources will be loaded from.
    269      * @param enterResId A resource ID of the animation resource to use for
    270      * the incoming activity.  Use 0 for no animation.
    271      * @param exitResId A resource ID of the animation resource to use for
    272      * the outgoing activity.  Use 0 for no animation.
    273      * @param handler If <var>listener</var> is non-null this must be a valid
    274      * Handler on which to dispatch the callback; otherwise it should be null.
    275      * @param listener Optional OnAnimationStartedListener to find out when the
    276      * requested animation has started running.  If for some reason the animation
    277      * is not executed, the callback will happen immediately.
    278      * @return Returns a new ActivityOptions object that you can use to
    279      * supply these options as the options Bundle when starting an activity.
    280      * @hide
    281      */
    282     public static ActivityOptions makeCustomAnimation(Context context,
    283             int enterResId, int exitResId, Handler handler, OnAnimationStartedListener listener) {
    284         ActivityOptions opts = new ActivityOptions();
    285         opts.mPackageName = context.getPackageName();
    286         opts.mAnimationType = ANIM_CUSTOM;
    287         opts.mCustomEnterResId = enterResId;
    288         opts.mCustomExitResId = exitResId;
    289         opts.setOnAnimationStartedListener(handler, listener);
    290         return opts;
    291     }
    292 
    293     /**
    294      * Creates an ActivityOptions specifying a custom animation to run in place on an existing
    295      * activity.
    296      *
    297      * @param context Who is defining this.  This is the application that the
    298      * animation resources will be loaded from.
    299      * @param animId A resource ID of the animation resource to use for
    300      * the incoming activity.
    301      * @return Returns a new ActivityOptions object that you can use to
    302      * supply these options as the options Bundle when running an in-place animation.
    303      * @hide
    304      */
    305     public static ActivityOptions makeCustomInPlaceAnimation(Context context, int animId) {
    306         if (animId == 0) {
    307             throw new RuntimeException("You must specify a valid animation.");
    308         }
    309 
    310         ActivityOptions opts = new ActivityOptions();
    311         opts.mPackageName = context.getPackageName();
    312         opts.mAnimationType = ANIM_CUSTOM_IN_PLACE;
    313         opts.mCustomInPlaceResId = animId;
    314         return opts;
    315     }
    316 
    317     private void setOnAnimationStartedListener(final Handler handler,
    318             final OnAnimationStartedListener listener) {
    319         if (listener != null) {
    320             mAnimationStartedListener = new IRemoteCallback.Stub() {
    321                 @Override
    322                 public void sendResult(Bundle data) throws RemoteException {
    323                     handler.post(new Runnable() {
    324                         @Override public void run() {
    325                             listener.onAnimationStarted();
    326                         }
    327                     });
    328                 }
    329             };
    330         }
    331     }
    332 
    333     /**
    334      * Callback for use with {@link ActivityOptions#makeThumbnailScaleUpAnimation}
    335      * to find out when the given animation has started running.
    336      * @hide
    337      */
    338     public interface OnAnimationStartedListener {
    339         void onAnimationStarted();
    340     }
    341 
    342     private void setOnAnimationFinishedListener(final Handler handler,
    343             final OnAnimationFinishedListener listener) {
    344         if (listener != null) {
    345             mAnimationFinishedListener = new IRemoteCallback.Stub() {
    346                 @Override
    347                 public void sendResult(Bundle data) throws RemoteException {
    348                     handler.post(new Runnable() {
    349                         @Override
    350                         public void run() {
    351                             listener.onAnimationFinished();
    352                         }
    353                     });
    354                 }
    355             };
    356         }
    357     }
    358 
    359     /**
    360      * Callback for use with {@link ActivityOptions#makeThumbnailAspectScaleDownAnimation}
    361      * to find out when the given animation has drawn its last frame.
    362      * @hide
    363      */
    364     public interface OnAnimationFinishedListener {
    365         void onAnimationFinished();
    366     }
    367 
    368     /**
    369      * Create an ActivityOptions specifying an animation where the new
    370      * activity is scaled from a small originating area of the screen to
    371      * its final full representation.
    372      *
    373      * <p>If the Intent this is being used with has not set its
    374      * {@link android.content.Intent#setSourceBounds Intent.setSourceBounds},
    375      * those bounds will be filled in for you based on the initial
    376      * bounds passed in here.
    377      *
    378      * @param source The View that the new activity is animating from.  This
    379      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
    380      * @param startX The x starting location of the new activity, relative to <var>source</var>.
    381      * @param startY The y starting location of the activity, relative to <var>source</var>.
    382      * @param width The initial width of the new activity.
    383      * @param height The initial height of the new activity.
    384      * @return Returns a new ActivityOptions object that you can use to
    385      * supply these options as the options Bundle when starting an activity.
    386      */
    387     public static ActivityOptions makeScaleUpAnimation(View source,
    388             int startX, int startY, int width, int height) {
    389         ActivityOptions opts = new ActivityOptions();
    390         opts.mPackageName = source.getContext().getPackageName();
    391         opts.mAnimationType = ANIM_SCALE_UP;
    392         int[] pts = new int[2];
    393         source.getLocationOnScreen(pts);
    394         opts.mStartX = pts[0] + startX;
    395         opts.mStartY = pts[1] + startY;
    396         opts.mWidth = width;
    397         opts.mHeight = height;
    398         return opts;
    399     }
    400 
    401     /**
    402      * Create an ActivityOptions specifying an animation where the new
    403      * activity is revealed from a small originating area of the screen to
    404      * its final full representation.
    405      *
    406      * @param source The View that the new activity is animating from.  This
    407      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
    408      * @param startX The x starting location of the new activity, relative to <var>source</var>.
    409      * @param startY The y starting location of the activity, relative to <var>source</var>.
    410      * @param width The initial width of the new activity.
    411      * @param height The initial height of the new activity.
    412      * @return Returns a new ActivityOptions object that you can use to
    413      * supply these options as the options Bundle when starting an activity.
    414      */
    415     public static ActivityOptions makeClipRevealAnimation(View source,
    416             int startX, int startY, int width, int height) {
    417         ActivityOptions opts = new ActivityOptions();
    418         opts.mAnimationType = ANIM_CLIP_REVEAL;
    419         int[] pts = new int[2];
    420         source.getLocationOnScreen(pts);
    421         opts.mStartX = pts[0] + startX;
    422         opts.mStartY = pts[1] + startY;
    423         opts.mWidth = width;
    424         opts.mHeight = height;
    425         return opts;
    426     }
    427 
    428     /**
    429      * Create an ActivityOptions specifying an animation where a thumbnail
    430      * is scaled from a given position to the new activity window that is
    431      * being started.
    432      *
    433      * <p>If the Intent this is being used with has not set its
    434      * {@link android.content.Intent#setSourceBounds Intent.setSourceBounds},
    435      * those bounds will be filled in for you based on the initial
    436      * thumbnail location and size provided here.
    437      *
    438      * @param source The View that this thumbnail is animating from.  This
    439      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
    440      * @param thumbnail The bitmap that will be shown as the initial thumbnail
    441      * of the animation.
    442      * @param startX The x starting location of the bitmap, relative to <var>source</var>.
    443      * @param startY The y starting location of the bitmap, relative to <var>source</var>.
    444      * @return Returns a new ActivityOptions object that you can use to
    445      * supply these options as the options Bundle when starting an activity.
    446      */
    447     public static ActivityOptions makeThumbnailScaleUpAnimation(View source,
    448             Bitmap thumbnail, int startX, int startY) {
    449         return makeThumbnailScaleUpAnimation(source, thumbnail, startX, startY, null);
    450     }
    451 
    452     /**
    453      * Create an ActivityOptions specifying an animation where a thumbnail
    454      * is scaled from a given position to the new activity window that is
    455      * being started.
    456      *
    457      * @param source The View that this thumbnail is animating from.  This
    458      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
    459      * @param thumbnail The bitmap that will be shown as the initial thumbnail
    460      * of the animation.
    461      * @param startX The x starting location of the bitmap, relative to <var>source</var>.
    462      * @param startY The y starting location of the bitmap, relative to <var>source</var>.
    463      * @param listener Optional OnAnimationStartedListener to find out when the
    464      * requested animation has started running.  If for some reason the animation
    465      * is not executed, the callback will happen immediately.
    466      * @return Returns a new ActivityOptions object that you can use to
    467      * supply these options as the options Bundle when starting an activity.
    468      * @hide
    469      */
    470     public static ActivityOptions makeThumbnailScaleUpAnimation(View source,
    471             Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
    472         return makeThumbnailAnimation(source, thumbnail, startX, startY, listener, true);
    473     }
    474 
    475     /**
    476      * Create an ActivityOptions specifying an animation where an activity window
    477      * is scaled from a given position to a thumbnail at a specified location.
    478      *
    479      * @param source The View that this thumbnail is animating to.  This
    480      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
    481      * @param thumbnail The bitmap that will be shown as the final thumbnail
    482      * of the animation.
    483      * @param startX The x end location of the bitmap, relative to <var>source</var>.
    484      * @param startY The y end location of the bitmap, relative to <var>source</var>.
    485      * @param listener Optional OnAnimationStartedListener to find out when the
    486      * requested animation has started running.  If for some reason the animation
    487      * is not executed, the callback will happen immediately.
    488      * @return Returns a new ActivityOptions object that you can use to
    489      * supply these options as the options Bundle when starting an activity.
    490      * @hide
    491      */
    492     public static ActivityOptions makeThumbnailScaleDownAnimation(View source,
    493             Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
    494         return makeThumbnailAnimation(source, thumbnail, startX, startY, listener, false);
    495     }
    496 
    497     private static ActivityOptions makeThumbnailAnimation(View source,
    498             Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener,
    499             boolean scaleUp) {
    500         ActivityOptions opts = new ActivityOptions();
    501         opts.mPackageName = source.getContext().getPackageName();
    502         opts.mAnimationType = scaleUp ? ANIM_THUMBNAIL_SCALE_UP : ANIM_THUMBNAIL_SCALE_DOWN;
    503         opts.mThumbnail = thumbnail;
    504         int[] pts = new int[2];
    505         source.getLocationOnScreen(pts);
    506         opts.mStartX = pts[0] + startX;
    507         opts.mStartY = pts[1] + startY;
    508         opts.setOnAnimationStartedListener(source.getHandler(), listener);
    509         return opts;
    510     }
    511 
    512     /**
    513      * Create an ActivityOptions specifying an animation where the new activity
    514      * window and a thumbnail is aspect-scaled to a new location.
    515      *
    516      * @param source The View that this thumbnail is animating from.  This
    517      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
    518      * @param thumbnail The bitmap that will be shown as the initial thumbnail
    519      * of the animation.
    520      * @param startX The x starting location of the bitmap, relative to <var>source</var>.
    521      * @param startY The y starting location of the bitmap, relative to <var>source</var>.
    522      * @param handler If <var>listener</var> is non-null this must be a valid
    523      * Handler on which to dispatch the callback; otherwise it should be null.
    524      * @param listener Optional OnAnimationStartedListener to find out when the
    525      * requested animation has started running.  If for some reason the animation
    526      * is not executed, the callback will happen immediately.
    527      * @return Returns a new ActivityOptions object that you can use to
    528      * supply these options as the options Bundle when starting an activity.
    529      * @hide
    530      */
    531     public static ActivityOptions makeThumbnailAspectScaleUpAnimation(View source,
    532             Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight,
    533             Handler handler, OnAnimationStartedListener listener) {
    534         return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY,
    535                 targetWidth, targetHeight, handler, listener, true);
    536     }
    537 
    538     /**
    539      * Create an ActivityOptions specifying an animation where the new activity
    540      * window and a thumbnail is aspect-scaled to a new location.
    541      *
    542      * @param source The View that this thumbnail is animating to.  This
    543      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
    544      * @param thumbnail The bitmap that will be shown as the final thumbnail
    545      * of the animation.
    546      * @param startX The x end location of the bitmap, relative to <var>source</var>.
    547      * @param startY The y end location of the bitmap, relative to <var>source</var>.
    548      * @param handler If <var>listener</var> is non-null this must be a valid
    549      * Handler on which to dispatch the callback; otherwise it should be null.
    550      * @param listener Optional OnAnimationStartedListener to find out when the
    551      * requested animation has started running.  If for some reason the animation
    552      * is not executed, the callback will happen immediately.
    553      * @return Returns a new ActivityOptions object that you can use to
    554      * supply these options as the options Bundle when starting an activity.
    555      * @hide
    556      */
    557     public static ActivityOptions makeThumbnailAspectScaleDownAnimation(View source,
    558             Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight,
    559             Handler handler, OnAnimationStartedListener listener) {
    560         return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY,
    561                 targetWidth, targetHeight, handler, listener, false);
    562     }
    563 
    564     private static ActivityOptions makeAspectScaledThumbnailAnimation(View source, Bitmap thumbnail,
    565             int startX, int startY, int targetWidth, int targetHeight,
    566             Handler handler, OnAnimationStartedListener listener, boolean scaleUp) {
    567         ActivityOptions opts = new ActivityOptions();
    568         opts.mPackageName = source.getContext().getPackageName();
    569         opts.mAnimationType = scaleUp ? ANIM_THUMBNAIL_ASPECT_SCALE_UP :
    570                 ANIM_THUMBNAIL_ASPECT_SCALE_DOWN;
    571         opts.mThumbnail = thumbnail;
    572         int[] pts = new int[2];
    573         source.getLocationOnScreen(pts);
    574         opts.mStartX = pts[0] + startX;
    575         opts.mStartY = pts[1] + startY;
    576         opts.mWidth = targetWidth;
    577         opts.mHeight = targetHeight;
    578         opts.setOnAnimationStartedListener(handler, listener);
    579         return opts;
    580     }
    581 
    582     /** @hide */
    583     public static ActivityOptions makeThumbnailAspectScaleDownAnimation(View source,
    584             AppTransitionAnimationSpec[] specs, Handler handler,
    585             OnAnimationStartedListener onAnimationStartedListener,
    586             OnAnimationFinishedListener onAnimationFinishedListener) {
    587         ActivityOptions opts = new ActivityOptions();
    588         opts.mPackageName = source.getContext().getPackageName();
    589         opts.mAnimationType = ANIM_THUMBNAIL_ASPECT_SCALE_DOWN;
    590         opts.mAnimSpecs = specs;
    591         opts.setOnAnimationStartedListener(handler, onAnimationStartedListener);
    592         opts.setOnAnimationFinishedListener(handler, onAnimationFinishedListener);
    593         return opts;
    594     }
    595 
    596     /**
    597      * Create an ActivityOptions to transition between Activities using cross-Activity scene
    598      * animations. This method carries the position of one shared element to the started Activity.
    599      * The position of <code>sharedElement</code> will be used as the epicenter for the
    600      * exit Transition. The position of the shared element in the launched Activity will be the
    601      * epicenter of its entering Transition.
    602      *
    603      * <p>This requires {@link android.view.Window#FEATURE_ACTIVITY_TRANSITIONS} to be
    604      * enabled on the calling Activity to cause an exit transition. The same must be in
    605      * the called Activity to get an entering transition.</p>
    606      * @param activity The Activity whose window contains the shared elements.
    607      * @param sharedElement The View to transition to the started Activity.
    608      * @param sharedElementName The shared element name as used in the target Activity. This
    609      *                          must not be null.
    610      * @return Returns a new ActivityOptions object that you can use to
    611      *         supply these options as the options Bundle when starting an activity.
    612      * @see android.transition.Transition#setEpicenterCallback(
    613      *          android.transition.Transition.EpicenterCallback)
    614      */
    615     public static ActivityOptions makeSceneTransitionAnimation(Activity activity,
    616             View sharedElement, String sharedElementName) {
    617         return makeSceneTransitionAnimation(activity, Pair.create(sharedElement, sharedElementName));
    618     }
    619 
    620     /**
    621      * Create an ActivityOptions to transition between Activities using cross-Activity scene
    622      * animations. This method carries the position of multiple shared elements to the started
    623      * Activity. The position of the first element in sharedElements
    624      * will be used as the epicenter for the exit Transition. The position of the associated
    625      * shared element in the launched Activity will be the epicenter of its entering Transition.
    626      *
    627      * <p>This requires {@link android.view.Window#FEATURE_ACTIVITY_TRANSITIONS} to be
    628      * enabled on the calling Activity to cause an exit transition. The same must be in
    629      * the called Activity to get an entering transition.</p>
    630      * @param activity The Activity whose window contains the shared elements.
    631      * @param sharedElements The names of the shared elements to transfer to the called
    632      *                       Activity and their associated Views. The Views must each have
    633      *                       a unique shared element name.
    634      * @return Returns a new ActivityOptions object that you can use to
    635      *         supply these options as the options Bundle when starting an activity.
    636      * @see android.transition.Transition#setEpicenterCallback(
    637      *          android.transition.Transition.EpicenterCallback)
    638      */
    639     @SafeVarargs
    640     public static ActivityOptions makeSceneTransitionAnimation(Activity activity,
    641             Pair<View, String>... sharedElements) {
    642         ActivityOptions opts = new ActivityOptions();
    643         if (!activity.getWindow().hasFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)) {
    644             opts.mAnimationType = ANIM_DEFAULT;
    645             return opts;
    646         }
    647         opts.mAnimationType = ANIM_SCENE_TRANSITION;
    648 
    649         ArrayList<String> names = new ArrayList<String>();
    650         ArrayList<View> views = new ArrayList<View>();
    651 
    652         if (sharedElements != null) {
    653             for (int i = 0; i < sharedElements.length; i++) {
    654                 Pair<View, String> sharedElement = sharedElements[i];
    655                 String sharedElementName = sharedElement.second;
    656                 if (sharedElementName == null) {
    657                     throw new IllegalArgumentException("Shared element name must not be null");
    658                 }
    659                 names.add(sharedElementName);
    660                 View view = sharedElement.first;
    661                 if (view == null) {
    662                     throw new IllegalArgumentException("Shared element must not be null");
    663                 }
    664                 views.add(sharedElement.first);
    665             }
    666         }
    667 
    668         ExitTransitionCoordinator exit = new ExitTransitionCoordinator(activity, names, names,
    669                 views, false);
    670         opts.mTransitionReceiver = exit;
    671         opts.mSharedElementNames = names;
    672         opts.mIsReturning = false;
    673         opts.mExitCoordinatorIndex =
    674                 activity.mActivityTransitionState.addExitTransitionCoordinator(exit);
    675         return opts;
    676     }
    677 
    678     /** @hide */
    679     public static ActivityOptions makeSceneTransitionAnimation(Activity activity,
    680             ExitTransitionCoordinator exitCoordinator, ArrayList<String> sharedElementNames,
    681             int resultCode, Intent resultData) {
    682         ActivityOptions opts = new ActivityOptions();
    683         opts.mAnimationType = ANIM_SCENE_TRANSITION;
    684         opts.mSharedElementNames = sharedElementNames;
    685         opts.mTransitionReceiver = exitCoordinator;
    686         opts.mIsReturning = true;
    687         opts.mResultCode = resultCode;
    688         opts.mResultData = resultData;
    689         opts.mExitCoordinatorIndex =
    690                 activity.mActivityTransitionState.addExitTransitionCoordinator(exitCoordinator);
    691         return opts;
    692     }
    693 
    694     /**
    695      * If set along with Intent.FLAG_ACTIVITY_NEW_DOCUMENT then the task being launched will not be
    696      * presented to the user but will instead be only available through the recents task list.
    697      * In addition, the new task wil be affiliated with the launching activity's task.
    698      * Affiliated tasks are grouped together in the recents task list.
    699      *
    700      * <p>This behavior is not supported for activities with {@link
    701      * android.R.styleable#AndroidManifestActivity_launchMode launchMode} values of
    702      * <code>singleInstance</code> or <code>singleTask</code>.
    703      */
    704     public static ActivityOptions makeTaskLaunchBehind() {
    705         final ActivityOptions opts = new ActivityOptions();
    706         opts.mAnimationType = ANIM_LAUNCH_TASK_BEHIND;
    707         return opts;
    708     }
    709 
    710     /**
    711      * Create a basic ActivityOptions that has no special animation associated with it.
    712      * Other options can still be set.
    713      */
    714     public static ActivityOptions makeBasic() {
    715         final ActivityOptions opts = new ActivityOptions();
    716         return opts;
    717     }
    718 
    719     /** @hide */
    720     public boolean getLaunchTaskBehind() {
    721         return mAnimationType == ANIM_LAUNCH_TASK_BEHIND;
    722     }
    723 
    724     private ActivityOptions() {
    725     }
    726 
    727     /** @hide */
    728     public ActivityOptions(Bundle opts) {
    729         // If the remote side sent us bad parcelables, they won't get the
    730         // results they want, which is their loss.
    731         opts.setDefusable(true);
    732 
    733         mPackageName = opts.getString(KEY_PACKAGE_NAME);
    734         try {
    735             mUsageTimeReport = opts.getParcelable(KEY_USAGE_TIME_REPORT);
    736         } catch (RuntimeException e) {
    737             Slog.w(TAG, e);
    738         }
    739         mLaunchBounds = opts.getParcelable(KEY_LAUNCH_BOUNDS);
    740         mAnimationType = opts.getInt(KEY_ANIM_TYPE);
    741         switch (mAnimationType) {
    742             case ANIM_CUSTOM:
    743                 mCustomEnterResId = opts.getInt(KEY_ANIM_ENTER_RES_ID, 0);
    744                 mCustomExitResId = opts.getInt(KEY_ANIM_EXIT_RES_ID, 0);
    745                 mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
    746                         opts.getBinder(KEY_ANIM_START_LISTENER));
    747                 break;
    748 
    749             case ANIM_CUSTOM_IN_PLACE:
    750                 mCustomInPlaceResId = opts.getInt(KEY_ANIM_IN_PLACE_RES_ID, 0);
    751                 break;
    752 
    753             case ANIM_SCALE_UP:
    754             case ANIM_CLIP_REVEAL:
    755                 mStartX = opts.getInt(KEY_ANIM_START_X, 0);
    756                 mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
    757                 mWidth = opts.getInt(KEY_ANIM_WIDTH, 0);
    758                 mHeight = opts.getInt(KEY_ANIM_HEIGHT, 0);
    759                 break;
    760 
    761             case ANIM_THUMBNAIL_SCALE_UP:
    762             case ANIM_THUMBNAIL_SCALE_DOWN:
    763             case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
    764             case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
    765                 mThumbnail = (Bitmap) opts.getParcelable(KEY_ANIM_THUMBNAIL);
    766                 mStartX = opts.getInt(KEY_ANIM_START_X, 0);
    767                 mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
    768                 mWidth = opts.getInt(KEY_ANIM_WIDTH, 0);
    769                 mHeight = opts.getInt(KEY_ANIM_HEIGHT, 0);
    770                 mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
    771                         opts.getBinder(KEY_ANIM_START_LISTENER));
    772                 break;
    773 
    774             case ANIM_SCENE_TRANSITION:
    775                 mTransitionReceiver = opts.getParcelable(KEY_TRANSITION_COMPLETE_LISTENER);
    776                 mIsReturning = opts.getBoolean(KEY_TRANSITION_IS_RETURNING, false);
    777                 mSharedElementNames = opts.getStringArrayList(KEY_TRANSITION_SHARED_ELEMENTS);
    778                 mResultData = opts.getParcelable(KEY_RESULT_DATA);
    779                 mResultCode = opts.getInt(KEY_RESULT_CODE);
    780                 mExitCoordinatorIndex = opts.getInt(KEY_EXIT_COORDINATOR_INDEX);
    781                 break;
    782         }
    783         mLaunchStackId = opts.getInt(KEY_LAUNCH_STACK_ID, INVALID_STACK_ID);
    784         mLaunchTaskId = opts.getInt(KEY_LAUNCH_TASK_ID, -1);
    785         mTaskOverlay = opts.getBoolean(KEY_TASK_OVERLAY, false);
    786         mDockCreateMode = opts.getInt(KEY_DOCK_CREATE_MODE, DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT);
    787         if (opts.containsKey(KEY_ANIM_SPECS)) {
    788             Parcelable[] specs = opts.getParcelableArray(KEY_ANIM_SPECS);
    789             mAnimSpecs = new AppTransitionAnimationSpec[specs.length];
    790             for (int i = specs.length - 1; i >= 0; i--) {
    791                 mAnimSpecs[i] = (AppTransitionAnimationSpec) specs[i];
    792             }
    793         }
    794         if (opts.containsKey(KEY_ANIMATION_FINISHED_LISTENER)) {
    795             mAnimationFinishedListener = IRemoteCallback.Stub.asInterface(
    796                     opts.getBinder(KEY_ANIMATION_FINISHED_LISTENER));
    797         }
    798     }
    799 
    800     /**
    801      * Sets the bounds (window size) that the activity should be launched in.
    802      * Rect position should be provided in pixels and in screen coordinates.
    803      * Set to null explicitly for fullscreen.
    804      * <p>
    805      * <strong>NOTE:<strong/> This value is ignored on devices that don't have
    806      * {@link android.content.pm.PackageManager#FEATURE_FREEFORM_WINDOW_MANAGEMENT} or
    807      * {@link android.content.pm.PackageManager#FEATURE_PICTURE_IN_PICTURE} enabled.
    808      * @param screenSpacePixelRect Launch bounds to use for the activity or null for fullscreen.
    809      */
    810     public ActivityOptions setLaunchBounds(@Nullable Rect screenSpacePixelRect) {
    811         mLaunchBounds = screenSpacePixelRect != null ? new Rect(screenSpacePixelRect) : null;
    812         return this;
    813     }
    814 
    815     /** @hide */
    816     public String getPackageName() {
    817         return mPackageName;
    818     }
    819 
    820     /**
    821      * Returns the bounds that should be used to launch the activity.
    822      * @see #setLaunchBounds(Rect)
    823      * @return Bounds used to launch the activity.
    824      */
    825     @Nullable
    826     public Rect getLaunchBounds() {
    827         return mLaunchBounds;
    828     }
    829 
    830     /** @hide */
    831     public int getAnimationType() {
    832         return mAnimationType;
    833     }
    834 
    835     /** @hide */
    836     public int getCustomEnterResId() {
    837         return mCustomEnterResId;
    838     }
    839 
    840     /** @hide */
    841     public int getCustomExitResId() {
    842         return mCustomExitResId;
    843     }
    844 
    845     /** @hide */
    846     public int getCustomInPlaceResId() {
    847         return mCustomInPlaceResId;
    848     }
    849 
    850     /** @hide */
    851     public Bitmap getThumbnail() {
    852         return mThumbnail;
    853     }
    854 
    855     /** @hide */
    856     public int getStartX() {
    857         return mStartX;
    858     }
    859 
    860     /** @hide */
    861     public int getStartY() {
    862         return mStartY;
    863     }
    864 
    865     /** @hide */
    866     public int getWidth() {
    867         return mWidth;
    868     }
    869 
    870     /** @hide */
    871     public int getHeight() {
    872         return mHeight;
    873     }
    874 
    875     /** @hide */
    876     public IRemoteCallback getOnAnimationStartListener() {
    877         return mAnimationStartedListener;
    878     }
    879 
    880     /** @hide */
    881     public IRemoteCallback getAnimationFinishedListener() {
    882         return mAnimationFinishedListener;
    883     }
    884 
    885     /** @hide */
    886     public int getExitCoordinatorKey() { return mExitCoordinatorIndex; }
    887 
    888     /** @hide */
    889     public void abort() {
    890         if (mAnimationStartedListener != null) {
    891             try {
    892                 mAnimationStartedListener.sendResult(null);
    893             } catch (RemoteException e) {
    894             }
    895         }
    896     }
    897 
    898     /** @hide */
    899     public boolean isReturning() {
    900         return mIsReturning;
    901     }
    902 
    903     /** @hide */
    904     public ArrayList<String> getSharedElementNames() {
    905         return mSharedElementNames;
    906     }
    907 
    908     /** @hide */
    909     public ResultReceiver getResultReceiver() { return mTransitionReceiver; }
    910 
    911     /** @hide */
    912     public int getResultCode() { return mResultCode; }
    913 
    914     /** @hide */
    915     public Intent getResultData() { return mResultData; }
    916 
    917     /** @hide */
    918     public PendingIntent getUsageTimeReport() {
    919         return mUsageTimeReport;
    920     }
    921 
    922     /** @hide */
    923     public AppTransitionAnimationSpec[] getAnimSpecs() { return mAnimSpecs; }
    924 
    925     /** @hide */
    926     public static ActivityOptions fromBundle(Bundle bOptions) {
    927         return bOptions != null ? new ActivityOptions(bOptions) : null;
    928     }
    929 
    930     /** @hide */
    931     public static void abort(ActivityOptions options) {
    932         if (options != null) {
    933             options.abort();
    934         }
    935     }
    936 
    937     /** @hide */
    938     public int getLaunchStackId() {
    939         return mLaunchStackId;
    940     }
    941 
    942     /** @hide */
    943     @TestApi
    944     public void setLaunchStackId(int launchStackId) {
    945         mLaunchStackId = launchStackId;
    946     }
    947 
    948     /**
    949      * Sets the task the activity will be launched in.
    950      * @hide
    951      */
    952     public void setLaunchTaskId(int taskId) {
    953         mLaunchTaskId = taskId;
    954     }
    955 
    956     /**
    957      * @hide
    958      */
    959     public int getLaunchTaskId() {
    960         return mLaunchTaskId;
    961     }
    962 
    963     /**
    964      * Set's whether the activity launched with this option should be a task overlay. That is the
    965      * activity will always be the top activity of the task and doesn't cause the task to be moved
    966      * to the front when it is added.
    967      * @hide
    968      */
    969     public void setTaskOverlay(boolean taskOverlay) {
    970         mTaskOverlay = taskOverlay;
    971     }
    972 
    973     /**
    974      * @hide
    975      */
    976     public boolean getTaskOverlay() {
    977         return mTaskOverlay;
    978     }
    979 
    980     /** @hide */
    981     public int getDockCreateMode() {
    982         return mDockCreateMode;
    983     }
    984 
    985     /** @hide */
    986     public void setDockCreateMode(int dockCreateMode) {
    987         mDockCreateMode = dockCreateMode;
    988     }
    989 
    990     /**
    991      * Update the current values in this ActivityOptions from those supplied
    992      * in <var>otherOptions</var>.  Any values
    993      * defined in <var>otherOptions</var> replace those in the base options.
    994      */
    995     public void update(ActivityOptions otherOptions) {
    996         if (otherOptions.mPackageName != null) {
    997             mPackageName = otherOptions.mPackageName;
    998         }
    999         mUsageTimeReport = otherOptions.mUsageTimeReport;
   1000         mTransitionReceiver = null;
   1001         mSharedElementNames = null;
   1002         mIsReturning = false;
   1003         mResultData = null;
   1004         mResultCode = 0;
   1005         mExitCoordinatorIndex = 0;
   1006         mAnimationType = otherOptions.mAnimationType;
   1007         switch (otherOptions.mAnimationType) {
   1008             case ANIM_CUSTOM:
   1009                 mCustomEnterResId = otherOptions.mCustomEnterResId;
   1010                 mCustomExitResId = otherOptions.mCustomExitResId;
   1011                 mThumbnail = null;
   1012                 if (mAnimationStartedListener != null) {
   1013                     try {
   1014                         mAnimationStartedListener.sendResult(null);
   1015                     } catch (RemoteException e) {
   1016                     }
   1017                 }
   1018                 mAnimationStartedListener = otherOptions.mAnimationStartedListener;
   1019                 break;
   1020             case ANIM_CUSTOM_IN_PLACE:
   1021                 mCustomInPlaceResId = otherOptions.mCustomInPlaceResId;
   1022                 break;
   1023             case ANIM_SCALE_UP:
   1024                 mStartX = otherOptions.mStartX;
   1025                 mStartY = otherOptions.mStartY;
   1026                 mWidth = otherOptions.mWidth;
   1027                 mHeight = otherOptions.mHeight;
   1028                 if (mAnimationStartedListener != null) {
   1029                     try {
   1030                         mAnimationStartedListener.sendResult(null);
   1031                     } catch (RemoteException e) {
   1032                     }
   1033                 }
   1034                 mAnimationStartedListener = null;
   1035                 break;
   1036             case ANIM_THUMBNAIL_SCALE_UP:
   1037             case ANIM_THUMBNAIL_SCALE_DOWN:
   1038             case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
   1039             case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
   1040                 mThumbnail = otherOptions.mThumbnail;
   1041                 mStartX = otherOptions.mStartX;
   1042                 mStartY = otherOptions.mStartY;
   1043                 mWidth = otherOptions.mWidth;
   1044                 mHeight = otherOptions.mHeight;
   1045                 if (mAnimationStartedListener != null) {
   1046                     try {
   1047                         mAnimationStartedListener.sendResult(null);
   1048                     } catch (RemoteException e) {
   1049                     }
   1050                 }
   1051                 mAnimationStartedListener = otherOptions.mAnimationStartedListener;
   1052                 break;
   1053             case ANIM_SCENE_TRANSITION:
   1054                 mTransitionReceiver = otherOptions.mTransitionReceiver;
   1055                 mSharedElementNames = otherOptions.mSharedElementNames;
   1056                 mIsReturning = otherOptions.mIsReturning;
   1057                 mThumbnail = null;
   1058                 mAnimationStartedListener = null;
   1059                 mResultData = otherOptions.mResultData;
   1060                 mResultCode = otherOptions.mResultCode;
   1061                 mExitCoordinatorIndex = otherOptions.mExitCoordinatorIndex;
   1062                 break;
   1063         }
   1064         mAnimSpecs = otherOptions.mAnimSpecs;
   1065         mAnimationFinishedListener = otherOptions.mAnimationFinishedListener;
   1066     }
   1067 
   1068     /**
   1069      * Returns the created options as a Bundle, which can be passed to
   1070      * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle)
   1071      * Context.startActivity(Intent, Bundle)} and related methods.
   1072      * Note that the returned Bundle is still owned by the ActivityOptions
   1073      * object; you must not modify it, but can supply it to the startActivity
   1074      * methods that take an options Bundle.
   1075      */
   1076     public Bundle toBundle() {
   1077         if (mAnimationType == ANIM_DEFAULT) {
   1078             return null;
   1079         }
   1080         Bundle b = new Bundle();
   1081         if (mPackageName != null) {
   1082             b.putString(KEY_PACKAGE_NAME, mPackageName);
   1083         }
   1084         if (mLaunchBounds != null) {
   1085             b.putParcelable(KEY_LAUNCH_BOUNDS, mLaunchBounds);
   1086         }
   1087         b.putInt(KEY_ANIM_TYPE, mAnimationType);
   1088         if (mUsageTimeReport != null) {
   1089             b.putParcelable(KEY_USAGE_TIME_REPORT, mUsageTimeReport);
   1090         }
   1091         switch (mAnimationType) {
   1092             case ANIM_CUSTOM:
   1093                 b.putInt(KEY_ANIM_ENTER_RES_ID, mCustomEnterResId);
   1094                 b.putInt(KEY_ANIM_EXIT_RES_ID, mCustomExitResId);
   1095                 b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
   1096                         != null ? mAnimationStartedListener.asBinder() : null);
   1097                 break;
   1098             case ANIM_CUSTOM_IN_PLACE:
   1099                 b.putInt(KEY_ANIM_IN_PLACE_RES_ID, mCustomInPlaceResId);
   1100                 break;
   1101             case ANIM_SCALE_UP:
   1102             case ANIM_CLIP_REVEAL:
   1103                 b.putInt(KEY_ANIM_START_X, mStartX);
   1104                 b.putInt(KEY_ANIM_START_Y, mStartY);
   1105                 b.putInt(KEY_ANIM_WIDTH, mWidth);
   1106                 b.putInt(KEY_ANIM_HEIGHT, mHeight);
   1107                 break;
   1108             case ANIM_THUMBNAIL_SCALE_UP:
   1109             case ANIM_THUMBNAIL_SCALE_DOWN:
   1110             case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
   1111             case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
   1112                 b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
   1113                 b.putInt(KEY_ANIM_START_X, mStartX);
   1114                 b.putInt(KEY_ANIM_START_Y, mStartY);
   1115                 b.putInt(KEY_ANIM_WIDTH, mWidth);
   1116                 b.putInt(KEY_ANIM_HEIGHT, mHeight);
   1117                 b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
   1118                         != null ? mAnimationStartedListener.asBinder() : null);
   1119                 break;
   1120             case ANIM_SCENE_TRANSITION:
   1121                 if (mTransitionReceiver != null) {
   1122                     b.putParcelable(KEY_TRANSITION_COMPLETE_LISTENER, mTransitionReceiver);
   1123                 }
   1124                 b.putBoolean(KEY_TRANSITION_IS_RETURNING, mIsReturning);
   1125                 b.putStringArrayList(KEY_TRANSITION_SHARED_ELEMENTS, mSharedElementNames);
   1126                 b.putParcelable(KEY_RESULT_DATA, mResultData);
   1127                 b.putInt(KEY_RESULT_CODE, mResultCode);
   1128                 b.putInt(KEY_EXIT_COORDINATOR_INDEX, mExitCoordinatorIndex);
   1129                 break;
   1130         }
   1131         b.putInt(KEY_LAUNCH_STACK_ID, mLaunchStackId);
   1132         b.putInt(KEY_LAUNCH_TASK_ID, mLaunchTaskId);
   1133         b.putBoolean(KEY_TASK_OVERLAY, mTaskOverlay);
   1134         b.putInt(KEY_DOCK_CREATE_MODE, mDockCreateMode);
   1135         if (mAnimSpecs != null) {
   1136             b.putParcelableArray(KEY_ANIM_SPECS, mAnimSpecs);
   1137         }
   1138         if (mAnimationFinishedListener != null) {
   1139             b.putBinder(KEY_ANIMATION_FINISHED_LISTENER, mAnimationFinishedListener.asBinder());
   1140         }
   1141 
   1142         return b;
   1143     }
   1144 
   1145     /**
   1146      * Ask the the system track that time the user spends in the app being launched, and
   1147      * report it back once done.  The report will be sent to the given receiver, with
   1148      * the extras {@link #EXTRA_USAGE_TIME_REPORT} and {@link #EXTRA_USAGE_TIME_REPORT_PACKAGES}
   1149      * filled in.
   1150      *
   1151      * <p>The time interval tracked is from launching this activity until the user leaves
   1152      * that activity's flow.  They are considered to stay in the flow as long as
   1153      * new activities are being launched or returned to from the original flow,
   1154      * even if this crosses package or task boundaries.  For example, if the originator
   1155      * starts an activity to view an image, and while there the user selects to share,
   1156      * which launches their email app in a new task, and they complete the share, the
   1157      * time during that entire operation will be included until they finally hit back from
   1158      * the original image viewer activity.</p>
   1159      *
   1160      * <p>The user is considered to complete a flow once they switch to another
   1161      * activity that is not part of the tracked flow.  This may happen, for example, by
   1162      * using the notification shade, launcher, or recents to launch or switch to another
   1163      * app.  Simply going in to these navigation elements does not break the flow (although
   1164      * the launcher and recents stops time tracking of the session); it is the act of
   1165      * going somewhere else that completes the tracking.</p>
   1166      *
   1167      * @param receiver A broadcast receiver that willl receive the report.
   1168      */
   1169     public void requestUsageTimeReport(PendingIntent receiver) {
   1170         mUsageTimeReport = receiver;
   1171     }
   1172 
   1173     /**
   1174      * Return the filtered options only meant to be seen by the target activity itself
   1175      * @hide
   1176      */
   1177     public ActivityOptions forTargetActivity() {
   1178         if (mAnimationType == ANIM_SCENE_TRANSITION) {
   1179             final ActivityOptions result = new ActivityOptions();
   1180             result.update(this);
   1181             return result;
   1182         }
   1183 
   1184         return null;
   1185     }
   1186 
   1187     /** @hide */
   1188     @Override
   1189     public String toString() {
   1190         return "ActivityOptions(" + hashCode() + "), mPackageName=" + mPackageName
   1191                 + ", mAnimationType=" + mAnimationType + ", mStartX=" + mStartX + ", mStartY="
   1192                 + mStartY + ", mWidth=" + mWidth + ", mHeight=" + mHeight;
   1193     }
   1194 }
   1195