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