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      */
makeCustomAnimation(Context context, int enterResId, int exitResId)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      */
makeCustomAnimation(Context context, int enterResId, int exitResId, Handler handler, OnAnimationStartedListener listener)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      */
makeCustomInPlaceAnimation(Context context, int animId)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 
setOnAnimationStartedListener(final Handler handler, final OnAnimationStartedListener listener)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 {
onAnimationStarted()339         void onAnimationStarted();
340     }
341 
setOnAnimationFinishedListener(final Handler handler, final OnAnimationFinishedListener listener)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 {
onAnimationFinished()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      */
makeScaleUpAnimation(View source, int startX, int startY, int width, int height)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      */
makeClipRevealAnimation(View source, int startX, int startY, int width, int height)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      */
makeThumbnailScaleUpAnimation(View source, Bitmap thumbnail, int startX, int startY)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      */
makeThumbnailScaleUpAnimation(View source, Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener)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      */
makeThumbnailScaleDownAnimation(View source, Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener)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 
makeThumbnailAnimation(View source, Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener, boolean scaleUp)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      */
makeThumbnailAspectScaleUpAnimation(View source, Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight, Handler handler, OnAnimationStartedListener listener)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      */
makeThumbnailAspectScaleDownAnimation(View source, Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight, Handler handler, OnAnimationStartedListener listener)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 
makeAspectScaledThumbnailAnimation(View source, Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight, Handler handler, OnAnimationStartedListener listener, boolean scaleUp)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 */
makeThumbnailAspectScaleDownAnimation(View source, AppTransitionAnimationSpec[] specs, Handler handler, OnAnimationStartedListener onAnimationStartedListener, OnAnimationFinishedListener onAnimationFinishedListener)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      */
makeSceneTransitionAnimation(Activity activity, View sharedElement, String sharedElementName)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
makeSceneTransitionAnimation(Activity activity, Pair<View, String>... sharedElements)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 */
makeSceneTransitionAnimation(Activity activity, ExitTransitionCoordinator exitCoordinator, ArrayList<String> sharedElementNames, int resultCode, Intent resultData)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      */
makeTaskLaunchBehind()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      */
makeBasic()714     public static ActivityOptions makeBasic() {
715         final ActivityOptions opts = new ActivityOptions();
716         return opts;
717     }
718 
719     /** @hide */
getLaunchTaskBehind()720     public boolean getLaunchTaskBehind() {
721         return mAnimationType == ANIM_LAUNCH_TASK_BEHIND;
722     }
723 
ActivityOptions()724     private ActivityOptions() {
725     }
726 
727     /** @hide */
ActivityOptions(Bundle opts)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      */
setLaunchBounds(@ullable Rect screenSpacePixelRect)810     public ActivityOptions setLaunchBounds(@Nullable Rect screenSpacePixelRect) {
811         mLaunchBounds = screenSpacePixelRect != null ? new Rect(screenSpacePixelRect) : null;
812         return this;
813     }
814 
815     /** @hide */
getPackageName()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
getLaunchBounds()826     public Rect getLaunchBounds() {
827         return mLaunchBounds;
828     }
829 
830     /** @hide */
getAnimationType()831     public int getAnimationType() {
832         return mAnimationType;
833     }
834 
835     /** @hide */
getCustomEnterResId()836     public int getCustomEnterResId() {
837         return mCustomEnterResId;
838     }
839 
840     /** @hide */
getCustomExitResId()841     public int getCustomExitResId() {
842         return mCustomExitResId;
843     }
844 
845     /** @hide */
getCustomInPlaceResId()846     public int getCustomInPlaceResId() {
847         return mCustomInPlaceResId;
848     }
849 
850     /** @hide */
getThumbnail()851     public Bitmap getThumbnail() {
852         return mThumbnail;
853     }
854 
855     /** @hide */
getStartX()856     public int getStartX() {
857         return mStartX;
858     }
859 
860     /** @hide */
getStartY()861     public int getStartY() {
862         return mStartY;
863     }
864 
865     /** @hide */
getWidth()866     public int getWidth() {
867         return mWidth;
868     }
869 
870     /** @hide */
getHeight()871     public int getHeight() {
872         return mHeight;
873     }
874 
875     /** @hide */
getOnAnimationStartListener()876     public IRemoteCallback getOnAnimationStartListener() {
877         return mAnimationStartedListener;
878     }
879 
880     /** @hide */
getAnimationFinishedListener()881     public IRemoteCallback getAnimationFinishedListener() {
882         return mAnimationFinishedListener;
883     }
884 
885     /** @hide */
getExitCoordinatorKey()886     public int getExitCoordinatorKey() { return mExitCoordinatorIndex; }
887 
888     /** @hide */
abort()889     public void abort() {
890         if (mAnimationStartedListener != null) {
891             try {
892                 mAnimationStartedListener.sendResult(null);
893             } catch (RemoteException e) {
894             }
895         }
896     }
897 
898     /** @hide */
isReturning()899     public boolean isReturning() {
900         return mIsReturning;
901     }
902 
903     /** @hide */
getSharedElementNames()904     public ArrayList<String> getSharedElementNames() {
905         return mSharedElementNames;
906     }
907 
908     /** @hide */
getResultReceiver()909     public ResultReceiver getResultReceiver() { return mTransitionReceiver; }
910 
911     /** @hide */
getResultCode()912     public int getResultCode() { return mResultCode; }
913 
914     /** @hide */
getResultData()915     public Intent getResultData() { return mResultData; }
916 
917     /** @hide */
getUsageTimeReport()918     public PendingIntent getUsageTimeReport() {
919         return mUsageTimeReport;
920     }
921 
922     /** @hide */
getAnimSpecs()923     public AppTransitionAnimationSpec[] getAnimSpecs() { return mAnimSpecs; }
924 
925     /** @hide */
fromBundle(Bundle bOptions)926     public static ActivityOptions fromBundle(Bundle bOptions) {
927         return bOptions != null ? new ActivityOptions(bOptions) : null;
928     }
929 
930     /** @hide */
abort(ActivityOptions options)931     public static void abort(ActivityOptions options) {
932         if (options != null) {
933             options.abort();
934         }
935     }
936 
937     /** @hide */
getLaunchStackId()938     public int getLaunchStackId() {
939         return mLaunchStackId;
940     }
941 
942     /** @hide */
943     @TestApi
setLaunchStackId(int launchStackId)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      */
setLaunchTaskId(int taskId)952     public void setLaunchTaskId(int taskId) {
953         mLaunchTaskId = taskId;
954     }
955 
956     /**
957      * @hide
958      */
getLaunchTaskId()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      */
setTaskOverlay(boolean taskOverlay)969     public void setTaskOverlay(boolean taskOverlay) {
970         mTaskOverlay = taskOverlay;
971     }
972 
973     /**
974      * @hide
975      */
getTaskOverlay()976     public boolean getTaskOverlay() {
977         return mTaskOverlay;
978     }
979 
980     /** @hide */
getDockCreateMode()981     public int getDockCreateMode() {
982         return mDockCreateMode;
983     }
984 
985     /** @hide */
setDockCreateMode(int dockCreateMode)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      */
update(ActivityOptions otherOptions)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      */
toBundle()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      */
requestUsageTimeReport(PendingIntent receiver)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      */
forTargetActivity()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
toString()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