• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
20 import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
22 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
23 import static android.view.Display.INVALID_DISPLAY;
24 
25 import android.annotation.IntDef;
26 import android.annotation.NonNull;
27 import android.annotation.Nullable;
28 import android.annotation.RequiresPermission;
29 import android.annotation.TestApi;
30 import android.app.ExitTransitionCoordinator.ActivityExitTransitionCallbacks;
31 import android.app.ExitTransitionCoordinator.ExitTransitionCallbacks;
32 import android.compat.annotation.UnsupportedAppUsage;
33 import android.content.ComponentName;
34 import android.content.Context;
35 import android.content.Intent;
36 import android.graphics.Bitmap;
37 import android.graphics.Bitmap.Config;
38 import android.graphics.Rect;
39 import android.hardware.HardwareBuffer;
40 import android.os.Bundle;
41 import android.os.Handler;
42 import android.os.IBinder;
43 import android.os.IRemoteCallback;
44 import android.os.Parcel;
45 import android.os.Parcelable;
46 import android.os.RemoteException;
47 import android.os.ResultReceiver;
48 import android.os.UserHandle;
49 import android.transition.TransitionManager;
50 import android.util.Pair;
51 import android.util.Slog;
52 import android.view.AppTransitionAnimationSpec;
53 import android.view.IAppTransitionAnimationSpecsFuture;
54 import android.view.RemoteAnimationAdapter;
55 import android.view.View;
56 import android.view.ViewGroup;
57 import android.view.Window;
58 import android.window.IRemoteTransition;
59 import android.window.SplashScreen;
60 import android.window.WindowContainerToken;
61 
62 import java.lang.annotation.Retention;
63 import java.lang.annotation.RetentionPolicy;
64 import java.util.ArrayList;
65 
66 /**
67  * Helper class for building an options Bundle that can be used with
68  * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle)
69  * Context.startActivity(Intent, Bundle)} and related methods.
70  */
71 public class ActivityOptions {
72     private static final String TAG = "ActivityOptions";
73 
74     /**
75      * A long in the extras delivered by {@link #requestUsageTimeReport} that contains
76      * the total time (in ms) the user spent in the app flow.
77      */
78     public static final String EXTRA_USAGE_TIME_REPORT = "android.activity.usage_time";
79 
80     /**
81      * A Bundle in the extras delivered by {@link #requestUsageTimeReport} that contains
82      * detailed information about the time spent in each package associated with the app;
83      * each key is a package name, whose value is a long containing the time (in ms).
84      */
85     public static final String EXTRA_USAGE_TIME_REPORT_PACKAGES = "android.usage_time_packages";
86 
87     /**
88      * The package name that created the options.
89      * @hide
90      */
91     public static final String KEY_PACKAGE_NAME = "android:activity.packageName";
92 
93     /**
94      * The bounds (window size) that the activity should be launched in. Set to null explicitly for
95      * full screen. If the key is not found, previous bounds will be preserved.
96      * NOTE: This value is ignored on devices that don't have
97      * {@link android.content.pm.PackageManager#FEATURE_FREEFORM_WINDOW_MANAGEMENT} or
98      * {@link android.content.pm.PackageManager#FEATURE_PICTURE_IN_PICTURE} enabled.
99      * @hide
100      */
101     public static final String KEY_LAUNCH_BOUNDS = "android:activity.launchBounds";
102 
103     /**
104      * Type of animation that arguments specify.
105      * @hide
106      */
107     public static final String KEY_ANIM_TYPE = "android:activity.animType";
108 
109     /**
110      * Custom enter animation resource ID.
111      * @hide
112      */
113     public static final String KEY_ANIM_ENTER_RES_ID = "android:activity.animEnterRes";
114 
115     /**
116      * Custom exit animation resource ID.
117      * @hide
118      */
119     public static final String KEY_ANIM_EXIT_RES_ID = "android:activity.animExitRes";
120 
121     /**
122      * Custom in-place animation resource ID.
123      * @hide
124      */
125     public static final String KEY_ANIM_IN_PLACE_RES_ID = "android:activity.animInPlaceRes";
126 
127     /**
128      * Bitmap for thumbnail animation.
129      * @hide
130      */
131     public static final String KEY_ANIM_THUMBNAIL = "android:activity.animThumbnail";
132 
133     /**
134      * Start X position of thumbnail animation.
135      * @hide
136      */
137     public static final String KEY_ANIM_START_X = "android:activity.animStartX";
138 
139     /**
140      * Start Y position of thumbnail animation.
141      * @hide
142      */
143     public static final String KEY_ANIM_START_Y = "android:activity.animStartY";
144 
145     /**
146      * Initial width of the animation.
147      * @hide
148      */
149     public static final String KEY_ANIM_WIDTH = "android:activity.animWidth";
150 
151     /**
152      * Initial height of the animation.
153      * @hide
154      */
155     public static final String KEY_ANIM_HEIGHT = "android:activity.animHeight";
156 
157     /**
158      * Callback for when animation is started.
159      * @hide
160      */
161     public static final String KEY_ANIM_START_LISTENER = "android:activity.animStartListener";
162 
163     /**
164      * Specific a theme for a splash screen window.
165      * @hide
166      */
167     public static final String KEY_SPLASH_SCREEN_THEME = "android.activity.splashScreenTheme";
168 
169     /**
170      * Callback for when the last frame of the animation is played.
171      * @hide
172      */
173     private static final String KEY_ANIMATION_FINISHED_LISTENER =
174             "android:activity.animationFinishedListener";
175 
176     /**
177      * Descriptions of app transition animations to be played during the activity launch.
178      */
179     private static final String KEY_ANIM_SPECS = "android:activity.animSpecs";
180 
181     /**
182      * Whether the activity should be launched into LockTask mode.
183      * @see #setLockTaskEnabled(boolean)
184      */
185     private static final String KEY_LOCK_TASK_MODE = "android:activity.lockTaskMode";
186 
187     /**
188      * The display id the activity should be launched into.
189      * @see #setLaunchDisplayId(int)
190      * @hide
191      */
192     private static final String KEY_LAUNCH_DISPLAY_ID = "android.activity.launchDisplayId";
193 
194     /**
195      * The id of the display where the caller was on.
196      * @see #setCallerDisplayId(int)
197      * @hide
198      */
199     private static final String KEY_CALLER_DISPLAY_ID = "android.activity.callerDisplayId";
200 
201     /**
202      * The task display area token the activity should be launched into.
203      * @see #setLaunchTaskDisplayArea(WindowContainerToken)
204      * @hide
205      */
206     private static final String KEY_LAUNCH_TASK_DISPLAY_AREA_TOKEN =
207             "android.activity.launchTaskDisplayAreaToken";
208 
209     /**
210      * The root task token the activity should be launched into.
211      * @see #setLaunchRootTask(WindowContainerToken)
212      * @hide
213      */
214     public static final String KEY_LAUNCH_ROOT_TASK_TOKEN =
215             "android.activity.launchRootTaskToken";
216 
217     /**
218      * The windowing mode the activity should be launched into.
219      * @hide
220      */
221     private static final String KEY_LAUNCH_WINDOWING_MODE = "android.activity.windowingMode";
222 
223     /**
224      * The activity type the activity should be launched as.
225      * @hide
226      */
227     private static final String KEY_LAUNCH_ACTIVITY_TYPE = "android.activity.activityType";
228 
229     /**
230      * The task id the activity should be launched into.
231      * @hide
232      */
233     private static final String KEY_LAUNCH_TASK_ID = "android.activity.launchTaskId";
234 
235     /**
236      * See {@link #setPendingIntentLaunchFlags(int)}
237      * @hide
238      */
239     private static final String KEY_PENDING_INTENT_LAUNCH_FLAGS =
240             "android.activity.pendingIntentLaunchFlags";
241 
242     /**
243      * See {@link #setTaskAlwaysOnTop}.
244      * @hide
245      */
246     private static final String KEY_TASK_ALWAYS_ON_TOP = "android.activity.alwaysOnTop";
247 
248     /**
249      * See {@link #setTaskOverlay}.
250      * @hide
251      */
252     private static final String KEY_TASK_OVERLAY = "android.activity.taskOverlay";
253 
254     /**
255      * See {@link #setTaskOverlay}.
256      * @hide
257      */
258     private static final String KEY_TASK_OVERLAY_CAN_RESUME =
259             "android.activity.taskOverlayCanResume";
260 
261     /**
262      * See {@link #setAvoidMoveToFront()}.
263      * @hide
264      */
265     private static final String KEY_AVOID_MOVE_TO_FRONT = "android.activity.avoidMoveToFront";
266 
267     /**
268      * See {@link #setFreezeRecentTasksReordering()}.
269      * @hide
270      */
271     private static final String KEY_FREEZE_RECENT_TASKS_REORDERING =
272             "android.activity.freezeRecentTasksReordering";
273 
274     /**
275      * Determines whether to disallow the outgoing activity from entering picture-in-picture as the
276      * result of a new activity being launched.
277      * @hide
278      */
279     private static final String KEY_DISALLOW_ENTER_PICTURE_IN_PICTURE_WHILE_LAUNCHING =
280             "android:activity.disallowEnterPictureInPictureWhileLaunching";
281 
282     /**
283      * Indicates flags should be applied to the launching activity such that it will behave
284      * correctly in a bubble.
285      * @hide
286      */
287     private static final String KEY_APPLY_ACTIVITY_FLAGS_FOR_BUBBLES =
288             "android:activity.applyActivityFlagsForBubbles";
289 
290     /**
291      * For Activity transitions, the calling Activity's TransitionListener used to
292      * notify the called Activity when the shared element and the exit transitions
293      * complete.
294      */
295     private static final String KEY_TRANSITION_COMPLETE_LISTENER
296             = "android:activity.transitionCompleteListener";
297 
298     private static final String KEY_TRANSITION_IS_RETURNING
299             = "android:activity.transitionIsReturning";
300     private static final String KEY_TRANSITION_SHARED_ELEMENTS
301             = "android:activity.sharedElementNames";
302     private static final String KEY_RESULT_DATA = "android:activity.resultData";
303     private static final String KEY_RESULT_CODE = "android:activity.resultCode";
304     private static final String KEY_EXIT_COORDINATOR_INDEX
305             = "android:activity.exitCoordinatorIndex";
306 
307     /** See {@link SourceInfo}. */
308     private static final String KEY_SOURCE_INFO = "android.activity.sourceInfo";
309 
310     private static final String KEY_USAGE_TIME_REPORT = "android:activity.usageTimeReport";
311     private static final String KEY_ROTATION_ANIMATION_HINT = "android:activity.rotationAnimationHint";
312 
313     private static final String KEY_INSTANT_APP_VERIFICATION_BUNDLE
314             = "android:instantapps.installerbundle";
315     private static final String KEY_SPECS_FUTURE = "android:activity.specsFuture";
316     private static final String KEY_REMOTE_ANIMATION_ADAPTER
317             = "android:activity.remoteAnimationAdapter";
318     private static final String KEY_REMOTE_TRANSITION =
319             "android:activity.remoteTransition";
320 
321     private static final String KEY_OVERRIDE_TASK_TRANSITION =
322             "android:activity.overrideTaskTransition";
323 
324     /** See {@link #setRemoveWithTaskOrganizer(boolean)}. */
325     private static final String KEY_REMOVE_WITH_TASK_ORGANIZER =
326             "android.activity.removeWithTaskOrganizer";
327     /** See {@link #setLaunchedFromBubble(boolean)}. */
328     private static final String KEY_LAUNCHED_FROM_BUBBLE =
329             "android.activity.launchTypeBubble";
330 
331     /** See {@link #setSplashscreenStyle(int)}. */
332     private static final String KEY_SPLASH_SCREEN_STYLE =
333             "android.activity.splashScreenStyle";
334 
335     /** See {@link #setTransientLaunch()}. */
336     private static final String KEY_TRANSIENT_LAUNCH = "android.activity.transientLaunch";
337 
338     /**
339      * @see #setLaunchCookie
340      * @hide
341      */
342     public static final String KEY_LAUNCH_COOKIE = "android.activity.launchCookie";
343 
344     /** @hide */
345     public static final int ANIM_UNDEFINED = -1;
346     /** @hide */
347     public static final int ANIM_NONE = 0;
348     /** @hide */
349     public static final int ANIM_CUSTOM = 1;
350     /** @hide */
351     public static final int ANIM_SCALE_UP = 2;
352     /** @hide */
353     public static final int ANIM_THUMBNAIL_SCALE_UP = 3;
354     /** @hide */
355     public static final int ANIM_THUMBNAIL_SCALE_DOWN = 4;
356     /** @hide */
357     public static final int ANIM_SCENE_TRANSITION = 5;
358     /** @hide */
359     public static final int ANIM_DEFAULT = 6;
360     /** @hide */
361     public static final int ANIM_LAUNCH_TASK_BEHIND = 7;
362     /** @hide */
363     public static final int ANIM_THUMBNAIL_ASPECT_SCALE_UP = 8;
364     /** @hide */
365     public static final int ANIM_THUMBNAIL_ASPECT_SCALE_DOWN = 9;
366     /** @hide */
367     public static final int ANIM_CUSTOM_IN_PLACE = 10;
368     /** @hide */
369     public static final int ANIM_CLIP_REVEAL = 11;
370     /** @hide */
371     public static final int ANIM_OPEN_CROSS_PROFILE_APPS = 12;
372     /** @hide */
373     public static final int ANIM_REMOTE_ANIMATION = 13;
374 
375     private String mPackageName;
376     private Rect mLaunchBounds;
377     private int mAnimationType = ANIM_UNDEFINED;
378     private int mCustomEnterResId;
379     private int mCustomExitResId;
380     private int mCustomInPlaceResId;
381     private Bitmap mThumbnail;
382     private int mStartX;
383     private int mStartY;
384     private int mWidth;
385     private int mHeight;
386     private IRemoteCallback mAnimationStartedListener;
387     private IRemoteCallback mAnimationFinishedListener;
388     private ResultReceiver mTransitionReceiver;
389     private boolean mIsReturning;
390     private ArrayList<String> mSharedElementNames;
391     private Intent mResultData;
392     private int mResultCode;
393     private int mExitCoordinatorIndex;
394     private PendingIntent mUsageTimeReport;
395     private int mLaunchDisplayId = INVALID_DISPLAY;
396     private int mCallerDisplayId = INVALID_DISPLAY;
397     private WindowContainerToken mLaunchTaskDisplayArea;
398     private WindowContainerToken mLaunchRootTask;
399     @WindowConfiguration.WindowingMode
400     private int mLaunchWindowingMode = WINDOWING_MODE_UNDEFINED;
401     @WindowConfiguration.ActivityType
402     private int mLaunchActivityType = ACTIVITY_TYPE_UNDEFINED;
403     private int mLaunchTaskId = -1;
404     private int mPendingIntentLaunchFlags;
405     private boolean mLockTaskMode = false;
406     private boolean mDisallowEnterPictureInPictureWhileLaunching;
407     private boolean mApplyActivityFlagsForBubbles;
408     private boolean mTaskAlwaysOnTop;
409     private boolean mTaskOverlay;
410     private boolean mTaskOverlayCanResume;
411     private boolean mAvoidMoveToFront;
412     private boolean mFreezeRecentTasksReordering;
413     private AppTransitionAnimationSpec mAnimSpecs[];
414     private SourceInfo mSourceInfo;
415     private int mRotationAnimationHint = -1;
416     private Bundle mAppVerificationBundle;
417     private IAppTransitionAnimationSpecsFuture mSpecsFuture;
418     private RemoteAnimationAdapter mRemoteAnimationAdapter;
419     private IBinder mLaunchCookie;
420     private IRemoteTransition mRemoteTransition;
421     private boolean mOverrideTaskTransition;
422     private String mSplashScreenThemeResName;
423     @SplashScreen.SplashScreenStyle
424     private int mSplashScreenStyle;
425     private boolean mRemoveWithTaskOrganizer;
426     private boolean mLaunchedFromBubble;
427     private boolean mTransientLaunch;
428 
429     /**
430      * Create an ActivityOptions specifying a custom animation to run when
431      * the activity is displayed.
432      *
433      * @param context Who is defining this.  This is the application that the
434      * animation resources will be loaded from.
435      * @param enterResId A resource ID of the animation resource to use for
436      * the incoming activity.  Use 0 for no animation.
437      * @param exitResId A resource ID of the animation resource to use for
438      * the outgoing activity.  Use 0 for no animation.
439      * @return Returns a new ActivityOptions object that you can use to
440      * supply these options as the options Bundle when starting an activity.
441      */
makeCustomAnimation(Context context, int enterResId, int exitResId)442     public static ActivityOptions makeCustomAnimation(Context context,
443             int enterResId, int exitResId) {
444         return makeCustomAnimation(context, enterResId, exitResId, null, null, null);
445     }
446 
447     /**
448      * Create an ActivityOptions specifying a custom animation to run when
449      * the activity is displayed.
450      *
451      * @param context Who is defining this.  This is the application that the
452      * animation resources will be loaded from.
453      * @param enterResId A resource ID of the animation resource to use for
454      * the incoming activity.  Use 0 for no animation.
455      * @param exitResId A resource ID of the animation resource to use for
456      * the outgoing activity.  Use 0 for no animation.
457      * @param handler If <var>listener</var> is non-null this must be a valid
458      * Handler on which to dispatch the callback; otherwise it should be null.
459      * @param listener Optional OnAnimationStartedListener to find out when the
460      * requested animation has started running.  If for some reason the animation
461      * is not executed, the callback will happen immediately.
462      * @return Returns a new ActivityOptions object that you can use to
463      * supply these options as the options Bundle when starting an activity.
464      * @hide
465      */
466     @UnsupportedAppUsage
makeCustomAnimation(Context context, int enterResId, int exitResId, Handler handler, OnAnimationStartedListener listener)467     public static ActivityOptions makeCustomAnimation(Context context,
468             int enterResId, int exitResId, Handler handler, OnAnimationStartedListener listener) {
469         ActivityOptions opts = new ActivityOptions();
470         opts.mPackageName = context.getPackageName();
471         opts.mAnimationType = ANIM_CUSTOM;
472         opts.mCustomEnterResId = enterResId;
473         opts.mCustomExitResId = exitResId;
474         opts.setOnAnimationStartedListener(handler, listener);
475         return opts;
476     }
477 
478     /**
479      * Create an ActivityOptions specifying a custom animation to run when
480      * the activity is displayed.
481      *
482      * @param context Who is defining this.  This is the application that the
483      * animation resources will be loaded from.
484      * @param enterResId A resource ID of the animation resource to use for
485      * the incoming activity.  Use 0 for no animation.
486      * @param exitResId A resource ID of the animation resource to use for
487      * the outgoing activity.  Use 0 for no animation.
488      * @param handler If <var>listener</var> is non-null this must be a valid
489      * Handler on which to dispatch the callback; otherwise it should be null.
490      * @param startedListener Optional OnAnimationStartedListener to find out when the
491      * requested animation has started running.  If for some reason the animation
492      * is not executed, the callback will happen immediately.
493      * @param finishedListener Optional OnAnimationFinishedListener when the animation
494      * has finished running.
495      * @return Returns a new ActivityOptions object that you can use to
496      * supply these options as the options Bundle when starting an activity.
497      * @hide
498      */
499     @TestApi
makeCustomAnimation(@onNull Context context, int enterResId, int exitResId, @Nullable Handler handler, @Nullable OnAnimationStartedListener startedListener, @Nullable OnAnimationFinishedListener finishedListener)500     public static @NonNull ActivityOptions makeCustomAnimation(@NonNull Context context,
501             int enterResId, int exitResId, @Nullable Handler handler,
502             @Nullable OnAnimationStartedListener startedListener,
503             @Nullable OnAnimationFinishedListener finishedListener) {
504         ActivityOptions opts = makeCustomAnimation(context, enterResId, exitResId, handler,
505                 startedListener);
506         opts.setOnAnimationFinishedListener(handler, finishedListener);
507         return opts;
508     }
509 
510     /**
511      * Create an ActivityOptions specifying a custom animation to run when the activity in the
512      * different task is displayed.
513      *
514      * @param context Who is defining this.  This is the application that the
515      * animation resources will be loaded from.
516      * @param enterResId A resource ID of the animation resource to use for
517      * the incoming activity.  Use 0 for no animation.
518      * @param exitResId A resource ID of the animation resource to use for
519      * the outgoing activity.  Use 0 for no animation.
520      * @param handler If <var>listener</var> is non-null this must be a valid
521      * Handler on which to dispatch the callback; otherwise it should be null.
522      * @param startedListener Optional OnAnimationStartedListener to find out when the
523      * requested animation has started running.  If for some reason the animation
524      * is not executed, the callback will happen immediately.
525      * @param finishedListener Optional OnAnimationFinishedListener when the animation
526      * has finished running.
527      *
528      * @return Returns a new ActivityOptions object that you can use to
529      * supply these options as the options Bundle when starting an activity.
530      * @hide
531      */
532     @RequiresPermission(START_TASKS_FROM_RECENTS)
533     @TestApi
makeCustomTaskAnimation(@onNull Context context, int enterResId, int exitResId, @Nullable Handler handler, @Nullable OnAnimationStartedListener startedListener, @Nullable OnAnimationFinishedListener finishedListener)534     public static @NonNull ActivityOptions makeCustomTaskAnimation(@NonNull Context context,
535             int enterResId, int exitResId, @Nullable Handler handler,
536             @Nullable OnAnimationStartedListener startedListener,
537             @Nullable OnAnimationFinishedListener finishedListener) {
538         ActivityOptions opts = makeCustomAnimation(context, enterResId, exitResId, handler,
539                 startedListener, finishedListener);
540         opts.mOverrideTaskTransition = true;
541         return opts;
542     }
543 
544     /**
545      * Creates an ActivityOptions specifying a custom animation to run in place on an existing
546      * activity.
547      *
548      * @param context Who is defining this.  This is the application that the
549      * animation resources will be loaded from.
550      * @param animId A resource ID of the animation resource to use for
551      * the incoming activity.
552      * @return Returns a new ActivityOptions object that you can use to
553      * supply these options as the options Bundle when running an in-place animation.
554      * @hide
555      */
makeCustomInPlaceAnimation(Context context, int animId)556     public static ActivityOptions makeCustomInPlaceAnimation(Context context, int animId) {
557         if (animId == 0) {
558             throw new RuntimeException("You must specify a valid animation.");
559         }
560 
561         ActivityOptions opts = new ActivityOptions();
562         opts.mPackageName = context.getPackageName();
563         opts.mAnimationType = ANIM_CUSTOM_IN_PLACE;
564         opts.mCustomInPlaceResId = animId;
565         return opts;
566     }
567 
setOnAnimationStartedListener(final Handler handler, final OnAnimationStartedListener listener)568     private void setOnAnimationStartedListener(final Handler handler,
569             final OnAnimationStartedListener listener) {
570         if (listener != null) {
571             mAnimationStartedListener = new IRemoteCallback.Stub() {
572                 @Override
573                 public void sendResult(Bundle data) throws RemoteException {
574                     handler.post(new Runnable() {
575                         @Override public void run() {
576                             listener.onAnimationStarted();
577                         }
578                     });
579                 }
580             };
581         }
582     }
583 
584     /**
585      * Callback for use with {@link ActivityOptions#makeThumbnailScaleUpAnimation}
586      * to find out when the given animation has started running.
587      * @hide
588      */
589     @TestApi
590     public interface OnAnimationStartedListener {
onAnimationStarted()591         void onAnimationStarted();
592     }
593 
setOnAnimationFinishedListener(final Handler handler, final OnAnimationFinishedListener listener)594     private void setOnAnimationFinishedListener(final Handler handler,
595             final OnAnimationFinishedListener listener) {
596         if (listener != null) {
597             mAnimationFinishedListener = new IRemoteCallback.Stub() {
598                 @Override
599                 public void sendResult(Bundle data) throws RemoteException {
600                     handler.post(new Runnable() {
601                         @Override
602                         public void run() {
603                             listener.onAnimationFinished();
604                         }
605                     });
606                 }
607             };
608         }
609     }
610 
611     /**
612      * Callback for use with {@link ActivityOptions#makeThumbnailAspectScaleDownAnimation}
613      * to find out when the given animation has drawn its last frame.
614      * @hide
615      */
616     @TestApi
617     public interface OnAnimationFinishedListener {
onAnimationFinished()618         void onAnimationFinished();
619     }
620 
621     /**
622      * Create an ActivityOptions specifying an animation where the new
623      * activity is scaled from a small originating area of the screen to
624      * its final full representation.
625      *
626      * <p>If the Intent this is being used with has not set its
627      * {@link android.content.Intent#setSourceBounds Intent.setSourceBounds},
628      * those bounds will be filled in for you based on the initial
629      * bounds passed in here.
630      *
631      * @param source The View that the new activity is animating from.  This
632      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
633      * @param startX The x starting location of the new activity, relative to <var>source</var>.
634      * @param startY The y starting location of the activity, relative to <var>source</var>.
635      * @param width The initial width of the new activity.
636      * @param height The initial height of the new activity.
637      * @return Returns a new ActivityOptions object that you can use to
638      * supply these options as the options Bundle when starting an activity.
639      */
makeScaleUpAnimation(View source, int startX, int startY, int width, int height)640     public static ActivityOptions makeScaleUpAnimation(View source,
641             int startX, int startY, int width, int height) {
642         ActivityOptions opts = new ActivityOptions();
643         opts.mPackageName = source.getContext().getPackageName();
644         opts.mAnimationType = ANIM_SCALE_UP;
645         int[] pts = new int[2];
646         source.getLocationOnScreen(pts);
647         opts.mStartX = pts[0] + startX;
648         opts.mStartY = pts[1] + startY;
649         opts.mWidth = width;
650         opts.mHeight = height;
651         return opts;
652     }
653 
654     /**
655      * Create an ActivityOptions specifying an animation where the new
656      * activity is revealed from a small originating area of the screen to
657      * its final full representation.
658      *
659      * @param source The View that the new activity is animating from.  This
660      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
661      * @param startX The x starting location of the new activity, relative to <var>source</var>.
662      * @param startY The y starting location of the activity, relative to <var>source</var>.
663      * @param width The initial width of the new activity.
664      * @param height The initial height of the new activity.
665      * @return Returns a new ActivityOptions object that you can use to
666      * supply these options as the options Bundle when starting an activity.
667      */
makeClipRevealAnimation(View source, int startX, int startY, int width, int height)668     public static ActivityOptions makeClipRevealAnimation(View source,
669             int startX, int startY, int width, int height) {
670         ActivityOptions opts = new ActivityOptions();
671         opts.mAnimationType = ANIM_CLIP_REVEAL;
672         int[] pts = new int[2];
673         source.getLocationOnScreen(pts);
674         opts.mStartX = pts[0] + startX;
675         opts.mStartY = pts[1] + startY;
676         opts.mWidth = width;
677         opts.mHeight = height;
678         return opts;
679     }
680 
681     /**
682      * Creates an {@link ActivityOptions} object specifying an animation where the new activity
683      * is started in another user profile by calling {@link
684      * android.content.pm.crossprofile.CrossProfileApps#startMainActivity(ComponentName, UserHandle)
685      * }.
686      * @hide
687      */
makeOpenCrossProfileAppsAnimation()688     public static ActivityOptions makeOpenCrossProfileAppsAnimation() {
689         ActivityOptions options = new ActivityOptions();
690         options.mAnimationType = ANIM_OPEN_CROSS_PROFILE_APPS;
691         return options;
692     }
693 
694     /**
695      * Create an ActivityOptions specifying an animation where a thumbnail
696      * is scaled from a given position to the new activity window that is
697      * being started.
698      *
699      * <p>If the Intent this is being used with has not set its
700      * {@link android.content.Intent#setSourceBounds Intent.setSourceBounds},
701      * those bounds will be filled in for you based on the initial
702      * thumbnail location and size provided here.
703      *
704      * @param source The View that this thumbnail is animating from.  This
705      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
706      * @param thumbnail The bitmap that will be shown as the initial thumbnail
707      * of the animation.
708      * @param startX The x starting location of the bitmap, relative to <var>source</var>.
709      * @param startY The y starting location of the bitmap, relative to <var>source</var>.
710      * @return Returns a new ActivityOptions object that you can use to
711      * supply these options as the options Bundle when starting an activity.
712      */
makeThumbnailScaleUpAnimation(View source, Bitmap thumbnail, int startX, int startY)713     public static ActivityOptions makeThumbnailScaleUpAnimation(View source,
714             Bitmap thumbnail, int startX, int startY) {
715         return makeThumbnailScaleUpAnimation(source, thumbnail, startX, startY, null);
716     }
717 
718     /**
719      * Create an ActivityOptions specifying an animation where a thumbnail
720      * is scaled from a given position to the new activity window that is
721      * being started.
722      *
723      * @param source The View that this thumbnail is animating from.  This
724      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
725      * @param thumbnail The bitmap that will be shown as the initial thumbnail
726      * of the animation.
727      * @param startX The x starting location of the bitmap, relative to <var>source</var>.
728      * @param startY The y starting location of the bitmap, relative to <var>source</var>.
729      * @param listener Optional OnAnimationStartedListener to find out when the
730      * requested animation has started running.  If for some reason the animation
731      * is not executed, the callback will happen immediately.
732      * @return Returns a new ActivityOptions object that you can use to
733      * supply these options as the options Bundle when starting an activity.
734      */
makeThumbnailScaleUpAnimation(View source, Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener)735     private static ActivityOptions makeThumbnailScaleUpAnimation(View source,
736             Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
737         return makeThumbnailAnimation(source, thumbnail, startX, startY, listener, true);
738     }
739 
makeThumbnailAnimation(View source, Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener, boolean scaleUp)740     private static ActivityOptions makeThumbnailAnimation(View source,
741             Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener,
742             boolean scaleUp) {
743         ActivityOptions opts = new ActivityOptions();
744         opts.mPackageName = source.getContext().getPackageName();
745         opts.mAnimationType = scaleUp ? ANIM_THUMBNAIL_SCALE_UP : ANIM_THUMBNAIL_SCALE_DOWN;
746         opts.mThumbnail = thumbnail;
747         int[] pts = new int[2];
748         source.getLocationOnScreen(pts);
749         opts.mStartX = pts[0] + startX;
750         opts.mStartY = pts[1] + startY;
751         opts.setOnAnimationStartedListener(source.getHandler(), listener);
752         return opts;
753     }
754 
755     /**
756      * Create an ActivityOptions specifying an animation where a list of activity windows and
757      * thumbnails are aspect scaled to/from a new location.
758      * @hide
759      */
760     @UnsupportedAppUsage
makeMultiThumbFutureAspectScaleAnimation(Context context, Handler handler, IAppTransitionAnimationSpecsFuture specsFuture, OnAnimationStartedListener listener, boolean scaleUp)761     public static ActivityOptions makeMultiThumbFutureAspectScaleAnimation(Context context,
762             Handler handler, IAppTransitionAnimationSpecsFuture specsFuture,
763             OnAnimationStartedListener listener, boolean scaleUp) {
764         ActivityOptions opts = new ActivityOptions();
765         opts.mPackageName = context.getPackageName();
766         opts.mAnimationType = scaleUp
767                 ? ANIM_THUMBNAIL_ASPECT_SCALE_UP
768                 : ANIM_THUMBNAIL_ASPECT_SCALE_DOWN;
769         opts.mSpecsFuture = specsFuture;
770         opts.setOnAnimationStartedListener(handler, listener);
771         return opts;
772     }
773 
774     /**
775      * Create an ActivityOptions specifying an animation where the new activity
776      * window and a thumbnail is aspect-scaled to a new location.
777      *
778      * @param source The View that this thumbnail is animating to.  This
779      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
780      * @param thumbnail The bitmap that will be shown as the final thumbnail
781      * of the animation.
782      * @param startX The x end location of the bitmap, relative to <var>source</var>.
783      * @param startY The y end location of the bitmap, relative to <var>source</var>.
784      * @param handler If <var>listener</var> is non-null this must be a valid
785      * Handler on which to dispatch the callback; otherwise it should be null.
786      * @param listener Optional OnAnimationStartedListener to find out when the
787      * requested animation has started running.  If for some reason the animation
788      * is not executed, the callback will happen immediately.
789      * @return Returns a new ActivityOptions object that you can use to
790      * supply these options as the options Bundle when starting an activity.
791      * @hide
792      */
makeThumbnailAspectScaleDownAnimation(View source, Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight, Handler handler, OnAnimationStartedListener listener)793     public static ActivityOptions makeThumbnailAspectScaleDownAnimation(View source,
794             Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight,
795             Handler handler, OnAnimationStartedListener listener) {
796         return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY,
797                 targetWidth, targetHeight, handler, listener, false);
798     }
799 
makeAspectScaledThumbnailAnimation(View source, Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight, Handler handler, OnAnimationStartedListener listener, boolean scaleUp)800     private static ActivityOptions makeAspectScaledThumbnailAnimation(View source, Bitmap thumbnail,
801             int startX, int startY, int targetWidth, int targetHeight,
802             Handler handler, OnAnimationStartedListener listener, boolean scaleUp) {
803         ActivityOptions opts = new ActivityOptions();
804         opts.mPackageName = source.getContext().getPackageName();
805         opts.mAnimationType = scaleUp ? ANIM_THUMBNAIL_ASPECT_SCALE_UP :
806                 ANIM_THUMBNAIL_ASPECT_SCALE_DOWN;
807         opts.mThumbnail = thumbnail;
808         int[] pts = new int[2];
809         source.getLocationOnScreen(pts);
810         opts.mStartX = pts[0] + startX;
811         opts.mStartY = pts[1] + startY;
812         opts.mWidth = targetWidth;
813         opts.mHeight = targetHeight;
814         opts.setOnAnimationStartedListener(handler, listener);
815         return opts;
816     }
817 
818     /** @hide */
makeThumbnailAspectScaleDownAnimation(View source, AppTransitionAnimationSpec[] specs, Handler handler, OnAnimationStartedListener onAnimationStartedListener, OnAnimationFinishedListener onAnimationFinishedListener)819     public static ActivityOptions makeThumbnailAspectScaleDownAnimation(View source,
820             AppTransitionAnimationSpec[] specs, Handler handler,
821             OnAnimationStartedListener onAnimationStartedListener,
822             OnAnimationFinishedListener onAnimationFinishedListener) {
823         ActivityOptions opts = new ActivityOptions();
824         opts.mPackageName = source.getContext().getPackageName();
825         opts.mAnimationType = ANIM_THUMBNAIL_ASPECT_SCALE_DOWN;
826         opts.mAnimSpecs = specs;
827         opts.setOnAnimationStartedListener(handler, onAnimationStartedListener);
828         opts.setOnAnimationFinishedListener(handler, onAnimationFinishedListener);
829         return opts;
830     }
831 
832     /**
833      * Create an ActivityOptions to transition between Activities using cross-Activity scene
834      * animations. This method carries the position of one shared element to the started Activity.
835      * The position of <code>sharedElement</code> will be used as the epicenter for the
836      * exit Transition. The position of the shared element in the launched Activity will be the
837      * epicenter of its entering Transition.
838      *
839      * <p>This requires {@link android.view.Window#FEATURE_ACTIVITY_TRANSITIONS} to be
840      * enabled on the calling Activity to cause an exit transition. The same must be in
841      * the called Activity to get an entering transition.</p>
842      * @param activity The Activity whose window contains the shared elements.
843      * @param sharedElement The View to transition to the started Activity.
844      * @param sharedElementName The shared element name as used in the target Activity. This
845      *                          must not be null.
846      * @return Returns a new ActivityOptions object that you can use to
847      *         supply these options as the options Bundle when starting an activity.
848      * @see android.transition.Transition#setEpicenterCallback(
849      *          android.transition.Transition.EpicenterCallback)
850      */
makeSceneTransitionAnimation(Activity activity, View sharedElement, String sharedElementName)851     public static ActivityOptions makeSceneTransitionAnimation(Activity activity,
852             View sharedElement, String sharedElementName) {
853         return makeSceneTransitionAnimation(activity, Pair.create(sharedElement, sharedElementName));
854     }
855 
856     /**
857      * Create an ActivityOptions to transition between Activities using cross-Activity scene
858      * animations. This method carries the position of multiple shared elements to the started
859      * Activity. The position of the first element in sharedElements
860      * will be used as the epicenter for the exit Transition. The position of the associated
861      * shared element in the launched Activity will be the epicenter of its entering Transition.
862      *
863      * <p>This requires {@link android.view.Window#FEATURE_ACTIVITY_TRANSITIONS} to be
864      * enabled on the calling Activity to cause an exit transition. The same must be in
865      * the called Activity to get an entering transition.</p>
866      * @param activity The Activity whose window contains the shared elements.
867      * @param sharedElements The names of the shared elements to transfer to the called
868      *                       Activity and their associated Views. The Views must each have
869      *                       a unique shared element name.
870      * @return Returns a new ActivityOptions object that you can use to
871      *         supply these options as the options Bundle when starting an activity.
872      * @see android.transition.Transition#setEpicenterCallback(
873      *          android.transition.Transition.EpicenterCallback)
874      */
875     @SafeVarargs
makeSceneTransitionAnimation(Activity activity, Pair<View, String>... sharedElements)876     public static ActivityOptions makeSceneTransitionAnimation(Activity activity,
877             Pair<View, String>... sharedElements) {
878         ActivityOptions opts = new ActivityOptions();
879         ExitTransitionCoordinator exit = makeSceneTransitionAnimation(
880                 new ActivityExitTransitionCallbacks(activity), activity.mExitTransitionListener,
881                 activity.getWindow(), opts, sharedElements);
882         opts.mExitCoordinatorIndex =
883                 activity.mActivityTransitionState.addExitTransitionCoordinator(exit);
884         return opts;
885     }
886 
887     /**
888      * Call this immediately prior to startActivity to begin a shared element transition
889      * from a non-Activity. The window must support Window.FEATURE_ACTIVITY_TRANSITIONS.
890      * The exit transition will start immediately and the shared element transition will
891      * start once the launched Activity's shared element is ready.
892      * <p>
893      * When all transitions have completed and the shared element has been transfered,
894      * the window's decor View will have its visibility set to View.GONE.
895      *
896      * @hide
897      */
898     @SafeVarargs
startSharedElementAnimation( Window window, ExitTransitionCallbacks exitCallbacks, SharedElementCallback callback, Pair<View, String>... sharedElements)899     public static Pair<ActivityOptions, ExitTransitionCoordinator> startSharedElementAnimation(
900             Window window, ExitTransitionCallbacks exitCallbacks, SharedElementCallback callback,
901             Pair<View, String>... sharedElements) {
902         ActivityOptions opts = new ActivityOptions();
903         ExitTransitionCoordinator exit = makeSceneTransitionAnimation(
904                 exitCallbacks, callback, window, opts, sharedElements);
905         opts.mExitCoordinatorIndex = -1;
906         return Pair.create(opts, exit);
907     }
908 
909     /**
910      * This method should be called when the
911      * {@link #startSharedElementAnimation(Window, ExitTransitionCallbacks, Pair[])}
912      * animation must be stopped and the Views reset. This can happen if there was an error
913      * from startActivity or a springboard activity and the animation should stop and reset.
914      *
915      * @hide
916      */
stopSharedElementAnimation(Window window)917     public static void stopSharedElementAnimation(Window window) {
918         final View decorView = window.getDecorView();
919         if (decorView == null) {
920             return;
921         }
922         final ExitTransitionCoordinator exit = (ExitTransitionCoordinator)
923                 decorView.getTag(com.android.internal.R.id.cross_task_transition);
924         if (exit != null) {
925             exit.cancelPendingTransitions();
926             decorView.setTagInternal(com.android.internal.R.id.cross_task_transition, null);
927             TransitionManager.endTransitions((ViewGroup) decorView);
928             exit.resetViews();
929             exit.clearState();
930             decorView.setVisibility(View.VISIBLE);
931         }
932     }
933 
makeSceneTransitionAnimation( ExitTransitionCallbacks exitCallbacks, SharedElementCallback callback, Window window, ActivityOptions opts, Pair<View, String>[] sharedElements)934     static ExitTransitionCoordinator makeSceneTransitionAnimation(
935             ExitTransitionCallbacks exitCallbacks, SharedElementCallback callback, Window window,
936             ActivityOptions opts, Pair<View, String>[] sharedElements) {
937         if (!window.hasFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)) {
938             opts.mAnimationType = ANIM_DEFAULT;
939             return null;
940         }
941         opts.mAnimationType = ANIM_SCENE_TRANSITION;
942 
943         ArrayList<String> names = new ArrayList<String>();
944         ArrayList<View> views = new ArrayList<View>();
945 
946         if (sharedElements != null) {
947             for (int i = 0; i < sharedElements.length; i++) {
948                 Pair<View, String> sharedElement = sharedElements[i];
949                 String sharedElementName = sharedElement.second;
950                 if (sharedElementName == null) {
951                     throw new IllegalArgumentException("Shared element name must not be null");
952                 }
953                 names.add(sharedElementName);
954                 View view = sharedElement.first;
955                 if (view == null) {
956                     throw new IllegalArgumentException("Shared element must not be null");
957                 }
958                 views.add(sharedElement.first);
959             }
960         }
961 
962         ExitTransitionCoordinator exit = new ExitTransitionCoordinator(exitCallbacks, window,
963                 callback, names, names, views, false);
964         opts.mTransitionReceiver = exit;
965         opts.mSharedElementNames = names;
966         opts.mIsReturning = false;
967         return exit;
968     }
969 
970     /**
971      * Needed for virtual devices because they can be slow enough that the 1 second timeout
972      * triggers when it doesn't on normal devices.
973      *
974      * @hide
975      */
976     @TestApi
setExitTransitionTimeout(long timeoutMillis)977     public static void setExitTransitionTimeout(long timeoutMillis) {
978         ExitTransitionCoordinator.sMaxWaitMillis = timeoutMillis;
979     }
980 
981     /** @hide */
makeSceneTransitionAnimation(Activity activity, ExitTransitionCoordinator exitCoordinator, ArrayList<String> sharedElementNames, int resultCode, Intent resultData)982     static ActivityOptions makeSceneTransitionAnimation(Activity activity,
983             ExitTransitionCoordinator exitCoordinator, ArrayList<String> sharedElementNames,
984             int resultCode, Intent resultData) {
985         ActivityOptions opts = new ActivityOptions();
986         opts.mAnimationType = ANIM_SCENE_TRANSITION;
987         opts.mSharedElementNames = sharedElementNames;
988         opts.mTransitionReceiver = exitCoordinator;
989         opts.mIsReturning = true;
990         opts.mResultCode = resultCode;
991         opts.mResultData = resultData;
992         if (activity == null) {
993             opts.mExitCoordinatorIndex = -1;
994         } else {
995             opts.mExitCoordinatorIndex =
996                     activity.mActivityTransitionState.addExitTransitionCoordinator(exitCoordinator);
997         }
998         return opts;
999     }
1000 
1001     /**
1002      * If set along with Intent.FLAG_ACTIVITY_NEW_DOCUMENT then the task being launched will not be
1003      * presented to the user but will instead be only available through the recents task list.
1004      * In addition, the new task wil be affiliated with the launching activity's task.
1005      * Affiliated tasks are grouped together in the recents task list.
1006      *
1007      * <p>This behavior is not supported for activities with {@link
1008      * android.R.styleable#AndroidManifestActivity_launchMode launchMode} values of
1009      * <code>singleInstance</code> or <code>singleTask</code>.
1010      */
makeTaskLaunchBehind()1011     public static ActivityOptions makeTaskLaunchBehind() {
1012         final ActivityOptions opts = new ActivityOptions();
1013         opts.mAnimationType = ANIM_LAUNCH_TASK_BEHIND;
1014         return opts;
1015     }
1016 
1017     /**
1018      * Create a basic ActivityOptions that has no special animation associated with it.
1019      * Other options can still be set.
1020      */
makeBasic()1021     public static ActivityOptions makeBasic() {
1022         final ActivityOptions opts = new ActivityOptions();
1023         return opts;
1024     }
1025 
1026     /**
1027      * Create an {@link ActivityOptions} instance that lets the application control the entire
1028      * animation using a {@link RemoteAnimationAdapter}.
1029      * @hide
1030      */
1031     @RequiresPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS)
1032     @UnsupportedAppUsage
makeRemoteAnimation( RemoteAnimationAdapter remoteAnimationAdapter)1033     public static ActivityOptions makeRemoteAnimation(
1034             RemoteAnimationAdapter remoteAnimationAdapter) {
1035         final ActivityOptions opts = new ActivityOptions();
1036         opts.mRemoteAnimationAdapter = remoteAnimationAdapter;
1037         opts.mAnimationType = ANIM_REMOTE_ANIMATION;
1038         return opts;
1039     }
1040 
1041     /**
1042      * Create an {@link ActivityOptions} instance that lets the application control the entire
1043      * animation using a {@link RemoteAnimationAdapter}.
1044      * @hide
1045      */
1046     @RequiresPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS)
makeRemoteAnimation(RemoteAnimationAdapter remoteAnimationAdapter, IRemoteTransition remoteTransition)1047     public static ActivityOptions makeRemoteAnimation(RemoteAnimationAdapter remoteAnimationAdapter,
1048             IRemoteTransition remoteTransition) {
1049         final ActivityOptions opts = new ActivityOptions();
1050         opts.mRemoteAnimationAdapter = remoteAnimationAdapter;
1051         opts.mAnimationType = ANIM_REMOTE_ANIMATION;
1052         opts.mRemoteTransition = remoteTransition;
1053         return opts;
1054     }
1055 
1056     /**
1057      * Create an {@link ActivityOptions} instance that lets the application control the entire
1058      * transition using a {@link IRemoteTransition}.
1059      * @hide
1060      */
1061     @RequiresPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS)
makeRemoteTransition(IRemoteTransition remoteTransition)1062     public static ActivityOptions makeRemoteTransition(IRemoteTransition remoteTransition) {
1063         final ActivityOptions opts = new ActivityOptions();
1064         opts.mRemoteTransition = remoteTransition;
1065         return opts;
1066     }
1067 
1068     /** @hide */
getLaunchTaskBehind()1069     public boolean getLaunchTaskBehind() {
1070         return mAnimationType == ANIM_LAUNCH_TASK_BEHIND;
1071     }
1072 
ActivityOptions()1073     private ActivityOptions() {
1074     }
1075 
1076     /** @hide */
ActivityOptions(Bundle opts)1077     public ActivityOptions(Bundle opts) {
1078         // If the remote side sent us bad parcelables, they won't get the
1079         // results they want, which is their loss.
1080         opts.setDefusable(true);
1081 
1082         mPackageName = opts.getString(KEY_PACKAGE_NAME);
1083         try {
1084             mUsageTimeReport = opts.getParcelable(KEY_USAGE_TIME_REPORT);
1085         } catch (RuntimeException e) {
1086             Slog.w(TAG, e);
1087         }
1088         mLaunchBounds = opts.getParcelable(KEY_LAUNCH_BOUNDS);
1089         mAnimationType = opts.getInt(KEY_ANIM_TYPE, ANIM_UNDEFINED);
1090         switch (mAnimationType) {
1091             case ANIM_CUSTOM:
1092                 mCustomEnterResId = opts.getInt(KEY_ANIM_ENTER_RES_ID, 0);
1093                 mCustomExitResId = opts.getInt(KEY_ANIM_EXIT_RES_ID, 0);
1094                 mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
1095                         opts.getBinder(KEY_ANIM_START_LISTENER));
1096                 break;
1097 
1098             case ANIM_CUSTOM_IN_PLACE:
1099                 mCustomInPlaceResId = opts.getInt(KEY_ANIM_IN_PLACE_RES_ID, 0);
1100                 break;
1101 
1102             case ANIM_SCALE_UP:
1103             case ANIM_CLIP_REVEAL:
1104                 mStartX = opts.getInt(KEY_ANIM_START_X, 0);
1105                 mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
1106                 mWidth = opts.getInt(KEY_ANIM_WIDTH, 0);
1107                 mHeight = opts.getInt(KEY_ANIM_HEIGHT, 0);
1108                 break;
1109 
1110             case ANIM_THUMBNAIL_SCALE_UP:
1111             case ANIM_THUMBNAIL_SCALE_DOWN:
1112             case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
1113             case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
1114                 // Unpackage the HardwareBuffer from the parceled thumbnail
1115                 final HardwareBuffer buffer = opts.getParcelable(KEY_ANIM_THUMBNAIL);
1116                 if (buffer != null) {
1117                     mThumbnail = Bitmap.wrapHardwareBuffer(buffer, null);
1118                 }
1119                 mStartX = opts.getInt(KEY_ANIM_START_X, 0);
1120                 mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
1121                 mWidth = opts.getInt(KEY_ANIM_WIDTH, 0);
1122                 mHeight = opts.getInt(KEY_ANIM_HEIGHT, 0);
1123                 mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
1124                         opts.getBinder(KEY_ANIM_START_LISTENER));
1125                 break;
1126 
1127             case ANIM_SCENE_TRANSITION:
1128                 mTransitionReceiver = opts.getParcelable(KEY_TRANSITION_COMPLETE_LISTENER);
1129                 mIsReturning = opts.getBoolean(KEY_TRANSITION_IS_RETURNING, false);
1130                 mSharedElementNames = opts.getStringArrayList(KEY_TRANSITION_SHARED_ELEMENTS);
1131                 mResultData = opts.getParcelable(KEY_RESULT_DATA);
1132                 mResultCode = opts.getInt(KEY_RESULT_CODE);
1133                 mExitCoordinatorIndex = opts.getInt(KEY_EXIT_COORDINATOR_INDEX);
1134                 break;
1135         }
1136         mLockTaskMode = opts.getBoolean(KEY_LOCK_TASK_MODE, false);
1137         mLaunchDisplayId = opts.getInt(KEY_LAUNCH_DISPLAY_ID, INVALID_DISPLAY);
1138         mCallerDisplayId = opts.getInt(KEY_CALLER_DISPLAY_ID, INVALID_DISPLAY);
1139         mLaunchTaskDisplayArea = opts.getParcelable(KEY_LAUNCH_TASK_DISPLAY_AREA_TOKEN);
1140         mLaunchRootTask = opts.getParcelable(KEY_LAUNCH_ROOT_TASK_TOKEN);
1141         mLaunchWindowingMode = opts.getInt(KEY_LAUNCH_WINDOWING_MODE, WINDOWING_MODE_UNDEFINED);
1142         mLaunchActivityType = opts.getInt(KEY_LAUNCH_ACTIVITY_TYPE, ACTIVITY_TYPE_UNDEFINED);
1143         mLaunchTaskId = opts.getInt(KEY_LAUNCH_TASK_ID, -1);
1144         mPendingIntentLaunchFlags = opts.getInt(KEY_PENDING_INTENT_LAUNCH_FLAGS, 0);
1145         mTaskAlwaysOnTop = opts.getBoolean(KEY_TASK_ALWAYS_ON_TOP, false);
1146         mTaskOverlay = opts.getBoolean(KEY_TASK_OVERLAY, false);
1147         mTaskOverlayCanResume = opts.getBoolean(KEY_TASK_OVERLAY_CAN_RESUME, false);
1148         mAvoidMoveToFront = opts.getBoolean(KEY_AVOID_MOVE_TO_FRONT, false);
1149         mFreezeRecentTasksReordering = opts.getBoolean(KEY_FREEZE_RECENT_TASKS_REORDERING, false);
1150         mDisallowEnterPictureInPictureWhileLaunching = opts.getBoolean(
1151                 KEY_DISALLOW_ENTER_PICTURE_IN_PICTURE_WHILE_LAUNCHING, false);
1152         mApplyActivityFlagsForBubbles = opts.getBoolean(
1153                 KEY_APPLY_ACTIVITY_FLAGS_FOR_BUBBLES, false);
1154         if (opts.containsKey(KEY_ANIM_SPECS)) {
1155             Parcelable[] specs = opts.getParcelableArray(KEY_ANIM_SPECS);
1156             mAnimSpecs = new AppTransitionAnimationSpec[specs.length];
1157             for (int i = specs.length - 1; i >= 0; i--) {
1158                 mAnimSpecs[i] = (AppTransitionAnimationSpec) specs[i];
1159             }
1160         }
1161         if (opts.containsKey(KEY_ANIMATION_FINISHED_LISTENER)) {
1162             mAnimationFinishedListener = IRemoteCallback.Stub.asInterface(
1163                     opts.getBinder(KEY_ANIMATION_FINISHED_LISTENER));
1164         }
1165         mSourceInfo = opts.getParcelable(KEY_SOURCE_INFO);
1166         mRotationAnimationHint = opts.getInt(KEY_ROTATION_ANIMATION_HINT, -1);
1167         mAppVerificationBundle = opts.getBundle(KEY_INSTANT_APP_VERIFICATION_BUNDLE);
1168         if (opts.containsKey(KEY_SPECS_FUTURE)) {
1169             mSpecsFuture = IAppTransitionAnimationSpecsFuture.Stub.asInterface(opts.getBinder(
1170                     KEY_SPECS_FUTURE));
1171         }
1172         mRemoteAnimationAdapter = opts.getParcelable(KEY_REMOTE_ANIMATION_ADAPTER);
1173         mLaunchCookie = opts.getBinder(KEY_LAUNCH_COOKIE);
1174         mRemoteTransition = IRemoteTransition.Stub.asInterface(opts.getBinder(
1175                 KEY_REMOTE_TRANSITION));
1176         mOverrideTaskTransition = opts.getBoolean(KEY_OVERRIDE_TASK_TRANSITION);
1177         mSplashScreenThemeResName = opts.getString(KEY_SPLASH_SCREEN_THEME);
1178         mRemoveWithTaskOrganizer = opts.getBoolean(KEY_REMOVE_WITH_TASK_ORGANIZER);
1179         mLaunchedFromBubble = opts.getBoolean(KEY_LAUNCHED_FROM_BUBBLE);
1180         mTransientLaunch = opts.getBoolean(KEY_TRANSIENT_LAUNCH);
1181         mSplashScreenStyle = opts.getInt(KEY_SPLASH_SCREEN_STYLE);
1182     }
1183 
1184     /**
1185      * Sets the bounds (window size and position) that the activity should be launched in.
1186      * Rect position should be provided in pixels and in screen coordinates.
1187      * Set to {@code null} to explicitly launch fullscreen.
1188      * <p>
1189      * <strong>NOTE:</strong> This value is ignored on devices that don't have
1190      * {@link android.content.pm.PackageManager#FEATURE_FREEFORM_WINDOW_MANAGEMENT} or
1191      * {@link android.content.pm.PackageManager#FEATURE_PICTURE_IN_PICTURE} enabled.
1192      * @param screenSpacePixelRect launch bounds or {@code null} for fullscreen
1193      * @return {@code this} {@link ActivityOptions} instance
1194      */
setLaunchBounds(@ullable Rect screenSpacePixelRect)1195     public ActivityOptions setLaunchBounds(@Nullable Rect screenSpacePixelRect) {
1196         mLaunchBounds = screenSpacePixelRect != null ? new Rect(screenSpacePixelRect) : null;
1197         return this;
1198     }
1199 
1200     /** @hide */
getPackageName()1201     public String getPackageName() {
1202         return mPackageName;
1203     }
1204 
1205     /**
1206      * Returns the bounds that should be used to launch the activity.
1207      * @see #setLaunchBounds(Rect)
1208      * @return Bounds used to launch the activity.
1209      */
1210     @Nullable
getLaunchBounds()1211     public Rect getLaunchBounds() {
1212         return mLaunchBounds;
1213     }
1214 
1215     /** @hide */
getAnimationType()1216     public int getAnimationType() {
1217         return mAnimationType;
1218     }
1219 
1220     /** @hide */
getCustomEnterResId()1221     public int getCustomEnterResId() {
1222         return mCustomEnterResId;
1223     }
1224 
1225     /** @hide */
getCustomExitResId()1226     public int getCustomExitResId() {
1227         return mCustomExitResId;
1228     }
1229 
1230     /** @hide */
getCustomInPlaceResId()1231     public int getCustomInPlaceResId() {
1232         return mCustomInPlaceResId;
1233     }
1234 
1235     /**
1236      * The thumbnail is copied into a hardware bitmap when it is bundled and sent to the system, so
1237      * it should always be backed by a HardwareBuffer on the other end.
1238      *
1239      * @hide
1240      */
getThumbnail()1241     public HardwareBuffer getThumbnail() {
1242         return mThumbnail != null ? mThumbnail.getHardwareBuffer() : null;
1243     }
1244 
1245     /** @hide */
getStartX()1246     public int getStartX() {
1247         return mStartX;
1248     }
1249 
1250     /** @hide */
getStartY()1251     public int getStartY() {
1252         return mStartY;
1253     }
1254 
1255     /** @hide */
getWidth()1256     public int getWidth() {
1257         return mWidth;
1258     }
1259 
1260     /** @hide */
getHeight()1261     public int getHeight() {
1262         return mHeight;
1263     }
1264 
1265     /** @hide */
getAnimationStartedListener()1266     public IRemoteCallback getAnimationStartedListener() {
1267         return mAnimationStartedListener;
1268     }
1269 
1270     /** @hide */
getAnimationFinishedListener()1271     public IRemoteCallback getAnimationFinishedListener() {
1272         return mAnimationFinishedListener;
1273     }
1274 
1275     /** @hide */
getExitCoordinatorKey()1276     public int getExitCoordinatorKey() { return mExitCoordinatorIndex; }
1277 
1278     /** @hide */
abort()1279     public void abort() {
1280         if (mAnimationStartedListener != null) {
1281             try {
1282                 mAnimationStartedListener.sendResult(null);
1283             } catch (RemoteException e) {
1284             }
1285         }
1286     }
1287 
1288     /** @hide */
isReturning()1289     public boolean isReturning() {
1290         return mIsReturning;
1291     }
1292 
1293     /**
1294      * Returns whether or not the ActivityOptions was created with
1295      * {@link #startSharedElementAnimation(Window, Pair[])}.
1296      *
1297      * @hide
1298      */
isCrossTask()1299     boolean isCrossTask() {
1300         return mExitCoordinatorIndex < 0;
1301     }
1302 
1303     /** @hide */
getSharedElementNames()1304     public ArrayList<String> getSharedElementNames() {
1305         return mSharedElementNames;
1306     }
1307 
1308     /** @hide */
getResultReceiver()1309     public ResultReceiver getResultReceiver() { return mTransitionReceiver; }
1310 
1311     /** @hide */
getResultCode()1312     public int getResultCode() { return mResultCode; }
1313 
1314     /** @hide */
getResultData()1315     public Intent getResultData() { return mResultData; }
1316 
1317     /** @hide */
getUsageTimeReport()1318     public PendingIntent getUsageTimeReport() {
1319         return mUsageTimeReport;
1320     }
1321 
1322     /** @hide */
getAnimSpecs()1323     public AppTransitionAnimationSpec[] getAnimSpecs() { return mAnimSpecs; }
1324 
1325     /** @hide */
getSpecsFuture()1326     public IAppTransitionAnimationSpecsFuture getSpecsFuture() {
1327         return mSpecsFuture;
1328     }
1329 
1330     /** @hide */
getRemoteAnimationAdapter()1331     public RemoteAnimationAdapter getRemoteAnimationAdapter() {
1332         return mRemoteAnimationAdapter;
1333     }
1334 
1335     /** @hide */
setRemoteAnimationAdapter(RemoteAnimationAdapter remoteAnimationAdapter)1336     public void setRemoteAnimationAdapter(RemoteAnimationAdapter remoteAnimationAdapter) {
1337         mRemoteAnimationAdapter = remoteAnimationAdapter;
1338     }
1339 
1340     /** @hide */
getRemoteTransition()1341     public IRemoteTransition getRemoteTransition() {
1342         return mRemoteTransition;
1343     }
1344 
1345     /** @hide */
fromBundle(Bundle bOptions)1346     public static ActivityOptions fromBundle(Bundle bOptions) {
1347         return bOptions != null ? new ActivityOptions(bOptions) : null;
1348     }
1349 
1350     /** @hide */
abort(ActivityOptions options)1351     public static void abort(ActivityOptions options) {
1352         if (options != null) {
1353             options.abort();
1354         }
1355     }
1356 
1357     /**
1358      * Gets whether the activity is to be launched into LockTask mode.
1359      * @return {@code true} if the activity is to be launched into LockTask mode.
1360      * @see Activity#startLockTask()
1361      * @see android.app.admin.DevicePolicyManager#setLockTaskPackages(ComponentName, String[])
1362      */
getLockTaskMode()1363     public boolean getLockTaskMode() {
1364         return mLockTaskMode;
1365     }
1366 
1367     /**
1368      * Gets whether the activity want to be launched as other theme for the splash screen.
1369      * @hide
1370      */
1371     @Nullable
getSplashScreenThemeResName()1372     public String getSplashScreenThemeResName() {
1373         return mSplashScreenThemeResName;
1374     }
1375 
1376     /**
1377      * Sets the preferred splash screen style.
1378      * @hide
1379      */
setSplashscreenStyle(@plashScreen.SplashScreenStyle int style)1380     public void setSplashscreenStyle(@SplashScreen.SplashScreenStyle int style) {
1381         mSplashScreenStyle = style;
1382     }
1383 
1384     /**
1385      * Gets the preferred splash screen style from caller
1386      * @hide
1387      */
1388     @SplashScreen.SplashScreenStyle
getSplashScreenStyle()1389     public int getSplashScreenStyle() {
1390         return mSplashScreenStyle;
1391     }
1392 
1393     /**
1394      * Sets whether the activity is to be launched into LockTask mode.
1395      *
1396      * Use this option to start an activity in LockTask mode. Note that only apps permitted by
1397      * {@link android.app.admin.DevicePolicyManager} can run in LockTask mode. Therefore, if
1398      * {@link android.app.admin.DevicePolicyManager#isLockTaskPermitted(String)} returns
1399      * {@code false} for the package of the target activity, a {@link SecurityException} will be
1400      * thrown during {@link Context#startActivity(Intent, Bundle)}. This method doesn't affect
1401      * activities that are already running — relaunch the activity to run in lock task mode.
1402      *
1403      * Defaults to {@code false} if not set.
1404      *
1405      * @param lockTaskMode {@code true} if the activity is to be launched into LockTask mode.
1406      * @return {@code this} {@link ActivityOptions} instance.
1407      * @see Activity#startLockTask()
1408      * @see android.app.admin.DevicePolicyManager#setLockTaskPackages(ComponentName, String[])
1409      */
setLockTaskEnabled(boolean lockTaskMode)1410     public ActivityOptions setLockTaskEnabled(boolean lockTaskMode) {
1411         mLockTaskMode = lockTaskMode;
1412         return this;
1413     }
1414 
1415     /**
1416      * Gets the id of the display where activity should be launched.
1417      * @return The id of the display where activity should be launched,
1418      *         {@link android.view.Display#INVALID_DISPLAY} if not set.
1419      * @see #setLaunchDisplayId(int)
1420      */
getLaunchDisplayId()1421     public int getLaunchDisplayId() {
1422         return mLaunchDisplayId;
1423     }
1424 
1425     /**
1426      * Sets the id of the display where the activity should be launched.
1427      * An app can launch activities on public displays or displays where the app already has
1428      * activities. Otherwise, trying to launch on a private display or providing an invalid display
1429      * id will result in an exception.
1430      * <p>
1431      * Setting launch display id will be ignored on devices that don't have
1432      * {@link android.content.pm.PackageManager#FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS}.
1433      * @param launchDisplayId The id of the display where the activity should be launched.
1434      * @return {@code this} {@link ActivityOptions} instance.
1435      */
setLaunchDisplayId(int launchDisplayId)1436     public ActivityOptions setLaunchDisplayId(int launchDisplayId) {
1437         mLaunchDisplayId = launchDisplayId;
1438         return this;
1439     }
1440 
1441     /** @hide */
getCallerDisplayId()1442     public int getCallerDisplayId() {
1443         return mCallerDisplayId;
1444     }
1445 
1446     /** @hide */
setCallerDisplayId(int callerDisplayId)1447     public ActivityOptions setCallerDisplayId(int callerDisplayId) {
1448         mCallerDisplayId = callerDisplayId;
1449         return this;
1450     }
1451 
1452     /** @hide */
getLaunchTaskDisplayArea()1453     public WindowContainerToken getLaunchTaskDisplayArea() {
1454         return mLaunchTaskDisplayArea;
1455     }
1456 
1457     /** @hide */
setLaunchTaskDisplayArea( WindowContainerToken windowContainerToken)1458     public ActivityOptions setLaunchTaskDisplayArea(
1459             WindowContainerToken windowContainerToken) {
1460         mLaunchTaskDisplayArea = windowContainerToken;
1461         return this;
1462     }
1463 
1464     /** @hide */
getLaunchRootTask()1465     public WindowContainerToken getLaunchRootTask() {
1466         return mLaunchRootTask;
1467     }
1468 
1469     /** @hide */
setLaunchRootTask(WindowContainerToken windowContainerToken)1470     public ActivityOptions setLaunchRootTask(WindowContainerToken windowContainerToken) {
1471         mLaunchRootTask = windowContainerToken;
1472         return this;
1473     }
1474 
1475     /** @hide */
getLaunchWindowingMode()1476     public int getLaunchWindowingMode() {
1477         return mLaunchWindowingMode;
1478     }
1479 
1480     /**
1481      * Sets the windowing mode the activity should launch into.
1482      * @hide
1483      */
1484     @TestApi
setLaunchWindowingMode(int windowingMode)1485     public void setLaunchWindowingMode(int windowingMode) {
1486         mLaunchWindowingMode = windowingMode;
1487     }
1488 
1489     /** @hide */
getLaunchActivityType()1490     public int getLaunchActivityType() {
1491         return mLaunchActivityType;
1492     }
1493 
1494     /** @hide */
1495     @TestApi
setLaunchActivityType(int activityType)1496     public void setLaunchActivityType(int activityType) {
1497         mLaunchActivityType = activityType;
1498     }
1499 
1500     /**
1501      * Sets the task the activity will be launched in.
1502      * @hide
1503      */
1504     @TestApi
setLaunchTaskId(int taskId)1505     public void setLaunchTaskId(int taskId) {
1506         mLaunchTaskId = taskId;
1507     }
1508 
1509     /**
1510      * @hide
1511      */
getLaunchTaskId()1512     public int getLaunchTaskId() {
1513         return mLaunchTaskId;
1514     }
1515 
1516     /**
1517      * Specifies intent flags to be applied for any activity started from a PendingIntent.
1518      *
1519      * @hide
1520      */
setPendingIntentLaunchFlags(@ndroid.content.Intent.Flags int flags)1521     public void setPendingIntentLaunchFlags(@android.content.Intent.Flags int flags) {
1522         mPendingIntentLaunchFlags = flags;
1523     }
1524 
1525     /**
1526      * @hide
1527      */
getPendingIntentLaunchFlags()1528     public int getPendingIntentLaunchFlags() {
1529         return mPendingIntentLaunchFlags;
1530     }
1531 
1532     /**
1533      * Set's whether the task for the activity launched with this option should always be on top.
1534      * @hide
1535      */
1536     @TestApi
setTaskAlwaysOnTop(boolean alwaysOnTop)1537     public void setTaskAlwaysOnTop(boolean alwaysOnTop) {
1538         mTaskAlwaysOnTop = alwaysOnTop;
1539     }
1540 
1541     /**
1542      * @hide
1543      */
getTaskAlwaysOnTop()1544     public boolean getTaskAlwaysOnTop() {
1545         return mTaskAlwaysOnTop;
1546     }
1547 
1548     /**
1549      * Set's whether the activity launched with this option should be a task overlay. That is the
1550      * activity will always be the top activity of the task.
1551      * @param canResume {@code false} if the task will also not be moved to the front of the stack.
1552      * @hide
1553      */
1554     @TestApi
setTaskOverlay(boolean taskOverlay, boolean canResume)1555     public void setTaskOverlay(boolean taskOverlay, boolean canResume) {
1556         mTaskOverlay = taskOverlay;
1557         mTaskOverlayCanResume = canResume;
1558     }
1559 
1560     /**
1561      * @hide
1562      */
getTaskOverlay()1563     public boolean getTaskOverlay() {
1564         return mTaskOverlay;
1565     }
1566 
1567     /**
1568      * @hide
1569      */
canTaskOverlayResume()1570     public boolean canTaskOverlayResume() {
1571         return mTaskOverlayCanResume;
1572     }
1573 
1574     /**
1575      * Sets whether the activity launched should not cause the activity stack it is contained in to
1576      * be moved to the front as a part of launching.
1577      *
1578      * @hide
1579      */
setAvoidMoveToFront()1580     public void setAvoidMoveToFront() {
1581         mAvoidMoveToFront = true;
1582     }
1583 
1584     /**
1585      * @return whether the activity launch should prevent moving the associated activity stack to
1586      *         the front.
1587      * @hide
1588      */
getAvoidMoveToFront()1589     public boolean getAvoidMoveToFront() {
1590         return mAvoidMoveToFront;
1591     }
1592 
1593     /**
1594      * Sets whether the launch of this activity should freeze the recent task list reordering until
1595      * the next user interaction or timeout. This flag is only applied when starting an activity
1596      * in recents.
1597      * @hide
1598      */
setFreezeRecentTasksReordering()1599     public void setFreezeRecentTasksReordering() {
1600         mFreezeRecentTasksReordering = true;
1601     }
1602 
1603     /**
1604      * @return whether the launch of this activity should freeze the recent task list reordering
1605      * @hide
1606      */
freezeRecentTasksReordering()1607     public boolean freezeRecentTasksReordering() {
1608         return mFreezeRecentTasksReordering;
1609     }
1610 
1611     /** @hide */
1612     @UnsupportedAppUsage
setSplitScreenCreateMode(int splitScreenCreateMode)1613     public void setSplitScreenCreateMode(int splitScreenCreateMode) {
1614         // Remove this method after @UnsupportedAppUsage can be removed.
1615     }
1616 
1617     /** @hide */
setDisallowEnterPictureInPictureWhileLaunching(boolean disallow)1618     public void setDisallowEnterPictureInPictureWhileLaunching(boolean disallow) {
1619         mDisallowEnterPictureInPictureWhileLaunching = disallow;
1620     }
1621 
1622     /** @hide */
disallowEnterPictureInPictureWhileLaunching()1623     public boolean disallowEnterPictureInPictureWhileLaunching() {
1624         return mDisallowEnterPictureInPictureWhileLaunching;
1625     }
1626 
1627     /** @hide */
setApplyActivityFlagsForBubbles(boolean apply)1628     public void setApplyActivityFlagsForBubbles(boolean apply) {
1629         mApplyActivityFlagsForBubbles = apply;
1630     }
1631 
1632     /**  @hide */
isApplyActivityFlagsForBubbles()1633     public boolean isApplyActivityFlagsForBubbles() {
1634         return mApplyActivityFlagsForBubbles;
1635     }
1636 
1637     /**
1638      * Sets a launch cookie that can be used to track the activity and task that are launch as a
1639      * result of this option. If the launched activity is a trampoline that starts another activity
1640      * immediately, the cookie will be transferred to the next activity.
1641      *
1642      * @hide
1643      */
setLaunchCookie(IBinder launchCookie)1644     public void setLaunchCookie(IBinder launchCookie) {
1645         mLaunchCookie = launchCookie;
1646     }
1647 
1648     /**
1649      * @return The launch tracking cookie if set or {@code null} otherwise.
1650      *
1651      * @hide
1652      */
getLaunchCookie()1653     public IBinder getLaunchCookie() {
1654         return mLaunchCookie;
1655     }
1656 
1657 
1658     /** @hide */
getOverrideTaskTransition()1659     public boolean getOverrideTaskTransition() {
1660         return mOverrideTaskTransition;
1661     }
1662 
1663     /**
1664      * Sets whether to remove the task when TaskOrganizer, which is managing it, is destroyed.
1665      * @hide
1666      */
setRemoveWithTaskOrganizer(boolean remove)1667     public void setRemoveWithTaskOrganizer(boolean remove) {
1668         mRemoveWithTaskOrganizer = remove;
1669     }
1670 
1671     /**
1672      * @return whether to remove the task when TaskOrganizer, which is managing it, is destroyed.
1673      * @hide
1674      */
getRemoveWithTaskOranizer()1675     public boolean getRemoveWithTaskOranizer() {
1676         return mRemoveWithTaskOrganizer;
1677     }
1678 
1679     /**
1680      * Sets whether this activity is launched from a bubble.
1681      * @hide
1682      */
1683     @TestApi
setLaunchedFromBubble(boolean fromBubble)1684     public void setLaunchedFromBubble(boolean fromBubble) {
1685         mLaunchedFromBubble = fromBubble;
1686     }
1687 
1688     /**
1689      * @return whether the activity was launched from a bubble.
1690      * @hide
1691      */
getLaunchedFromBubble()1692     public boolean getLaunchedFromBubble() {
1693         return mLaunchedFromBubble;
1694     }
1695 
1696     /**
1697      * Sets whether the activity launch is part of a transient operation. If it is, it will not
1698      * cause lifecycle changes in existing activities even if it were to occlude them (ie. other
1699      * activities occluded by this one will not be paused or stopped until the launch is committed).
1700      * As a consequence, it will start immediately since it doesn't need to wait for other
1701      * lifecycles to evolve. Current user is recents.
1702      * @hide
1703      */
setTransientLaunch()1704     public ActivityOptions setTransientLaunch() {
1705         mTransientLaunch = true;
1706         return this;
1707     }
1708 
1709     /**
1710      * @see #setTransientLaunch()
1711      * @return whether the activity launch is part of a transient operation.
1712      * @hide
1713      */
getTransientLaunch()1714     public boolean getTransientLaunch() {
1715         return mTransientLaunch;
1716     }
1717 
1718     /**
1719      * Update the current values in this ActivityOptions from those supplied
1720      * in <var>otherOptions</var>.  Any values
1721      * defined in <var>otherOptions</var> replace those in the base options.
1722      */
update(ActivityOptions otherOptions)1723     public void update(ActivityOptions otherOptions) {
1724         if (otherOptions.mPackageName != null) {
1725             mPackageName = otherOptions.mPackageName;
1726         }
1727         mUsageTimeReport = otherOptions.mUsageTimeReport;
1728         mTransitionReceiver = null;
1729         mSharedElementNames = null;
1730         mIsReturning = false;
1731         mResultData = null;
1732         mResultCode = 0;
1733         mExitCoordinatorIndex = 0;
1734         mAnimationType = otherOptions.mAnimationType;
1735         switch (otherOptions.mAnimationType) {
1736             case ANIM_CUSTOM:
1737                 mCustomEnterResId = otherOptions.mCustomEnterResId;
1738                 mCustomExitResId = otherOptions.mCustomExitResId;
1739                 mThumbnail = null;
1740                 if (mAnimationStartedListener != null) {
1741                     try {
1742                         mAnimationStartedListener.sendResult(null);
1743                     } catch (RemoteException e) {
1744                     }
1745                 }
1746                 mAnimationStartedListener = otherOptions.mAnimationStartedListener;
1747                 break;
1748             case ANIM_CUSTOM_IN_PLACE:
1749                 mCustomInPlaceResId = otherOptions.mCustomInPlaceResId;
1750                 break;
1751             case ANIM_SCALE_UP:
1752                 mStartX = otherOptions.mStartX;
1753                 mStartY = otherOptions.mStartY;
1754                 mWidth = otherOptions.mWidth;
1755                 mHeight = otherOptions.mHeight;
1756                 if (mAnimationStartedListener != null) {
1757                     try {
1758                         mAnimationStartedListener.sendResult(null);
1759                     } catch (RemoteException e) {
1760                     }
1761                 }
1762                 mAnimationStartedListener = null;
1763                 break;
1764             case ANIM_THUMBNAIL_SCALE_UP:
1765             case ANIM_THUMBNAIL_SCALE_DOWN:
1766             case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
1767             case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
1768                 mThumbnail = otherOptions.mThumbnail;
1769                 mStartX = otherOptions.mStartX;
1770                 mStartY = otherOptions.mStartY;
1771                 mWidth = otherOptions.mWidth;
1772                 mHeight = otherOptions.mHeight;
1773                 if (mAnimationStartedListener != null) {
1774                     try {
1775                         mAnimationStartedListener.sendResult(null);
1776                     } catch (RemoteException e) {
1777                     }
1778                 }
1779                 mAnimationStartedListener = otherOptions.mAnimationStartedListener;
1780                 break;
1781             case ANIM_SCENE_TRANSITION:
1782                 mTransitionReceiver = otherOptions.mTransitionReceiver;
1783                 mSharedElementNames = otherOptions.mSharedElementNames;
1784                 mIsReturning = otherOptions.mIsReturning;
1785                 mThumbnail = null;
1786                 mAnimationStartedListener = null;
1787                 mResultData = otherOptions.mResultData;
1788                 mResultCode = otherOptions.mResultCode;
1789                 mExitCoordinatorIndex = otherOptions.mExitCoordinatorIndex;
1790                 break;
1791         }
1792         mLockTaskMode = otherOptions.mLockTaskMode;
1793         mAnimSpecs = otherOptions.mAnimSpecs;
1794         mAnimationFinishedListener = otherOptions.mAnimationFinishedListener;
1795         mSpecsFuture = otherOptions.mSpecsFuture;
1796         mRemoteAnimationAdapter = otherOptions.mRemoteAnimationAdapter;
1797     }
1798 
1799     /**
1800      * Returns the created options as a Bundle, which can be passed to
1801      * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle)
1802      * Context.startActivity(Intent, Bundle)} and related methods.
1803      * Note that the returned Bundle is still owned by the ActivityOptions
1804      * object; you must not modify it, but can supply it to the startActivity
1805      * methods that take an options Bundle.
1806      */
toBundle()1807     public Bundle toBundle() {
1808         Bundle b = new Bundle();
1809         if (mPackageName != null) {
1810             b.putString(KEY_PACKAGE_NAME, mPackageName);
1811         }
1812         if (mLaunchBounds != null) {
1813             b.putParcelable(KEY_LAUNCH_BOUNDS, mLaunchBounds);
1814         }
1815         if (mAnimationType != ANIM_UNDEFINED) {
1816             b.putInt(KEY_ANIM_TYPE, mAnimationType);
1817         }
1818         if (mUsageTimeReport != null) {
1819             b.putParcelable(KEY_USAGE_TIME_REPORT, mUsageTimeReport);
1820         }
1821         switch (mAnimationType) {
1822             case ANIM_CUSTOM:
1823                 b.putInt(KEY_ANIM_ENTER_RES_ID, mCustomEnterResId);
1824                 b.putInt(KEY_ANIM_EXIT_RES_ID, mCustomExitResId);
1825                 b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
1826                         != null ? mAnimationStartedListener.asBinder() : null);
1827                 break;
1828             case ANIM_CUSTOM_IN_PLACE:
1829                 b.putInt(KEY_ANIM_IN_PLACE_RES_ID, mCustomInPlaceResId);
1830                 break;
1831             case ANIM_SCALE_UP:
1832             case ANIM_CLIP_REVEAL:
1833                 b.putInt(KEY_ANIM_START_X, mStartX);
1834                 b.putInt(KEY_ANIM_START_Y, mStartY);
1835                 b.putInt(KEY_ANIM_WIDTH, mWidth);
1836                 b.putInt(KEY_ANIM_HEIGHT, mHeight);
1837                 break;
1838             case ANIM_THUMBNAIL_SCALE_UP:
1839             case ANIM_THUMBNAIL_SCALE_DOWN:
1840             case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
1841             case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
1842                 // Once we parcel the thumbnail for transfering over to the system, create a copy of
1843                 // the bitmap to a hardware bitmap and pass through the HardwareBuffer
1844                 if (mThumbnail != null) {
1845                     final Bitmap hwBitmap = mThumbnail.copy(Config.HARDWARE, false /* isMutable */);
1846                     if (hwBitmap != null) {
1847                         b.putParcelable(KEY_ANIM_THUMBNAIL, hwBitmap.getHardwareBuffer());
1848                     } else {
1849                         Slog.w(TAG, "Failed to copy thumbnail");
1850                     }
1851                 }
1852                 b.putInt(KEY_ANIM_START_X, mStartX);
1853                 b.putInt(KEY_ANIM_START_Y, mStartY);
1854                 b.putInt(KEY_ANIM_WIDTH, mWidth);
1855                 b.putInt(KEY_ANIM_HEIGHT, mHeight);
1856                 b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
1857                         != null ? mAnimationStartedListener.asBinder() : null);
1858                 break;
1859             case ANIM_SCENE_TRANSITION:
1860                 if (mTransitionReceiver != null) {
1861                     b.putParcelable(KEY_TRANSITION_COMPLETE_LISTENER, mTransitionReceiver);
1862                 }
1863                 b.putBoolean(KEY_TRANSITION_IS_RETURNING, mIsReturning);
1864                 b.putStringArrayList(KEY_TRANSITION_SHARED_ELEMENTS, mSharedElementNames);
1865                 b.putParcelable(KEY_RESULT_DATA, mResultData);
1866                 b.putInt(KEY_RESULT_CODE, mResultCode);
1867                 b.putInt(KEY_EXIT_COORDINATOR_INDEX, mExitCoordinatorIndex);
1868                 break;
1869         }
1870         if (mLockTaskMode) {
1871             b.putBoolean(KEY_LOCK_TASK_MODE, mLockTaskMode);
1872         }
1873         if (mLaunchDisplayId != INVALID_DISPLAY) {
1874             b.putInt(KEY_LAUNCH_DISPLAY_ID, mLaunchDisplayId);
1875         }
1876         if (mCallerDisplayId != INVALID_DISPLAY) {
1877             b.putInt(KEY_CALLER_DISPLAY_ID, mCallerDisplayId);
1878         }
1879         if (mLaunchTaskDisplayArea != null) {
1880             b.putParcelable(KEY_LAUNCH_TASK_DISPLAY_AREA_TOKEN, mLaunchTaskDisplayArea);
1881         }
1882         if (mLaunchRootTask != null) {
1883             b.putParcelable(KEY_LAUNCH_ROOT_TASK_TOKEN, mLaunchRootTask);
1884         }
1885         if (mLaunchWindowingMode != WINDOWING_MODE_UNDEFINED) {
1886             b.putInt(KEY_LAUNCH_WINDOWING_MODE, mLaunchWindowingMode);
1887         }
1888         if (mLaunchActivityType != ACTIVITY_TYPE_UNDEFINED) {
1889             b.putInt(KEY_LAUNCH_ACTIVITY_TYPE, mLaunchActivityType);
1890         }
1891         if (mLaunchTaskId != -1) {
1892             b.putInt(KEY_LAUNCH_TASK_ID, mLaunchTaskId);
1893         }
1894         if (mPendingIntentLaunchFlags != 0) {
1895             b.putInt(KEY_PENDING_INTENT_LAUNCH_FLAGS, mPendingIntentLaunchFlags);
1896         }
1897         if (mTaskAlwaysOnTop) {
1898             b.putBoolean(KEY_TASK_ALWAYS_ON_TOP, mTaskAlwaysOnTop);
1899         }
1900         if (mTaskOverlay) {
1901             b.putBoolean(KEY_TASK_OVERLAY, mTaskOverlay);
1902         }
1903         if (mTaskOverlayCanResume) {
1904             b.putBoolean(KEY_TASK_OVERLAY_CAN_RESUME, mTaskOverlayCanResume);
1905         }
1906         if (mAvoidMoveToFront) {
1907             b.putBoolean(KEY_AVOID_MOVE_TO_FRONT, mAvoidMoveToFront);
1908         }
1909         if (mFreezeRecentTasksReordering) {
1910             b.putBoolean(KEY_FREEZE_RECENT_TASKS_REORDERING, mFreezeRecentTasksReordering);
1911         }
1912         if (mDisallowEnterPictureInPictureWhileLaunching) {
1913             b.putBoolean(KEY_DISALLOW_ENTER_PICTURE_IN_PICTURE_WHILE_LAUNCHING,
1914                     mDisallowEnterPictureInPictureWhileLaunching);
1915         }
1916         if (mApplyActivityFlagsForBubbles) {
1917             b.putBoolean(KEY_APPLY_ACTIVITY_FLAGS_FOR_BUBBLES, mApplyActivityFlagsForBubbles);
1918         }
1919         if (mAnimSpecs != null) {
1920             b.putParcelableArray(KEY_ANIM_SPECS, mAnimSpecs);
1921         }
1922         if (mAnimationFinishedListener != null) {
1923             b.putBinder(KEY_ANIMATION_FINISHED_LISTENER, mAnimationFinishedListener.asBinder());
1924         }
1925         if (mSpecsFuture != null) {
1926             b.putBinder(KEY_SPECS_FUTURE, mSpecsFuture.asBinder());
1927         }
1928         if (mSourceInfo != null) {
1929             b.putParcelable(KEY_SOURCE_INFO, mSourceInfo);
1930         }
1931         if (mRotationAnimationHint != -1) {
1932             b.putInt(KEY_ROTATION_ANIMATION_HINT, mRotationAnimationHint);
1933         }
1934         if (mAppVerificationBundle != null) {
1935             b.putBundle(KEY_INSTANT_APP_VERIFICATION_BUNDLE, mAppVerificationBundle);
1936         }
1937         if (mRemoteAnimationAdapter != null) {
1938             b.putParcelable(KEY_REMOTE_ANIMATION_ADAPTER, mRemoteAnimationAdapter);
1939         }
1940         if (mLaunchCookie != null) {
1941             b.putBinder(KEY_LAUNCH_COOKIE, mLaunchCookie);
1942         }
1943         if (mRemoteTransition != null) {
1944             b.putBinder(KEY_REMOTE_TRANSITION, mRemoteTransition.asBinder());
1945         }
1946         if (mOverrideTaskTransition) {
1947             b.putBoolean(KEY_OVERRIDE_TASK_TRANSITION, mOverrideTaskTransition);
1948         }
1949         if (mSplashScreenThemeResName != null && !mSplashScreenThemeResName.isEmpty()) {
1950             b.putString(KEY_SPLASH_SCREEN_THEME, mSplashScreenThemeResName);
1951         }
1952         if (mRemoveWithTaskOrganizer) {
1953             b.putBoolean(KEY_REMOVE_WITH_TASK_ORGANIZER, mRemoveWithTaskOrganizer);
1954         }
1955         if (mLaunchedFromBubble) {
1956             b.putBoolean(KEY_LAUNCHED_FROM_BUBBLE, mLaunchedFromBubble);
1957         }
1958         if (mTransientLaunch) {
1959             b.putBoolean(KEY_TRANSIENT_LAUNCH, mTransientLaunch);
1960         }
1961         if (mSplashScreenStyle != 0) {
1962             b.putInt(KEY_SPLASH_SCREEN_STYLE, mSplashScreenStyle);
1963         }
1964         return b;
1965     }
1966 
1967     /**
1968      * Ask the system track that time the user spends in the app being launched, and
1969      * report it back once done.  The report will be sent to the given receiver, with
1970      * the extras {@link #EXTRA_USAGE_TIME_REPORT} and {@link #EXTRA_USAGE_TIME_REPORT_PACKAGES}
1971      * filled in.
1972      *
1973      * <p>The time interval tracked is from launching this activity until the user leaves
1974      * that activity's flow.  They are considered to stay in the flow as long as
1975      * new activities are being launched or returned to from the original flow,
1976      * even if this crosses package or task boundaries.  For example, if the originator
1977      * starts an activity to view an image, and while there the user selects to share,
1978      * which launches their email app in a new task, and they complete the share, the
1979      * time during that entire operation will be included until they finally hit back from
1980      * the original image viewer activity.</p>
1981      *
1982      * <p>The user is considered to complete a flow once they switch to another
1983      * activity that is not part of the tracked flow.  This may happen, for example, by
1984      * using the notification shade, launcher, or recents to launch or switch to another
1985      * app.  Simply going in to these navigation elements does not break the flow (although
1986      * the launcher and recents stops time tracking of the session); it is the act of
1987      * going somewhere else that completes the tracking.</p>
1988      *
1989      * @param receiver A broadcast receiver that willl receive the report.
1990      */
requestUsageTimeReport(PendingIntent receiver)1991     public void requestUsageTimeReport(PendingIntent receiver) {
1992         mUsageTimeReport = receiver;
1993     }
1994 
1995     /**
1996      * Returns the launch source information set by {@link #setSourceInfo}.
1997      * @hide
1998      */
getSourceInfo()1999     public @Nullable SourceInfo getSourceInfo() {
2000         return mSourceInfo;
2001     }
2002 
2003     /**
2004      * Sets the source information of the launch event.
2005      *
2006      * @param type The type of the startup source.
2007      * @param uptimeMillis The event time of startup source in milliseconds since boot, not
2008      *                     including sleep (e.g. from {@link android.view.MotionEvent#getEventTime}
2009      *                     or {@link android.os.SystemClock#uptimeMillis}).
2010      * @see SourceInfo
2011      * @hide
2012      */
setSourceInfo(@ourceInfo.SourceType int type, long uptimeMillis)2013     public void setSourceInfo(@SourceInfo.SourceType int type, long uptimeMillis) {
2014         mSourceInfo = new SourceInfo(type, uptimeMillis);
2015     }
2016 
2017     /**
2018      * Return the filtered options only meant to be seen by the target activity itself
2019      * @hide
2020      */
forTargetActivity()2021     public ActivityOptions forTargetActivity() {
2022         if (mAnimationType == ANIM_SCENE_TRANSITION) {
2023             final ActivityOptions result = new ActivityOptions();
2024             result.update(this);
2025             return result;
2026         }
2027 
2028         return null;
2029     }
2030 
2031     /**
2032      * Returns the rotation animation set by {@link setRotationAnimationHint} or -1
2033      * if unspecified.
2034      * @hide
2035      */
getRotationAnimationHint()2036     public int getRotationAnimationHint() {
2037         return mRotationAnimationHint;
2038     }
2039 
2040 
2041     /**
2042      * Set a rotation animation to be used if launching the activity
2043      * triggers an orientation change, or -1 to clear. See
2044      * {@link android.view.WindowManager.LayoutParams} for rotation
2045      * animation values.
2046      * @hide
2047      */
setRotationAnimationHint(int hint)2048     public void setRotationAnimationHint(int hint) {
2049         mRotationAnimationHint = hint;
2050     }
2051 
2052     /**
2053      * Pop the extra verification bundle for the installer.
2054      * This removes the bundle from the ActivityOptions to make sure the installer bundle
2055      * is only available once.
2056      * @hide
2057      */
popAppVerificationBundle()2058     public Bundle popAppVerificationBundle() {
2059         Bundle out = mAppVerificationBundle;
2060         mAppVerificationBundle = null;
2061         return out;
2062     }
2063 
2064     /**
2065      * Set the {@link Bundle} that is provided to the app installer for additional verification
2066      * if the call to {@link Context#startActivity} results in an app being installed.
2067      *
2068      * This Bundle is not provided to any other app besides the installer.
2069      */
setAppVerificationBundle(Bundle bundle)2070     public ActivityOptions setAppVerificationBundle(Bundle bundle) {
2071         mAppVerificationBundle = bundle;
2072         return this;
2073 
2074     }
2075 
2076     /** @hide */
2077     @Override
toString()2078     public String toString() {
2079         return "ActivityOptions(" + hashCode() + "), mPackageName=" + mPackageName
2080                 + ", mAnimationType=" + mAnimationType + ", mStartX=" + mStartX + ", mStartY="
2081                 + mStartY + ", mWidth=" + mWidth + ", mHeight=" + mHeight;
2082     }
2083 
2084     /**
2085      * The information about the source of activity launch. E.g. describe an activity is launched
2086      * from launcher by receiving a motion event with a timestamp.
2087      * @hide
2088      */
2089     public static class SourceInfo implements Parcelable {
2090         /** Launched from launcher. */
2091         public static final int TYPE_LAUNCHER = 1;
2092         /** Launched from notification. */
2093         public static final int TYPE_NOTIFICATION = 2;
2094         /** Launched from lockscreen, including notification while the device is locked. */
2095         public static final int TYPE_LOCKSCREEN = 3;
2096         /** Launched from recents gesture handler. */
2097         public static final int TYPE_RECENTS_ANIMATION = 4;
2098 
2099         @IntDef(prefix = { "TYPE_" }, value = {
2100                 TYPE_LAUNCHER,
2101                 TYPE_NOTIFICATION,
2102                 TYPE_LOCKSCREEN,
2103         })
2104         @Retention(RetentionPolicy.SOURCE)
2105         public @interface SourceType {}
2106 
2107         /** The type of the startup source. */
2108         public final @SourceType int type;
2109 
2110         /** The timestamp (uptime based) of the source to launch activity. */
2111         public final long eventTimeMs;
2112 
SourceInfo(@ourceType int srcType, long uptimeMillis)2113         SourceInfo(@SourceType int srcType, long uptimeMillis) {
2114             type = srcType;
2115             eventTimeMs = uptimeMillis;
2116         }
2117 
2118         @Override
writeToParcel(Parcel dest, int flags)2119         public void writeToParcel(Parcel dest, int flags) {
2120             dest.writeInt(type);
2121             dest.writeLong(eventTimeMs);
2122         }
2123 
2124         @Override
describeContents()2125         public int describeContents() {
2126             return 0;
2127         }
2128 
2129         public static final Creator<SourceInfo> CREATOR = new Creator<SourceInfo>() {
2130             public SourceInfo createFromParcel(Parcel in) {
2131                 return new SourceInfo(in.readInt(), in.readLong());
2132             }
2133 
2134             public SourceInfo[] newArray(int size) {
2135                 return new SourceInfo[size];
2136             }
2137         };
2138     }
2139 }
2140