• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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 com.android.server.wm;
18 
19 import static android.view.WindowManager.LayoutParams;
20 import static android.view.WindowManager.TRANSIT_CHANGE;
21 import static android.view.WindowManager.TRANSIT_CLOSE;
22 import static android.view.WindowManager.TRANSIT_FLAG_APP_CRASHED;
23 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
24 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION;
25 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
26 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
27 import static android.view.WindowManager.TRANSIT_FLAG_OPEN_BEHIND;
28 import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
29 import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
30 import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
31 import static android.view.WindowManager.TRANSIT_NONE;
32 import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE;
33 import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
34 import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_RELAUNCH;
35 import static android.view.WindowManager.TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE;
36 import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY;
37 import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
38 import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_OCCLUDE;
39 import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_UNOCCLUDE;
40 import static android.view.WindowManager.TRANSIT_OLD_NONE;
41 import static android.view.WindowManager.TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE;
42 import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
43 import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
44 import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN_BEHIND;
45 import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_BACK;
46 import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_FRONT;
47 import static android.view.WindowManager.TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE;
48 import static android.view.WindowManager.TRANSIT_OLD_TRANSLUCENT_ACTIVITY_OPEN;
49 import static android.view.WindowManager.TRANSIT_OLD_UNSET;
50 import static android.view.WindowManager.TRANSIT_OLD_WALLPAPER_CLOSE;
51 import static android.view.WindowManager.TRANSIT_OLD_WALLPAPER_INTRA_CLOSE;
52 import static android.view.WindowManager.TRANSIT_OLD_WALLPAPER_INTRA_OPEN;
53 import static android.view.WindowManager.TRANSIT_OLD_WALLPAPER_OPEN;
54 import static android.view.WindowManager.TRANSIT_OPEN;
55 import static android.view.WindowManager.TRANSIT_RELAUNCH;
56 import static android.view.WindowManager.TRANSIT_TO_BACK;
57 import static android.view.WindowManager.TRANSIT_TO_FRONT;
58 
59 import static com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation;
60 import static com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation;
61 import static com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation;
62 import static com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation;
63 import static com.android.internal.R.styleable.WindowAnimation_launchTaskBehindSourceAnimation;
64 import static com.android.internal.R.styleable.WindowAnimation_launchTaskBehindTargetAnimation;
65 import static com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation;
66 import static com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation;
67 import static com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation;
68 import static com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation;
69 import static com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation;
70 import static com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation;
71 import static com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation;
72 import static com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation;
73 import static com.android.internal.R.styleable.WindowAnimation_wallpaperCloseEnterAnimation;
74 import static com.android.internal.R.styleable.WindowAnimation_wallpaperCloseExitAnimation;
75 import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseEnterAnimation;
76 import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation;
77 import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenEnterAnimation;
78 import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation;
79 import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation;
80 import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation;
81 import static com.android.internal.policy.TransitionAnimation.THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN;
82 import static com.android.internal.policy.TransitionAnimation.THUMBNAIL_TRANSITION_ENTER_SCALE_UP;
83 import static com.android.internal.policy.TransitionAnimation.THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN;
84 import static com.android.internal.policy.TransitionAnimation.THUMBNAIL_TRANSITION_EXIT_SCALE_UP;
85 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
86 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
87 import static com.android.server.wm.AppTransitionProto.APP_TRANSITION_STATE;
88 import static com.android.server.wm.AppTransitionProto.LAST_USED_APP_TRANSITION;
89 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
90 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
91 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
92 import static com.android.server.wm.WindowManagerInternal.AppTransitionListener;
93 import static com.android.server.wm.WindowManagerInternal.KeyguardExitAnimationStartListener;
94 import static com.android.server.wm.WindowStateAnimator.ROOT_TASK_CLIP_AFTER_ANIM;
95 import static com.android.server.wm.WindowStateAnimator.ROOT_TASK_CLIP_NONE;
96 
97 import android.annotation.DrawableRes;
98 import android.annotation.NonNull;
99 import android.annotation.Nullable;
100 import android.app.ActivityManager;
101 import android.content.ComponentName;
102 import android.content.Context;
103 import android.content.res.Configuration;
104 import android.content.res.TypedArray;
105 import android.graphics.Bitmap;
106 import android.graphics.Canvas;
107 import android.graphics.Color;
108 import android.graphics.Picture;
109 import android.graphics.Rect;
110 import android.graphics.drawable.Drawable;
111 import android.hardware.HardwareBuffer;
112 import android.os.Binder;
113 import android.os.Debug;
114 import android.os.Handler;
115 import android.os.IBinder;
116 import android.os.IRemoteCallback;
117 import android.os.RemoteException;
118 import android.os.SystemClock;
119 import android.os.SystemProperties;
120 import android.os.UserHandle;
121 import android.util.Pair;
122 import android.util.Slog;
123 import android.util.SparseArray;
124 import android.util.proto.ProtoOutputStream;
125 import android.view.AppTransitionAnimationSpec;
126 import android.view.IAppTransitionAnimationSpecsFuture;
127 import android.view.RemoteAnimationAdapter;
128 import android.view.WindowManager.TransitionFlags;
129 import android.view.WindowManager.TransitionOldType;
130 import android.view.WindowManager.TransitionType;
131 import android.view.animation.AlphaAnimation;
132 import android.view.animation.Animation;
133 import android.view.animation.AnimationSet;
134 import android.view.animation.AnimationUtils;
135 import android.view.animation.ClipRectAnimation;
136 import android.view.animation.Interpolator;
137 import android.view.animation.PathInterpolator;
138 import android.view.animation.ScaleAnimation;
139 import android.view.animation.TranslateAnimation;
140 
141 import com.android.internal.annotations.VisibleForTesting;
142 import com.android.internal.policy.TransitionAnimation;
143 import com.android.internal.protolog.common.ProtoLog;
144 import com.android.internal.util.DumpUtils.Dump;
145 import com.android.internal.util.function.pooled.PooledLambda;
146 import com.android.internal.util.function.pooled.PooledPredicate;
147 
148 import java.io.PrintWriter;
149 import java.util.ArrayList;
150 import java.util.concurrent.ExecutorService;
151 import java.util.concurrent.Executors;
152 
153 // State management of app transitions.  When we are preparing for a
154 // transition, mNextAppTransition will be the kind of transition to
155 // perform or TRANSIT_NONE if we are not waiting.  If we are waiting,
156 // mOpeningApps and mClosingApps are the lists of tokens that will be
157 // made visible or hidden at the next transition.
158 public class AppTransition implements Dump {
159     private static final String TAG = TAG_WITH_CLASS_NAME ? "AppTransition" : TAG_WM;
160     private static final int CLIP_REVEAL_TRANSLATION_Y_DP = 8;
161 
162     /** Fraction of animation at which the recents thumbnail stays completely transparent */
163     private static final float RECENTS_THUMBNAIL_FADEIN_FRACTION = 0.5f;
164     /** Fraction of animation at which the recents thumbnail becomes completely transparent */
165     private static final float RECENTS_THUMBNAIL_FADEOUT_FRACTION = 0.5f;
166 
167     static final int DEFAULT_APP_TRANSITION_DURATION = 336;
168 
169     /** Interpolator to be used for animations that respond directly to a touch */
170     static final Interpolator TOUCH_RESPONSE_INTERPOLATOR =
171             new PathInterpolator(0.3f, 0f, 0.1f, 1f);
172 
173     /**
174      * Maximum duration for the clip reveal animation. This is used when there is a lot of movement
175      * involved, to make it more understandable.
176      */
177     private static final int MAX_CLIP_REVEAL_TRANSITION_DURATION = 420;
178     private static final int THUMBNAIL_APP_TRANSITION_DURATION = 336;
179     private static final long APP_TRANSITION_TIMEOUT_MS = 5000;
180     static final int MAX_APP_TRANSITION_DURATION = 3 * 1000; // 3 secs.
181 
182     private final Context mContext;
183     private final WindowManagerService mService;
184     private final DisplayContent mDisplayContent;
185 
186     private final TransitionAnimation mTransitionAnimation;
187 
188     private @TransitionFlags int mNextAppTransitionFlags = 0;
189     private final ArrayList<Integer> mNextAppTransitionRequests = new ArrayList<>();
190     private @TransitionOldType int mLastUsedAppTransition = TRANSIT_OLD_UNSET;
191     private String mLastOpeningApp;
192     private String mLastClosingApp;
193     private String mLastChangingApp;
194 
195     private static final int NEXT_TRANSIT_TYPE_NONE = 0;
196     private static final int NEXT_TRANSIT_TYPE_CUSTOM = 1;
197     private static final int NEXT_TRANSIT_TYPE_SCALE_UP = 2;
198     private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP = 3;
199     private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN = 4;
200     private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP = 5;
201     private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN = 6;
202     private static final int NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE = 7;
203     private static final int NEXT_TRANSIT_TYPE_CLIP_REVEAL = 8;
204 
205     /**
206      * Refers to the transition to activity started by using {@link
207      * android.content.pm.crossprofile.CrossProfileApps#startMainActivity(ComponentName, UserHandle)
208      * }.
209      */
210     private static final int NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS = 9;
211     private static final int NEXT_TRANSIT_TYPE_REMOTE = 10;
212 
213     private int mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE;
214     private boolean mNextAppTransitionOverrideRequested;
215 
216     private String mNextAppTransitionPackage;
217     // Used for thumbnail transitions. True if we're scaling up, false if scaling down
218     private boolean mNextAppTransitionScaleUp;
219     private IRemoteCallback mNextAppTransitionCallback;
220     private IRemoteCallback mNextAppTransitionFutureCallback;
221     private IRemoteCallback mAnimationFinishedCallback;
222     private int mNextAppTransitionEnter;
223     private int mNextAppTransitionExit;
224     private int mNextAppTransitionInPlace;
225 
226     // Keyed by WindowContainer hashCode.
227     private final SparseArray<AppTransitionAnimationSpec> mNextAppTransitionAnimationsSpecs
228             = new SparseArray<>();
229     private IAppTransitionAnimationSpecsFuture mNextAppTransitionAnimationsSpecsFuture;
230     private boolean mNextAppTransitionAnimationsSpecsPending;
231     private AppTransitionAnimationSpec mDefaultNextAppTransitionAnimationSpec;
232 
233     private Rect mNextAppTransitionInsets = new Rect();
234 
235     private Rect mTmpFromClipRect = new Rect();
236     private Rect mTmpToClipRect = new Rect();
237 
238     private final Rect mTmpRect = new Rect();
239 
240     private final static int APP_STATE_IDLE = 0;
241     private final static int APP_STATE_READY = 1;
242     private final static int APP_STATE_RUNNING = 2;
243     private final static int APP_STATE_TIMEOUT = 3;
244     private int mAppTransitionState = APP_STATE_IDLE;
245 
246     private final int mConfigShortAnimTime;
247     private final Interpolator mDecelerateInterpolator;
248     private final Interpolator mThumbnailFadeInInterpolator;
249     private final Interpolator mThumbnailFadeOutInterpolator;
250     private final Interpolator mLinearOutSlowInInterpolator;
251     private final Interpolator mFastOutLinearInInterpolator;
252     private final Interpolator mFastOutSlowInInterpolator;
253     private final Interpolator mClipHorizontalInterpolator = new PathInterpolator(0, 0, 0.4f, 1f);
254 
255     private final int mClipRevealTranslationY;
256 
257     private int mCurrentUserId = 0;
258     private long mLastClipRevealTransitionDuration = DEFAULT_APP_TRANSITION_DURATION;
259 
260     private final ArrayList<AppTransitionListener> mListeners = new ArrayList<>();
261     private KeyguardExitAnimationStartListener mKeyguardExitAnimationStartListener;
262     private final ExecutorService mDefaultExecutor = Executors.newSingleThreadExecutor();
263 
264     private int mLastClipRevealMaxTranslation;
265     private boolean mLastHadClipReveal;
266 
267     private final boolean mGridLayoutRecentsEnabled;
268     private final boolean mLowRamRecentsEnabled;
269 
270     private final int mDefaultWindowAnimationStyleResId;
271     private boolean mOverrideTaskTransition;
272 
273     private RemoteAnimationController mRemoteAnimationController;
274 
275     final Handler mHandler;
276     final Runnable mHandleAppTransitionTimeoutRunnable = () -> handleAppTransitionTimeout();
277 
AppTransition(Context context, WindowManagerService service, DisplayContent displayContent)278     AppTransition(Context context, WindowManagerService service, DisplayContent displayContent) {
279         mContext = context;
280         mService = service;
281         mHandler = new Handler(service.mH.getLooper());
282         mDisplayContent = displayContent;
283         mTransitionAnimation = new TransitionAnimation(context, DEBUG_ANIM, TAG);
284         mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
285                 com.android.internal.R.interpolator.linear_out_slow_in);
286         mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context,
287                 com.android.internal.R.interpolator.fast_out_linear_in);
288         mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
289                 com.android.internal.R.interpolator.fast_out_slow_in);
290         mConfigShortAnimTime = context.getResources().getInteger(
291                 com.android.internal.R.integer.config_shortAnimTime);
292         mDecelerateInterpolator = AnimationUtils.loadInterpolator(context,
293                 com.android.internal.R.interpolator.decelerate_cubic);
294         mThumbnailFadeInInterpolator = new Interpolator() {
295             @Override
296             public float getInterpolation(float input) {
297                 // Linear response for first fraction, then complete after that.
298                 if (input < RECENTS_THUMBNAIL_FADEIN_FRACTION) {
299                     return 0f;
300                 }
301                 float t = (input - RECENTS_THUMBNAIL_FADEIN_FRACTION) /
302                         (1f - RECENTS_THUMBNAIL_FADEIN_FRACTION);
303                 return mFastOutLinearInInterpolator.getInterpolation(t);
304             }
305         };
306         mThumbnailFadeOutInterpolator = new Interpolator() {
307             @Override
308             public float getInterpolation(float input) {
309                 // Linear response for first fraction, then complete after that.
310                 if (input < RECENTS_THUMBNAIL_FADEOUT_FRACTION) {
311                     float t = input / RECENTS_THUMBNAIL_FADEOUT_FRACTION;
312                     return mLinearOutSlowInInterpolator.getInterpolation(t);
313                 }
314                 return 1f;
315             }
316         };
317         mClipRevealTranslationY = (int) (CLIP_REVEAL_TRANSLATION_Y_DP
318                 * mContext.getResources().getDisplayMetrics().density);
319         mGridLayoutRecentsEnabled = SystemProperties.getBoolean("ro.recents.grid", false);
320         mLowRamRecentsEnabled = ActivityManager.isLowRamDeviceStatic();
321 
322         final TypedArray windowStyle = mContext.getTheme().obtainStyledAttributes(
323                 com.android.internal.R.styleable.Window);
324         mDefaultWindowAnimationStyleResId = windowStyle.getResourceId(
325                 com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
326         windowStyle.recycle();
327     }
328 
isTransitionSet()329     boolean isTransitionSet() {
330         return !mNextAppTransitionRequests.isEmpty();
331     }
332 
isUnoccluding()333     boolean isUnoccluding() {
334         return mNextAppTransitionRequests.contains(TRANSIT_KEYGUARD_UNOCCLUDE);
335     }
336 
transferFrom(AppTransition other)337     boolean transferFrom(AppTransition other) {
338         mNextAppTransitionRequests.addAll(other.mNextAppTransitionRequests);
339         return prepare();
340     }
341 
setLastAppTransition(@ransitionOldType int transit, ActivityRecord openingApp, ActivityRecord closingApp, ActivityRecord changingApp)342     void setLastAppTransition(@TransitionOldType int transit, ActivityRecord openingApp,
343             ActivityRecord closingApp, ActivityRecord changingApp) {
344         mLastUsedAppTransition = transit;
345         mLastOpeningApp = "" + openingApp;
346         mLastClosingApp = "" + closingApp;
347         mLastChangingApp = "" + changingApp;
348     }
349 
isReady()350     boolean isReady() {
351         return mAppTransitionState == APP_STATE_READY
352                 || mAppTransitionState == APP_STATE_TIMEOUT;
353     }
354 
setReady()355     void setReady() {
356         setAppTransitionState(APP_STATE_READY);
357         fetchAppTransitionSpecsFromFuture();
358     }
359 
isRunning()360     boolean isRunning() {
361         return mAppTransitionState == APP_STATE_RUNNING;
362     }
363 
setIdle()364     void setIdle() {
365         setAppTransitionState(APP_STATE_IDLE);
366     }
367 
isTimeout()368     boolean isTimeout() {
369         return mAppTransitionState == APP_STATE_TIMEOUT;
370     }
371 
setTimeout()372     void setTimeout() {
373         setAppTransitionState(APP_STATE_TIMEOUT);
374     }
375 
getAppTransitionThumbnailHeader(WindowContainer container)376     HardwareBuffer getAppTransitionThumbnailHeader(WindowContainer container) {
377         AppTransitionAnimationSpec spec = mNextAppTransitionAnimationsSpecs.get(
378                 container.hashCode());
379         if (spec == null) {
380             spec = mDefaultNextAppTransitionAnimationSpec;
381         }
382         return spec != null ? spec.buffer : null;
383     }
384 
385     /** Returns whether the next thumbnail transition is aspect scaled up. */
isNextThumbnailTransitionAspectScaled()386     boolean isNextThumbnailTransitionAspectScaled() {
387         return mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP ||
388                 mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
389     }
390 
391     /** Returns whether the next thumbnail transition is scaling up. */
isNextThumbnailTransitionScaleUp()392     boolean isNextThumbnailTransitionScaleUp() {
393         return mNextAppTransitionScaleUp;
394     }
395 
isNextAppTransitionThumbnailUp()396     boolean isNextAppTransitionThumbnailUp() {
397         return mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP ||
398                 mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP;
399     }
400 
isNextAppTransitionThumbnailDown()401     boolean isNextAppTransitionThumbnailDown() {
402         return mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN ||
403                 mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
404     }
405 
isNextAppTransitionOpenCrossProfileApps()406     boolean isNextAppTransitionOpenCrossProfileApps() {
407         return mNextAppTransitionType == NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS;
408     }
409 
410     /**
411      * @return true if and only if we are currently fetching app transition specs from the future
412      *         passed into {@link #overridePendingAppTransitionMultiThumbFuture}
413      */
isFetchingAppTransitionsSpecs()414     boolean isFetchingAppTransitionsSpecs() {
415         return mNextAppTransitionAnimationsSpecsPending;
416     }
417 
prepare()418     private boolean prepare() {
419         if (!isRunning()) {
420             setAppTransitionState(APP_STATE_IDLE);
421             notifyAppTransitionPendingLocked();
422             mLastHadClipReveal = false;
423             mLastClipRevealMaxTranslation = 0;
424             mLastClipRevealTransitionDuration = DEFAULT_APP_TRANSITION_DURATION;
425             return true;
426         }
427         return false;
428     }
429 
430     /**
431      * @return bit-map of WindowManagerPolicy#FINISH_LAYOUT_REDO_* to indicate whether another
432      *         layout pass needs to be done
433      */
goodToGo(@ransitionOldType int transit, ActivityRecord topOpeningApp)434     int goodToGo(@TransitionOldType int transit, ActivityRecord topOpeningApp) {
435         mNextAppTransitionFlags = 0;
436         mNextAppTransitionRequests.clear();
437         setAppTransitionState(APP_STATE_RUNNING);
438         final WindowContainer wc =
439                 topOpeningApp != null ? topOpeningApp.getAnimatingContainer() : null;
440         final AnimationAdapter topOpeningAnim = wc != null ? wc.getAnimation() : null;
441 
442         int redoLayout = notifyAppTransitionStartingLocked(
443                 AppTransition.isKeyguardGoingAwayTransitOld(transit),
444                 topOpeningAnim != null ? topOpeningAnim.getDurationHint() : 0,
445                 topOpeningAnim != null
446                         ? topOpeningAnim.getStatusBarTransitionsStartTime()
447                         : SystemClock.uptimeMillis(),
448                 AnimationAdapter.STATUS_BAR_TRANSITION_DURATION);
449 
450         if (mRemoteAnimationController != null) {
451             mRemoteAnimationController.goodToGo(transit);
452         } else if ((isTaskOpenTransitOld(transit) || transit == TRANSIT_OLD_WALLPAPER_CLOSE)
453                 && topOpeningAnim != null) {
454             if (mDisplayContent.getDisplayPolicy().shouldAttachNavBarToAppDuringTransition()
455                     && mService.getRecentsAnimationController() == null) {
456                 final NavBarFadeAnimationController controller =
457                         new NavBarFadeAnimationController(mDisplayContent);
458                 // For remote animation case, the nav bar fades out and in is controlled by the
459                 // remote side. For non-remote animation case, we play the fade out/in animation
460                 // here. We play the nav bar fade-out animation when the app transition animation
461                 // starts and play the fade-in animation sequentially once the fade-out is finished.
462                 controller.fadeOutAndInSequentially(topOpeningAnim.getDurationHint(),
463                         null /* fadeOutParent */, topOpeningApp.getSurfaceControl());
464             }
465         }
466         return redoLayout;
467     }
468 
clear()469     void clear() {
470         mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE;
471         mNextAppTransitionOverrideRequested = false;
472         mNextAppTransitionPackage = null;
473         mNextAppTransitionAnimationsSpecs.clear();
474         mRemoteAnimationController = null;
475         mNextAppTransitionAnimationsSpecsFuture = null;
476         mDefaultNextAppTransitionAnimationSpec = null;
477         mAnimationFinishedCallback = null;
478     }
479 
freeze()480     void freeze() {
481         final boolean keyguardGoingAway = mNextAppTransitionRequests.contains(
482                 TRANSIT_KEYGUARD_GOING_AWAY);
483 
484         // The RemoteAnimationControl didn't register AppTransitionListener and
485         // only initialized the finish and timeout callback when goodToGo().
486         // So cancel the remote animation here to prevent the animation can't do
487         // finish after transition state cleared.
488         if (mRemoteAnimationController != null) {
489             mRemoteAnimationController.cancelAnimation("freeze");
490         }
491         mNextAppTransitionRequests.clear();
492         clear();
493         setReady();
494         notifyAppTransitionCancelledLocked(keyguardGoingAway);
495     }
496 
setAppTransitionState(int state)497     private void setAppTransitionState(int state) {
498         mAppTransitionState = state;
499         updateBooster();
500     }
501 
502     /**
503      * Updates whether we currently boost wm locked sections and the animation thread. We want to
504      * boost the priorities to a more important value whenever an app transition is going to happen
505      * soon or an app transition is running.
506      */
updateBooster()507     void updateBooster() {
508         WindowManagerService.sThreadPriorityBooster.setAppTransitionRunning(needsBoosting());
509     }
510 
needsBoosting()511     private boolean needsBoosting() {
512         final boolean recentsAnimRunning = mService.getRecentsAnimationController() != null;
513         return !mNextAppTransitionRequests.isEmpty()
514                 || mAppTransitionState == APP_STATE_READY
515                 || mAppTransitionState == APP_STATE_RUNNING
516                 || recentsAnimRunning;
517     }
518 
registerListenerLocked(AppTransitionListener listener)519     void registerListenerLocked(AppTransitionListener listener) {
520         mListeners.add(listener);
521     }
522 
unregisterListener(AppTransitionListener listener)523     void unregisterListener(AppTransitionListener listener) {
524         mListeners.remove(listener);
525     }
526 
registerKeygaurdExitAnimationStartListener( KeyguardExitAnimationStartListener listener)527     void registerKeygaurdExitAnimationStartListener(
528             KeyguardExitAnimationStartListener listener) {
529         mKeyguardExitAnimationStartListener = listener;
530     }
531 
notifyAppTransitionFinishedLocked(IBinder token)532     public void notifyAppTransitionFinishedLocked(IBinder token) {
533         for (int i = 0; i < mListeners.size(); i++) {
534             mListeners.get(i).onAppTransitionFinishedLocked(token);
535         }
536     }
537 
notifyAppTransitionPendingLocked()538     private void notifyAppTransitionPendingLocked() {
539         for (int i = 0; i < mListeners.size(); i++) {
540             mListeners.get(i).onAppTransitionPendingLocked();
541         }
542     }
543 
notifyAppTransitionCancelledLocked(boolean keyguardGoingAway)544     private void notifyAppTransitionCancelledLocked(boolean keyguardGoingAway) {
545         for (int i = 0; i < mListeners.size(); i++) {
546             mListeners.get(i).onAppTransitionCancelledLocked(keyguardGoingAway);
547         }
548     }
549 
notifyAppTransitionTimeoutLocked()550     private void notifyAppTransitionTimeoutLocked() {
551         for (int i = 0; i < mListeners.size(); i++) {
552             mListeners.get(i).onAppTransitionTimeoutLocked();
553         }
554     }
555 
notifyAppTransitionStartingLocked(boolean keyguardGoingAway, long duration, long statusBarAnimationStartTime, long statusBarAnimationDuration)556     private int notifyAppTransitionStartingLocked(boolean keyguardGoingAway, long duration,
557             long statusBarAnimationStartTime, long statusBarAnimationDuration) {
558         int redoLayout = 0;
559         for (int i = 0; i < mListeners.size(); i++) {
560             redoLayout |= mListeners.get(i).onAppTransitionStartingLocked(keyguardGoingAway,
561                     duration, statusBarAnimationStartTime, statusBarAnimationDuration);
562         }
563         return redoLayout;
564     }
565 
566     @VisibleForTesting
getDefaultWindowAnimationStyleResId()567     int getDefaultWindowAnimationStyleResId() {
568         return mDefaultWindowAnimationStyleResId;
569     }
570 
571     /** Returns window animation style ID from {@link LayoutParams} or from system in some cases */
572     @VisibleForTesting
getAnimationStyleResId(@onNull LayoutParams lp)573     int getAnimationStyleResId(@NonNull LayoutParams lp) {
574         return mTransitionAnimation.getAnimationStyleResId(lp);
575     }
576 
577     @VisibleForTesting
578     @Nullable
loadAnimationSafely(Context context, int resId)579     Animation loadAnimationSafely(Context context, int resId) {
580         return TransitionAnimation.loadAnimationSafely(context, resId, TAG);
581     }
582 
583     @Nullable
loadAnimationAttr(LayoutParams lp, int animAttr, int transit)584     Animation loadAnimationAttr(LayoutParams lp, int animAttr, int transit) {
585         return mTransitionAnimation.loadAnimationAttr(lp, animAttr, transit);
586     }
587 
getDefaultNextAppTransitionStartRect(Rect rect)588     private void getDefaultNextAppTransitionStartRect(Rect rect) {
589         if (mDefaultNextAppTransitionAnimationSpec == null ||
590                 mDefaultNextAppTransitionAnimationSpec.rect == null) {
591             Slog.e(TAG, "Starting rect for app requested, but none available", new Throwable());
592             rect.setEmpty();
593         } else {
594             rect.set(mDefaultNextAppTransitionAnimationSpec.rect);
595         }
596     }
597 
getNextAppTransitionStartRect(WindowContainer container, Rect rect)598     void getNextAppTransitionStartRect(WindowContainer container, Rect rect) {
599         AppTransitionAnimationSpec spec = mNextAppTransitionAnimationsSpecs.get(
600                 container.hashCode());
601         if (spec == null) {
602             spec = mDefaultNextAppTransitionAnimationSpec;
603         }
604         if (spec == null || spec.rect == null) {
605             Slog.e(TAG, "Starting rect for container: " + container
606                             + " requested, but not available", new Throwable());
607             rect.setEmpty();
608         } else {
609             rect.set(spec.rect);
610         }
611     }
612 
putDefaultNextAppTransitionCoordinates(int left, int top, int width, int height, HardwareBuffer buffer)613     private void putDefaultNextAppTransitionCoordinates(int left, int top, int width, int height,
614             HardwareBuffer buffer) {
615         mDefaultNextAppTransitionAnimationSpec = new AppTransitionAnimationSpec(-1 /* taskId */,
616                 buffer, new Rect(left, top, left + width, top + height));
617     }
618 
619     /**
620      * Calculates the duration for the clip reveal animation. If the clip is "cut off", meaning that
621      * the start rect is outside of the target rect, and there is a lot of movement going on.
622      *
623      * @param cutOff whether the start rect was not fully contained by the end rect
624      * @param translationX the total translation the surface moves in x direction
625      * @param translationY the total translation the surfaces moves in y direction
626      * @param displayFrame our display frame
627      *
628      * @return the duration of the clip reveal animation, in milliseconds
629      */
calculateClipRevealTransitionDuration(boolean cutOff, float translationX, float translationY, Rect displayFrame)630     private long calculateClipRevealTransitionDuration(boolean cutOff, float translationX,
631             float translationY, Rect displayFrame) {
632         if (!cutOff) {
633             return DEFAULT_APP_TRANSITION_DURATION;
634         }
635         final float fraction = Math.max(Math.abs(translationX) / displayFrame.width(),
636                 Math.abs(translationY) / displayFrame.height());
637         return (long) (DEFAULT_APP_TRANSITION_DURATION + fraction *
638                 (MAX_CLIP_REVEAL_TRANSITION_DURATION - DEFAULT_APP_TRANSITION_DURATION));
639     }
640 
641     /**
642      * Prepares the specified animation with a standard duration, interpolator, etc.
643      */
prepareThumbnailAnimationWithDuration(@ullable Animation a, int appWidth, int appHeight, long duration, Interpolator interpolator)644     Animation prepareThumbnailAnimationWithDuration(@Nullable Animation a, int appWidth,
645             int appHeight, long duration, Interpolator interpolator) {
646         if (a != null) {
647             if (duration > 0) {
648                 a.setDuration(duration);
649             }
650             a.setFillAfter(true);
651             if (interpolator != null) {
652                 a.setInterpolator(interpolator);
653             }
654             a.initialize(appWidth, appHeight, appWidth, appHeight);
655         }
656         return a;
657     }
658 
659     /**
660      * Prepares the specified animation with a standard duration, interpolator, etc.
661      */
prepareThumbnailAnimation(Animation a, int appWidth, int appHeight, int transit)662     Animation prepareThumbnailAnimation(Animation a, int appWidth, int appHeight, int transit) {
663         // Pick the desired duration.  If this is an inter-activity transition,
664         // it  is the standard duration for that.  Otherwise we use the longer
665         // task transition duration.
666         final int duration;
667         switch (transit) {
668             case TRANSIT_OLD_ACTIVITY_OPEN:
669             case TRANSIT_OLD_ACTIVITY_CLOSE:
670                 duration = mConfigShortAnimTime;
671                 break;
672             default:
673                 duration = DEFAULT_APP_TRANSITION_DURATION;
674                 break;
675         }
676         return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, duration,
677                 mDecelerateInterpolator);
678     }
679 
680     /**
681      * Return the current thumbnail transition state.
682      */
getThumbnailTransitionState(boolean enter)683     int getThumbnailTransitionState(boolean enter) {
684         if (enter) {
685             if (mNextAppTransitionScaleUp) {
686                 return THUMBNAIL_TRANSITION_ENTER_SCALE_UP;
687             } else {
688                 return THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN;
689             }
690         } else {
691             if (mNextAppTransitionScaleUp) {
692                 return THUMBNAIL_TRANSITION_EXIT_SCALE_UP;
693             } else {
694                 return THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN;
695             }
696         }
697     }
698 
699     /**
700      * Creates an overlay with a background color and a thumbnail for the cross profile apps
701      * animation.
702      */
createCrossProfileAppsThumbnail( @rawableRes int thumbnailDrawableRes, Rect frame)703     HardwareBuffer createCrossProfileAppsThumbnail(
704             @DrawableRes int thumbnailDrawableRes, Rect frame) {
705         final int width = frame.width();
706         final int height = frame.height();
707 
708         final Picture picture = new Picture();
709         final Canvas canvas = picture.beginRecording(width, height);
710         canvas.drawColor(Color.argb(0.6f, 0, 0, 0));
711         final int thumbnailSize = mService.mContext.getResources().getDimensionPixelSize(
712                 com.android.internal.R.dimen.cross_profile_apps_thumbnail_size);
713         final Drawable drawable = mService.mContext.getDrawable(thumbnailDrawableRes);
714         drawable.setBounds(
715                 (width - thumbnailSize) / 2,
716                 (height - thumbnailSize) / 2,
717                 (width + thumbnailSize) / 2,
718                 (height + thumbnailSize) / 2);
719         drawable.setTint(mContext.getColor(android.R.color.white));
720         drawable.draw(canvas);
721         picture.endRecording();
722 
723         return Bitmap.createBitmap(picture).getHardwareBuffer();
724     }
725 
createCrossProfileAppsThumbnailAnimationLocked(Rect appRect)726     Animation createCrossProfileAppsThumbnailAnimationLocked(Rect appRect) {
727         final Animation animation =
728                 mTransitionAnimation.loadCrossProfileAppThumbnailEnterAnimation();
729         return prepareThumbnailAnimationWithDuration(animation, appRect.width(),
730                 appRect.height(), 0, null);
731     }
732 
733     /**
734      * This animation runs for the thumbnail that gets cross faded with the enter/exit activity
735      * when a thumbnail is specified with the pending animation override.
736      */
createThumbnailAspectScaleAnimationLocked(Rect appRect, @Nullable Rect contentInsets, HardwareBuffer thumbnailHeader, WindowContainer container, int uiMode, int orientation)737     Animation createThumbnailAspectScaleAnimationLocked(Rect appRect, @Nullable Rect contentInsets,
738             HardwareBuffer thumbnailHeader, WindowContainer container, int uiMode,
739             int orientation) {
740         Animation a;
741         final int thumbWidthI = thumbnailHeader.getWidth();
742         final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
743         final int thumbHeightI = thumbnailHeader.getHeight();
744         final int appWidth = appRect.width();
745 
746         float scaleW = appWidth / thumbWidth;
747         getNextAppTransitionStartRect(container, mTmpRect);
748         final float fromX;
749         float fromY;
750         final float toX;
751         float toY;
752         final float pivotX;
753         final float pivotY;
754         if (shouldScaleDownThumbnailTransition(uiMode, orientation)) {
755             fromX = mTmpRect.left;
756             fromY = mTmpRect.top;
757 
758             // For the curved translate animation to work, the pivot points needs to be at the
759             // same absolute position as the one from the real surface.
760             toX = mTmpRect.width() / 2 * (scaleW - 1f) + appRect.left;
761             toY = appRect.height() / 2 * (1 - 1 / scaleW) + appRect.top;
762             pivotX = mTmpRect.width() / 2;
763             pivotY = appRect.height() / 2 / scaleW;
764             if (mGridLayoutRecentsEnabled) {
765                 // In the grid layout, the header is displayed above the thumbnail instead of
766                 // overlapping it.
767                 fromY -= thumbHeightI;
768                 toY -= thumbHeightI * scaleW;
769             }
770         } else {
771             pivotX = 0;
772             pivotY = 0;
773             fromX = mTmpRect.left;
774             fromY = mTmpRect.top;
775             toX = appRect.left;
776             toY = appRect.top;
777         }
778         final long duration = getAspectScaleDuration();
779         final Interpolator interpolator = getAspectScaleInterpolator();
780         if (mNextAppTransitionScaleUp) {
781             // Animation up from the thumbnail to the full screen
782             Animation scale = new ScaleAnimation(1f, scaleW, 1f, scaleW, pivotX, pivotY);
783             scale.setInterpolator(interpolator);
784             scale.setDuration(duration);
785             Animation alpha = new AlphaAnimation(1f, 0f);
786             alpha.setInterpolator(mThumbnailFadeOutInterpolator);
787             alpha.setDuration(duration);
788             Animation translate = createCurvedMotion(fromX, toX, fromY, toY);
789             translate.setInterpolator(interpolator);
790             translate.setDuration(duration);
791 
792             mTmpFromClipRect.set(0, 0, thumbWidthI, thumbHeightI);
793             mTmpToClipRect.set(appRect);
794 
795             // Containing frame is in screen space, but we need the clip rect in the
796             // app space.
797             mTmpToClipRect.offsetTo(0, 0);
798             mTmpToClipRect.right = (int) (mTmpToClipRect.right / scaleW);
799             mTmpToClipRect.bottom = (int) (mTmpToClipRect.bottom / scaleW);
800 
801             if (contentInsets != null) {
802                 mTmpToClipRect.inset((int) (-contentInsets.left * scaleW),
803                         (int) (-contentInsets.top * scaleW),
804                         (int) (-contentInsets.right * scaleW),
805                         (int) (-contentInsets.bottom * scaleW));
806             }
807 
808             Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
809             clipAnim.setInterpolator(interpolator);
810             clipAnim.setDuration(duration);
811 
812             // This AnimationSet uses the Interpolators assigned above.
813             AnimationSet set = new AnimationSet(false);
814             set.addAnimation(scale);
815             if (!mGridLayoutRecentsEnabled) {
816                 // In the grid layout, the header should be shown for the whole animation.
817                 set.addAnimation(alpha);
818             }
819             set.addAnimation(translate);
820             set.addAnimation(clipAnim);
821             a = set;
822         } else {
823             // Animation down from the full screen to the thumbnail
824             Animation scale = new ScaleAnimation(scaleW, 1f, scaleW, 1f, pivotX, pivotY);
825             scale.setInterpolator(interpolator);
826             scale.setDuration(duration);
827             Animation alpha = new AlphaAnimation(0f, 1f);
828             alpha.setInterpolator(mThumbnailFadeInInterpolator);
829             alpha.setDuration(duration);
830             Animation translate = createCurvedMotion(toX, fromX, toY, fromY);
831             translate.setInterpolator(interpolator);
832             translate.setDuration(duration);
833 
834             // This AnimationSet uses the Interpolators assigned above.
835             AnimationSet set = new AnimationSet(false);
836             set.addAnimation(scale);
837             if (!mGridLayoutRecentsEnabled) {
838                 // In the grid layout, the header should be shown for the whole animation.
839                 set.addAnimation(alpha);
840             }
841             set.addAnimation(translate);
842             a = set;
843 
844         }
845         return prepareThumbnailAnimationWithDuration(a, appWidth, appRect.height(), 0,
846                 null);
847     }
848 
createCurvedMotion(float fromX, float toX, float fromY, float toY)849     private Animation createCurvedMotion(float fromX, float toX, float fromY, float toY) {
850         return new TranslateAnimation(fromX, toX, fromY, toY);
851     }
852 
getAspectScaleDuration()853     private long getAspectScaleDuration() {
854         return THUMBNAIL_APP_TRANSITION_DURATION;
855     }
856 
getAspectScaleInterpolator()857     private Interpolator getAspectScaleInterpolator() {
858         return TOUCH_RESPONSE_INTERPOLATOR;
859     }
860 
createAspectScaledThumbnailEnterFreeformAnimationLocked(Rect frame, @Nullable Rect surfaceInsets, WindowContainer container)861     private Animation createAspectScaledThumbnailEnterFreeformAnimationLocked(Rect frame,
862             @Nullable Rect surfaceInsets, WindowContainer container) {
863         getNextAppTransitionStartRect(container, mTmpRect);
864         return createAspectScaledThumbnailFreeformAnimationLocked(mTmpRect, frame, surfaceInsets,
865                 true);
866     }
867 
createAspectScaledThumbnailExitFreeformAnimationLocked(Rect frame, @Nullable Rect surfaceInsets, WindowContainer container)868     private Animation createAspectScaledThumbnailExitFreeformAnimationLocked(Rect frame,
869             @Nullable Rect surfaceInsets, WindowContainer container) {
870         getNextAppTransitionStartRect(container, mTmpRect);
871         return createAspectScaledThumbnailFreeformAnimationLocked(frame, mTmpRect, surfaceInsets,
872                 false);
873     }
874 
createAspectScaledThumbnailFreeformAnimationLocked(Rect sourceFrame, Rect destFrame, @Nullable Rect surfaceInsets, boolean enter)875     private AnimationSet createAspectScaledThumbnailFreeformAnimationLocked(Rect sourceFrame,
876             Rect destFrame, @Nullable Rect surfaceInsets, boolean enter) {
877         final float sourceWidth = sourceFrame.width();
878         final float sourceHeight = sourceFrame.height();
879         final float destWidth = destFrame.width();
880         final float destHeight = destFrame.height();
881         final float scaleH = enter ? sourceWidth / destWidth : destWidth / sourceWidth;
882         final float scaleV = enter ? sourceHeight / destHeight : destHeight / sourceHeight;
883         AnimationSet set = new AnimationSet(true);
884         final int surfaceInsetsH = surfaceInsets == null
885                 ? 0 : surfaceInsets.left + surfaceInsets.right;
886         final int surfaceInsetsV = surfaceInsets == null
887                 ? 0 : surfaceInsets.top + surfaceInsets.bottom;
888         // We want the scaling to happen from the center of the surface. In order to achieve that,
889         // we need to account for surface insets that will be used to enlarge the surface.
890         final float scaleHCenter = ((enter ? destWidth : sourceWidth) + surfaceInsetsH) / 2;
891         final float scaleVCenter = ((enter ? destHeight : sourceHeight) + surfaceInsetsV) / 2;
892         final ScaleAnimation scale = enter ?
893                 new ScaleAnimation(scaleH, 1, scaleV, 1, scaleHCenter, scaleVCenter)
894                 : new ScaleAnimation(1, scaleH, 1, scaleV, scaleHCenter, scaleVCenter);
895         final int sourceHCenter = sourceFrame.left + sourceFrame.width() / 2;
896         final int sourceVCenter = sourceFrame.top + sourceFrame.height() / 2;
897         final int destHCenter = destFrame.left + destFrame.width() / 2;
898         final int destVCenter = destFrame.top + destFrame.height() / 2;
899         final int fromX = enter ? sourceHCenter - destHCenter : destHCenter - sourceHCenter;
900         final int fromY = enter ? sourceVCenter - destVCenter : destVCenter - sourceVCenter;
901         final TranslateAnimation translation = enter ? new TranslateAnimation(fromX, 0, fromY, 0)
902                 : new TranslateAnimation(0, fromX, 0, fromY);
903         set.addAnimation(scale);
904         set.addAnimation(translation);
905         setAppTransitionFinishedCallbackIfNeeded(set);
906         return set;
907     }
908 
909     /**
910      * This animation runs for the thumbnail that gets cross faded with the enter/exit activity
911      * when a thumbnail is specified with the pending animation override.
912      */
createThumbnailScaleAnimationLocked(int appWidth, int appHeight, int transit, HardwareBuffer thumbnailHeader)913     Animation createThumbnailScaleAnimationLocked(int appWidth, int appHeight, int transit,
914             HardwareBuffer thumbnailHeader) {
915         Animation a;
916         getDefaultNextAppTransitionStartRect(mTmpRect);
917         final int thumbWidthI = thumbnailHeader.getWidth();
918         final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
919         final int thumbHeightI = thumbnailHeader.getHeight();
920         final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
921 
922         if (mNextAppTransitionScaleUp) {
923             // Animation for the thumbnail zooming from its initial size to the full screen
924             float scaleW = appWidth / thumbWidth;
925             float scaleH = appHeight / thumbHeight;
926             Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
927                     TransitionAnimation.computePivot(mTmpRect.left, 1 / scaleW),
928                     TransitionAnimation.computePivot(mTmpRect.top, 1 / scaleH));
929             scale.setInterpolator(mDecelerateInterpolator);
930 
931             Animation alpha = new AlphaAnimation(1, 0);
932             alpha.setInterpolator(mThumbnailFadeOutInterpolator);
933 
934             // This AnimationSet uses the Interpolators assigned above.
935             AnimationSet set = new AnimationSet(false);
936             set.addAnimation(scale);
937             set.addAnimation(alpha);
938             a = set;
939         } else {
940             // Animation for the thumbnail zooming down from the full screen to its final size
941             float scaleW = appWidth / thumbWidth;
942             float scaleH = appHeight / thumbHeight;
943             a = new ScaleAnimation(scaleW, 1, scaleH, 1,
944                     TransitionAnimation.computePivot(mTmpRect.left, 1 / scaleW),
945                     TransitionAnimation.computePivot(mTmpRect.top, 1 / scaleH));
946         }
947 
948         return prepareThumbnailAnimation(a, appWidth, appHeight, transit);
949     }
950 
951     /**
952      * @return true if and only if the first frame of the transition can be skipped, i.e. the first
953      *         frame of the transition doesn't change the visuals on screen, so we can start
954      *         directly with the second one
955      */
canSkipFirstFrame()956     boolean canSkipFirstFrame() {
957         return mNextAppTransitionType != NEXT_TRANSIT_TYPE_CUSTOM
958                 && !mNextAppTransitionOverrideRequested
959                 && mNextAppTransitionType != NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE
960                 && mNextAppTransitionType != NEXT_TRANSIT_TYPE_CLIP_REVEAL
961                 && !mNextAppTransitionRequests.contains(TRANSIT_KEYGUARD_GOING_AWAY);
962     }
963 
getRemoteAnimationController()964     RemoteAnimationController getRemoteAnimationController() {
965         return mRemoteAnimationController;
966     }
967 
968     /**
969      *
970      * @param frame These are the bounds of the window when it finishes the animation. This is where
971      *              the animation must usually finish in entrance animation, as the next frame will
972      *              display the window at these coordinates. In case of exit animation, this is
973      *              where the animation must start, as the frame before the animation is displaying
974      *              the window at these bounds.
975      * @param insets Knowing where the window will be positioned is not enough. Some parts of the
976      *               window might be obscured, usually by the system windows (status bar and
977      *               navigation bar) and we use content insets to convey that information. This
978      *               usually affects the animation aspects vertically, as the system decoration is
979      *               at the top and the bottom. For example when we animate from full screen to
980      *               recents, we want to exclude the covered parts, because they won't match the
981      *               thumbnail after the last frame is executed.
982      * @param surfaceInsets In rare situation the surface is larger than the content and we need to
983      *                      know about this to make the animation frames match. We currently use
984      *                      this for freeform windows, which have larger surfaces to display
985      *                      shadows. When we animate them from recents, we want to match the content
986      *                      to the recents thumbnail and hence need to account for the surface being
987      *                      bigger.
988      */
989     @Nullable
loadAnimation(LayoutParams lp, int transit, boolean enter, int uiMode, int orientation, Rect frame, Rect displayFrame, Rect insets, @Nullable Rect surfaceInsets, @Nullable Rect stableInsets, boolean isVoiceInteraction, boolean freeform, WindowContainer container)990     Animation loadAnimation(LayoutParams lp, int transit, boolean enter, int uiMode,
991             int orientation, Rect frame, Rect displayFrame, Rect insets,
992             @Nullable Rect surfaceInsets, @Nullable Rect stableInsets, boolean isVoiceInteraction,
993             boolean freeform, WindowContainer container) {
994 
995         if (mNextAppTransitionOverrideRequested
996                 && (container.canCustomizeAppTransition() || mOverrideTaskTransition)) {
997             mNextAppTransitionType = NEXT_TRANSIT_TYPE_CUSTOM;
998         }
999 
1000         Animation a;
1001         if (isKeyguardGoingAwayTransitOld(transit) && enter) {
1002             a = mTransitionAnimation.loadKeyguardExitAnimation(mNextAppTransitionFlags,
1003                     transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER);
1004         } else if (transit == TRANSIT_OLD_KEYGUARD_OCCLUDE) {
1005             a = null;
1006         } else if (transit == TRANSIT_OLD_KEYGUARD_UNOCCLUDE && !enter) {
1007             a = mTransitionAnimation.loadKeyguardUnoccludeAnimation();
1008         } else if (transit == TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE) {
1009             a = null;
1010         } else if (isVoiceInteraction && (transit == TRANSIT_OLD_ACTIVITY_OPEN
1011                 || transit == TRANSIT_OLD_TASK_OPEN
1012                 || transit == TRANSIT_OLD_TASK_TO_FRONT)) {
1013             a = mTransitionAnimation.loadVoiceActivityOpenAnimation(enter);
1014             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
1015                     "applyAnimation voice: anim=%s transit=%s isEntrance=%b Callers=%s", a,
1016                     appTransitionOldToString(transit), enter, Debug.getCallers(3));
1017         } else if (isVoiceInteraction && (transit == TRANSIT_OLD_ACTIVITY_CLOSE
1018                 || transit == TRANSIT_OLD_TASK_CLOSE
1019                 || transit == TRANSIT_OLD_TASK_TO_BACK)) {
1020             a = mTransitionAnimation.loadVoiceActivityExitAnimation(enter);
1021             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
1022                     "applyAnimation voice: anim=%s transit=%s isEntrance=%b Callers=%s", a,
1023                     appTransitionOldToString(transit), enter, Debug.getCallers(3));
1024         } else if (transit == TRANSIT_OLD_ACTIVITY_RELAUNCH) {
1025             a = mTransitionAnimation.createRelaunchAnimation(frame, insets,
1026                     mDefaultNextAppTransitionAnimationSpec != null
1027                             ? mDefaultNextAppTransitionAnimationSpec.rect : null);
1028             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
1029                     "applyAnimation: anim=%s transit=%s Callers=%s", a,
1030                     appTransitionOldToString(transit), Debug.getCallers(3));
1031         } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) {
1032             a = mTransitionAnimation.loadAppTransitionAnimation(mNextAppTransitionPackage,
1033                     enter ? mNextAppTransitionEnter : mNextAppTransitionExit);
1034             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
1035                     "applyAnimation: anim=%s nextAppTransition=ANIM_CUSTOM transit=%s "
1036                             + "isEntrance=%b Callers=%s",
1037                     a, appTransitionOldToString(transit), enter, Debug.getCallers(3));
1038         } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE) {
1039             a = mTransitionAnimation.loadAppTransitionAnimation(
1040                     mNextAppTransitionPackage, mNextAppTransitionInPlace);
1041             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
1042                     "applyAnimation: anim=%s nextAppTransition=ANIM_CUSTOM_IN_PLACE "
1043                             + "transit=%s Callers=%s",
1044                     a, appTransitionOldToString(transit), Debug.getCallers(3));
1045         } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CLIP_REVEAL) {
1046             a = mTransitionAnimation.createClipRevealAnimationLocked(
1047                     transit, enter, frame, displayFrame,
1048                     mDefaultNextAppTransitionAnimationSpec != null
1049                             ? mDefaultNextAppTransitionAnimationSpec.rect : null);
1050             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
1051                     "applyAnimation: anim=%s nextAppTransition=ANIM_CLIP_REVEAL "
1052                             + "transit=%s Callers=%s",
1053                     a, appTransitionOldToString(transit), Debug.getCallers(3));
1054         } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_SCALE_UP) {
1055             a = mTransitionAnimation.createScaleUpAnimationLocked(transit, enter, frame,
1056                     mDefaultNextAppTransitionAnimationSpec != null
1057                             ? mDefaultNextAppTransitionAnimationSpec.rect : null);
1058             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
1059                     "applyAnimation: anim=%s nextAppTransition=ANIM_SCALE_UP transit=%s "
1060                             + "isEntrance=%s Callers=%s",
1061                     a, appTransitionOldToString(transit), enter, Debug.getCallers(3));
1062         } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP ||
1063                 mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN) {
1064             mNextAppTransitionScaleUp =
1065                     (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP);
1066             final HardwareBuffer thumbnailHeader = getAppTransitionThumbnailHeader(container);
1067             a = mTransitionAnimation.createThumbnailEnterExitAnimationLocked(
1068                     getThumbnailTransitionState(enter), frame, transit, thumbnailHeader,
1069                     mDefaultNextAppTransitionAnimationSpec != null
1070                             ? mDefaultNextAppTransitionAnimationSpec.rect : null);
1071             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
1072                     "applyAnimation: anim=%s nextAppTransition=%s transit=%s isEntrance=%b "
1073                             + "Callers=%s",
1074                     a,  mNextAppTransitionScaleUp
1075                             ? "ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN",
1076                     appTransitionOldToString(transit), enter, Debug.getCallers(3));
1077         } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP ||
1078                 mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN) {
1079             mNextAppTransitionScaleUp =
1080                     (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP);
1081             AppTransitionAnimationSpec spec = mNextAppTransitionAnimationsSpecs.get(
1082                     container.hashCode());
1083             a = mTransitionAnimation.createAspectScaledThumbnailEnterExitAnimationLocked(
1084                     getThumbnailTransitionState(enter), orientation, transit, frame,
1085                     insets, surfaceInsets, stableInsets, freeform, spec != null ? spec.rect : null,
1086                     mDefaultNextAppTransitionAnimationSpec != null
1087                             ? mDefaultNextAppTransitionAnimationSpec.rect : null);
1088             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
1089                     "applyAnimation: anim=%s nextAppTransition=%s transit=%s isEntrance=%b "
1090                             + "Callers=%s",
1091                     a, mNextAppTransitionScaleUp
1092                             ? "ANIM_THUMBNAIL_ASPECT_SCALE_UP"
1093                         : "ANIM_THUMBNAIL_ASPECT_SCALE_DOWN",
1094                     appTransitionOldToString(transit), enter, Debug.getCallers(3));
1095         } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS && enter) {
1096             a = mTransitionAnimation.loadCrossProfileAppEnterAnimation();
1097             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
1098                     "applyAnimation NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS: "
1099                             + "anim=%s transit=%s isEntrance=true Callers=%s",
1100                     a, appTransitionOldToString(transit), Debug.getCallers(3));
1101         } else if (transit == TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE) {
1102             // In the absence of a specific adapter, we just want to keep everything stationary.
1103             a = new AlphaAnimation(1.f, 1.f);
1104             a.setDuration(WindowChangeAnimationSpec.ANIMATION_DURATION);
1105             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
1106                     "applyAnimation: anim=%s transit=%s isEntrance=%b Callers=%s",
1107                     a, appTransitionOldToString(transit), enter, Debug.getCallers(3));
1108         } else {
1109             int animAttr = 0;
1110             switch (transit) {
1111                 case TRANSIT_OLD_ACTIVITY_OPEN:
1112                 case TRANSIT_OLD_TRANSLUCENT_ACTIVITY_OPEN:
1113                     animAttr = enter
1114                             ? WindowAnimation_activityOpenEnterAnimation
1115                             : WindowAnimation_activityOpenExitAnimation;
1116                     break;
1117                 case TRANSIT_OLD_ACTIVITY_CLOSE:
1118                 case TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE:
1119                     animAttr = enter
1120                             ? WindowAnimation_activityCloseEnterAnimation
1121                             : WindowAnimation_activityCloseExitAnimation;
1122                     break;
1123                 case TRANSIT_OLD_TASK_OPEN:
1124                     animAttr = enter
1125                             ? WindowAnimation_taskOpenEnterAnimation
1126                             : WindowAnimation_taskOpenExitAnimation;
1127                     break;
1128                 case TRANSIT_OLD_TASK_CLOSE:
1129                     animAttr = enter
1130                             ? WindowAnimation_taskCloseEnterAnimation
1131                             : WindowAnimation_taskCloseExitAnimation;
1132                     break;
1133                 case TRANSIT_OLD_TASK_TO_FRONT:
1134                     animAttr = enter
1135                             ? WindowAnimation_taskToFrontEnterAnimation
1136                             : WindowAnimation_taskToFrontExitAnimation;
1137                     break;
1138                 case TRANSIT_OLD_TASK_TO_BACK:
1139                     animAttr = enter
1140                             ? WindowAnimation_taskToBackEnterAnimation
1141                             : WindowAnimation_taskToBackExitAnimation;
1142                     break;
1143                 case TRANSIT_OLD_WALLPAPER_OPEN:
1144                     animAttr = enter
1145                             ? WindowAnimation_wallpaperOpenEnterAnimation
1146                             : WindowAnimation_wallpaperOpenExitAnimation;
1147                     break;
1148                 case TRANSIT_OLD_WALLPAPER_CLOSE:
1149                     animAttr = enter
1150                             ? WindowAnimation_wallpaperCloseEnterAnimation
1151                             : WindowAnimation_wallpaperCloseExitAnimation;
1152                     break;
1153                 case TRANSIT_OLD_WALLPAPER_INTRA_OPEN:
1154                     animAttr = enter
1155                             ? WindowAnimation_wallpaperIntraOpenEnterAnimation
1156                             : WindowAnimation_wallpaperIntraOpenExitAnimation;
1157                     break;
1158                 case TRANSIT_OLD_WALLPAPER_INTRA_CLOSE:
1159                     animAttr = enter
1160                             ? WindowAnimation_wallpaperIntraCloseEnterAnimation
1161                             : WindowAnimation_wallpaperIntraCloseExitAnimation;
1162                     break;
1163                 case TRANSIT_OLD_TASK_OPEN_BEHIND:
1164                     animAttr = enter
1165                             ? WindowAnimation_launchTaskBehindSourceAnimation
1166                             : WindowAnimation_launchTaskBehindTargetAnimation;
1167             }
1168             a = animAttr != 0 ? loadAnimationAttr(lp, animAttr, transit) : null;
1169             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
1170                     "applyAnimation: anim=%s animAttr=0x%x transit=%s isEntrance=%b "
1171                             + "Callers=%s",
1172                     a, animAttr, appTransitionOldToString(transit), enter,
1173                     Debug.getCallers(3));
1174         }
1175         setAppTransitionFinishedCallbackIfNeeded(a);
1176         return a;
1177     }
1178 
getAppRootTaskClipMode()1179     int getAppRootTaskClipMode() {
1180         return mNextAppTransitionRequests.contains(TRANSIT_RELAUNCH)
1181                 || mNextAppTransitionRequests.contains(TRANSIT_KEYGUARD_GOING_AWAY)
1182                 || mNextAppTransitionType == NEXT_TRANSIT_TYPE_CLIP_REVEAL
1183                 ? ROOT_TASK_CLIP_NONE
1184                 : ROOT_TASK_CLIP_AFTER_ANIM;
1185     }
1186 
1187     @TransitionFlags
getTransitFlags()1188     public int getTransitFlags() {
1189         return mNextAppTransitionFlags;
1190     }
1191 
postAnimationCallback()1192     void postAnimationCallback() {
1193         if (mNextAppTransitionCallback != null) {
1194             mHandler.sendMessage(PooledLambda.obtainMessage(AppTransition::doAnimationCallback,
1195                     mNextAppTransitionCallback));
1196             mNextAppTransitionCallback = null;
1197         }
1198     }
1199 
overridePendingAppTransition(String packageName, int enterAnim, int exitAnim, IRemoteCallback startedCallback, IRemoteCallback endedCallback, boolean overrideTaskTransaction)1200     void overridePendingAppTransition(String packageName, int enterAnim, int exitAnim,
1201             IRemoteCallback startedCallback, IRemoteCallback endedCallback,
1202             boolean overrideTaskTransaction) {
1203         if (canOverridePendingAppTransition()) {
1204             clear();
1205             mNextAppTransitionOverrideRequested = true;
1206             mNextAppTransitionPackage = packageName;
1207             mNextAppTransitionEnter = enterAnim;
1208             mNextAppTransitionExit = exitAnim;
1209             postAnimationCallback();
1210             mNextAppTransitionCallback = startedCallback;
1211             mAnimationFinishedCallback = endedCallback;
1212             mOverrideTaskTransition = overrideTaskTransaction;
1213         }
1214     }
1215 
overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth, int startHeight)1216     void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
1217             int startHeight) {
1218         if (canOverridePendingAppTransition()) {
1219             clear();
1220             mNextAppTransitionType = NEXT_TRANSIT_TYPE_SCALE_UP;
1221             putDefaultNextAppTransitionCoordinates(startX, startY, startWidth, startHeight, null);
1222             postAnimationCallback();
1223         }
1224     }
1225 
overridePendingAppTransitionClipReveal(int startX, int startY, int startWidth, int startHeight)1226     void overridePendingAppTransitionClipReveal(int startX, int startY,
1227                                                 int startWidth, int startHeight) {
1228         if (canOverridePendingAppTransition()) {
1229             clear();
1230             mNextAppTransitionType = NEXT_TRANSIT_TYPE_CLIP_REVEAL;
1231             putDefaultNextAppTransitionCoordinates(startX, startY, startWidth, startHeight, null);
1232             postAnimationCallback();
1233         }
1234     }
1235 
overridePendingAppTransitionThumb(HardwareBuffer srcThumb, int startX, int startY, IRemoteCallback startedCallback, boolean scaleUp)1236     void overridePendingAppTransitionThumb(HardwareBuffer srcThumb, int startX, int startY,
1237                                            IRemoteCallback startedCallback, boolean scaleUp) {
1238         if (canOverridePendingAppTransition()) {
1239             clear();
1240             mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP
1241                     : NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN;
1242             mNextAppTransitionScaleUp = scaleUp;
1243             putDefaultNextAppTransitionCoordinates(startX, startY, 0, 0, srcThumb);
1244             postAnimationCallback();
1245             mNextAppTransitionCallback = startedCallback;
1246         }
1247     }
1248 
overridePendingAppTransitionAspectScaledThumb(HardwareBuffer srcThumb, int startX, int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback, boolean scaleUp)1249     void overridePendingAppTransitionAspectScaledThumb(HardwareBuffer srcThumb, int startX,
1250             int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback,
1251             boolean scaleUp) {
1252         if (canOverridePendingAppTransition()) {
1253             clear();
1254             mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP
1255                     : NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
1256             mNextAppTransitionScaleUp = scaleUp;
1257             putDefaultNextAppTransitionCoordinates(startX, startY, targetWidth, targetHeight,
1258                     srcThumb);
1259             postAnimationCallback();
1260             mNextAppTransitionCallback = startedCallback;
1261         }
1262     }
1263 
overridePendingAppTransitionMultiThumb(AppTransitionAnimationSpec[] specs, IRemoteCallback onAnimationStartedCallback, IRemoteCallback onAnimationFinishedCallback, boolean scaleUp)1264     void overridePendingAppTransitionMultiThumb(AppTransitionAnimationSpec[] specs,
1265             IRemoteCallback onAnimationStartedCallback, IRemoteCallback onAnimationFinishedCallback,
1266             boolean scaleUp) {
1267         if (canOverridePendingAppTransition()) {
1268             clear();
1269             mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP
1270                     : NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
1271             mNextAppTransitionScaleUp = scaleUp;
1272             if (specs != null) {
1273                 for (int i = 0; i < specs.length; i++) {
1274                     AppTransitionAnimationSpec spec = specs[i];
1275                     if (spec != null) {
1276                         final PooledPredicate p = PooledLambda.obtainPredicate(
1277                                 Task::isTaskId, PooledLambda.__(Task.class), spec.taskId);
1278                         final WindowContainer container = mDisplayContent.getTask(p);
1279                         p.recycle();
1280                         if (container == null) {
1281                             continue;
1282                         }
1283                         mNextAppTransitionAnimationsSpecs.put(container.hashCode(), spec);
1284                         if (i == 0) {
1285                             // In full screen mode, the transition code depends on the default spec
1286                             // to be set.
1287                             Rect rect = spec.rect;
1288                             putDefaultNextAppTransitionCoordinates(rect.left, rect.top,
1289                                     rect.width(), rect.height(), spec.buffer);
1290                         }
1291                     }
1292                 }
1293             }
1294             postAnimationCallback();
1295             mNextAppTransitionCallback = onAnimationStartedCallback;
1296             mAnimationFinishedCallback = onAnimationFinishedCallback;
1297         }
1298     }
1299 
overridePendingAppTransitionMultiThumbFuture( IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback callback, boolean scaleUp)1300     void overridePendingAppTransitionMultiThumbFuture(
1301             IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback callback,
1302             boolean scaleUp) {
1303         if (canOverridePendingAppTransition()) {
1304             clear();
1305             mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP
1306                     : NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
1307             mNextAppTransitionAnimationsSpecsFuture = specsFuture;
1308             mNextAppTransitionScaleUp = scaleUp;
1309             mNextAppTransitionFutureCallback = callback;
1310             if (isReady()) {
1311                 fetchAppTransitionSpecsFromFuture();
1312             }
1313         }
1314     }
1315 
overridePendingAppTransitionRemote(RemoteAnimationAdapter remoteAnimationAdapter)1316     void overridePendingAppTransitionRemote(RemoteAnimationAdapter remoteAnimationAdapter) {
1317         ProtoLog.i(WM_DEBUG_APP_TRANSITIONS, "Override pending remote transitionSet=%b adapter=%s",
1318                         isTransitionSet(), remoteAnimationAdapter);
1319         if (isTransitionSet()) {
1320             clear();
1321             mNextAppTransitionType = NEXT_TRANSIT_TYPE_REMOTE;
1322             mRemoteAnimationController = new RemoteAnimationController(mService, mDisplayContent,
1323                     remoteAnimationAdapter, mHandler);
1324         }
1325     }
1326 
overrideInPlaceAppTransition(String packageName, int anim)1327     void overrideInPlaceAppTransition(String packageName, int anim) {
1328         if (canOverridePendingAppTransition()) {
1329             clear();
1330             mNextAppTransitionType = NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE;
1331             mNextAppTransitionPackage = packageName;
1332             mNextAppTransitionInPlace = anim;
1333         }
1334     }
1335 
1336     /**
1337      * @see {@link #NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS}
1338      */
overridePendingAppTransitionStartCrossProfileApps()1339     void overridePendingAppTransitionStartCrossProfileApps() {
1340         if (canOverridePendingAppTransition()) {
1341             clear();
1342             mNextAppTransitionType = NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS;
1343             postAnimationCallback();
1344         }
1345     }
1346 
canOverridePendingAppTransition()1347     private boolean canOverridePendingAppTransition() {
1348         // Remote animations always take precedence
1349         return isTransitionSet() &&  mNextAppTransitionType != NEXT_TRANSIT_TYPE_REMOTE;
1350     }
1351 
1352     /**
1353      * If a future is set for the app transition specs, fetch it in another thread.
1354      */
fetchAppTransitionSpecsFromFuture()1355     private void fetchAppTransitionSpecsFromFuture() {
1356         if (mNextAppTransitionAnimationsSpecsFuture != null) {
1357             mNextAppTransitionAnimationsSpecsPending = true;
1358             final IAppTransitionAnimationSpecsFuture future
1359                     = mNextAppTransitionAnimationsSpecsFuture;
1360             mNextAppTransitionAnimationsSpecsFuture = null;
1361             mDefaultExecutor.execute(() -> {
1362                 AppTransitionAnimationSpec[] specs = null;
1363                 try {
1364                     Binder.allowBlocking(future.asBinder());
1365                     specs = future.get();
1366                 } catch (RemoteException e) {
1367                     Slog.w(TAG, "Failed to fetch app transition specs: " + e);
1368                 }
1369                 synchronized (mService.mGlobalLock) {
1370                     mNextAppTransitionAnimationsSpecsPending = false;
1371                     overridePendingAppTransitionMultiThumb(specs,
1372                             mNextAppTransitionFutureCallback, null /* finishedCallback */,
1373                             mNextAppTransitionScaleUp);
1374                     mNextAppTransitionFutureCallback = null;
1375                     mService.requestTraversal();
1376                 }
1377             });
1378         }
1379     }
1380 
1381     @Override
toString()1382     public String toString() {
1383         StringBuilder sb = new StringBuilder();
1384         sb.append("mNextAppTransitionRequests=[");
1385 
1386         boolean separator = false;
1387         for (Integer transit : mNextAppTransitionRequests) {
1388             if (separator) {
1389                 sb.append(", ");
1390             }
1391             sb.append(appTransitionToString(transit));
1392             separator = true;
1393         }
1394         sb.append("]");
1395         sb.append(", mNextAppTransitionFlags="
1396                 + appTransitionFlagsToString(mNextAppTransitionFlags));
1397         return sb.toString();
1398     }
1399 
1400     /**
1401      * Returns the human readable name of a old window transition.
1402      *
1403      * @param transition The old window transition.
1404      * @return The transition symbolic name.
1405      */
appTransitionOldToString(@ransitionOldType int transition)1406     public static String appTransitionOldToString(@TransitionOldType int transition) {
1407         switch (transition) {
1408             case TRANSIT_OLD_UNSET: {
1409                 return "TRANSIT_OLD_UNSET";
1410             }
1411             case TRANSIT_OLD_NONE: {
1412                 return "TRANSIT_OLD_NONE";
1413             }
1414             case TRANSIT_OLD_ACTIVITY_OPEN: {
1415                 return "TRANSIT_OLD_ACTIVITY_OPEN";
1416             }
1417             case TRANSIT_OLD_ACTIVITY_CLOSE: {
1418                 return "TRANSIT_OLD_ACTIVITY_CLOSE";
1419             }
1420             case TRANSIT_OLD_TASK_OPEN: {
1421                 return "TRANSIT_OLD_TASK_OPEN";
1422             }
1423             case TRANSIT_OLD_TASK_CLOSE: {
1424                 return "TRANSIT_OLD_TASK_CLOSE";
1425             }
1426             case TRANSIT_OLD_TASK_TO_FRONT: {
1427                 return "TRANSIT_OLD_TASK_TO_FRONT";
1428             }
1429             case TRANSIT_OLD_TASK_TO_BACK: {
1430                 return "TRANSIT_OLD_TASK_TO_BACK";
1431             }
1432             case TRANSIT_OLD_WALLPAPER_CLOSE: {
1433                 return "TRANSIT_OLD_WALLPAPER_CLOSE";
1434             }
1435             case TRANSIT_OLD_WALLPAPER_OPEN: {
1436                 return "TRANSIT_OLD_WALLPAPER_OPEN";
1437             }
1438             case TRANSIT_OLD_WALLPAPER_INTRA_OPEN: {
1439                 return "TRANSIT_OLD_WALLPAPER_INTRA_OPEN";
1440             }
1441             case TRANSIT_OLD_WALLPAPER_INTRA_CLOSE: {
1442                 return "TRANSIT_OLD_WALLPAPER_INTRA_CLOSE";
1443             }
1444             case TRANSIT_OLD_TASK_OPEN_BEHIND: {
1445                 return "TRANSIT_OLD_TASK_OPEN_BEHIND";
1446             }
1447             case TRANSIT_OLD_ACTIVITY_RELAUNCH: {
1448                 return "TRANSIT_OLD_ACTIVITY_RELAUNCH";
1449             }
1450             case TRANSIT_OLD_KEYGUARD_GOING_AWAY: {
1451                 return "TRANSIT_OLD_KEYGUARD_GOING_AWAY";
1452             }
1453             case TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER: {
1454                 return "TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER";
1455             }
1456             case TRANSIT_OLD_KEYGUARD_OCCLUDE: {
1457                 return "TRANSIT_OLD_KEYGUARD_OCCLUDE";
1458             }
1459             case TRANSIT_OLD_KEYGUARD_UNOCCLUDE: {
1460                 return "TRANSIT_OLD_KEYGUARD_UNOCCLUDE";
1461             }
1462             case TRANSIT_OLD_TRANSLUCENT_ACTIVITY_OPEN: {
1463                 return "TRANSIT_OLD_TRANSLUCENT_ACTIVITY_OPEN";
1464             }
1465             case TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE: {
1466                 return "TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE";
1467             }
1468             case TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE: {
1469                 return "TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE";
1470             }
1471             default: {
1472                 return "<UNKNOWN: " + transition + ">";
1473             }
1474         }
1475     }
1476 
1477     /**
1478      * Returns the human readable name of a window transition.
1479      *
1480      * @param transition The window transition.
1481      * @return The transition symbolic name.
1482      */
appTransitionToString(@ransitionType int transition)1483     public static String appTransitionToString(@TransitionType int transition) {
1484         switch (transition) {
1485             case TRANSIT_NONE: {
1486                 return "TRANSIT_NONE";
1487             }
1488             case TRANSIT_OPEN: {
1489                 return "TRANSIT_OPEN";
1490             }
1491             case TRANSIT_CLOSE: {
1492                 return "TRANSIT_CLOSE";
1493             }
1494             case TRANSIT_TO_FRONT: {
1495                 return "TRANSIT_TO_FRONT";
1496             }
1497             case TRANSIT_TO_BACK: {
1498                 return "TRANSIT_TO_BACK";
1499             }
1500             case TRANSIT_RELAUNCH: {
1501                 return "TRANSIT_RELAUNCH";
1502             }
1503             case TRANSIT_CHANGE: {
1504                 return "TRANSIT_CHANGE";
1505             }
1506             case TRANSIT_KEYGUARD_GOING_AWAY: {
1507                 return "TRANSIT_KEYGUARD_GOING_AWAY";
1508             }
1509             case TRANSIT_KEYGUARD_OCCLUDE: {
1510                 return "TRANSIT_KEYGUARD_OCCLUDE";
1511             }
1512             case TRANSIT_KEYGUARD_UNOCCLUDE: {
1513                 return "TRANSIT_KEYGUARD_UNOCCLUDE";
1514             }
1515             default: {
1516                 return "<UNKNOWN: " + transition + ">";
1517             }
1518         }
1519     }
1520 
appStateToString()1521     private String appStateToString() {
1522         switch (mAppTransitionState) {
1523             case APP_STATE_IDLE:
1524                 return "APP_STATE_IDLE";
1525             case APP_STATE_READY:
1526                 return "APP_STATE_READY";
1527             case APP_STATE_RUNNING:
1528                 return "APP_STATE_RUNNING";
1529             case APP_STATE_TIMEOUT:
1530                 return "APP_STATE_TIMEOUT";
1531             default:
1532                 return "unknown state=" + mAppTransitionState;
1533         }
1534     }
1535 
transitTypeToString()1536     private String transitTypeToString() {
1537         switch (mNextAppTransitionType) {
1538             case NEXT_TRANSIT_TYPE_NONE:
1539                 return "NEXT_TRANSIT_TYPE_NONE";
1540             case NEXT_TRANSIT_TYPE_CUSTOM:
1541                 return "NEXT_TRANSIT_TYPE_CUSTOM";
1542             case NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE:
1543                 return "NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE";
1544             case NEXT_TRANSIT_TYPE_SCALE_UP:
1545                 return "NEXT_TRANSIT_TYPE_SCALE_UP";
1546             case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP:
1547                 return "NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP";
1548             case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN:
1549                 return "NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN";
1550             case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP:
1551                 return "NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP";
1552             case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN:
1553                 return "NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN";
1554             case NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS:
1555                 return "NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS";
1556             default:
1557                 return "unknown type=" + mNextAppTransitionType;
1558         }
1559     }
1560 
1561     private static final ArrayList<Pair<Integer, String>> sFlagToString;
1562 
1563     static {
1564         sFlagToString = new ArrayList<>();
sFlagToString.add(new Pair<>(TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE, "TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE"))1565         sFlagToString.add(new Pair<>(TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE,
1566                 "TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE"));
sFlagToString.add(new Pair<>(TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION, "TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION"))1567         sFlagToString.add(new Pair<>(TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION,
1568                 "TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION"));
sFlagToString.add(new Pair<>(TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER, "TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER"))1569         sFlagToString.add(new Pair<>(TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER,
1570                 "TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER"));
sFlagToString.add(new Pair<>(TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION, "TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION"))1571         sFlagToString.add(new Pair<>(TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION,
1572                 "TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION"));
sFlagToString.add(new Pair<>(TRANSIT_FLAG_APP_CRASHED, "TRANSIT_FLAG_APP_CRASHED"))1573         sFlagToString.add(new Pair<>(TRANSIT_FLAG_APP_CRASHED,
1574                 "TRANSIT_FLAG_APP_CRASHED"));
sFlagToString.add(new Pair<>(TRANSIT_FLAG_OPEN_BEHIND, "TRANSIT_FLAG_OPEN_BEHIND"))1575         sFlagToString.add(new Pair<>(TRANSIT_FLAG_OPEN_BEHIND,
1576                 "TRANSIT_FLAG_OPEN_BEHIND"));
1577     }
1578 
1579     /**
1580      * Returns the human readable names of transit flags.
1581      *
1582      * @param flags a bitmask combination of transit flags.
1583      * @return The combination of symbolic names.
1584      */
appTransitionFlagsToString(int flags)1585     public static String appTransitionFlagsToString(int flags) {
1586         String sep = "";
1587         StringBuilder sb = new StringBuilder();
1588         for (Pair<Integer, String> pair : sFlagToString) {
1589             if ((flags & pair.first) != 0) {
1590                 sb.append(sep);
1591                 sb.append(pair.second);
1592                 sep = " | ";
1593             }
1594         }
1595         return sb.toString();
1596     }
1597 
dumpDebug(ProtoOutputStream proto, long fieldId)1598     void dumpDebug(ProtoOutputStream proto, long fieldId) {
1599         final long token = proto.start(fieldId);
1600         proto.write(APP_TRANSITION_STATE, mAppTransitionState);
1601         proto.write(LAST_USED_APP_TRANSITION, mLastUsedAppTransition);
1602         proto.end(token);
1603     }
1604 
1605     @Override
dump(PrintWriter pw, String prefix)1606     public void dump(PrintWriter pw, String prefix) {
1607         pw.print(prefix); pw.println(this);
1608         pw.print(prefix); pw.print("mAppTransitionState="); pw.println(appStateToString());
1609         if (mNextAppTransitionType != NEXT_TRANSIT_TYPE_NONE) {
1610             pw.print(prefix); pw.print("mNextAppTransitionType=");
1611                     pw.println(transitTypeToString());
1612         }
1613         if (mNextAppTransitionOverrideRequested
1614                 || mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) {
1615             pw.print(prefix); pw.print("mNextAppTransitionPackage=");
1616             pw.println(mNextAppTransitionPackage);
1617             pw.print(prefix); pw.print("mNextAppTransitionEnter=0x");
1618             pw.print(Integer.toHexString(mNextAppTransitionEnter));
1619             pw.print(" mNextAppTransitionExit=0x");
1620             pw.println(Integer.toHexString(mNextAppTransitionExit));
1621         }
1622         switch (mNextAppTransitionType) {
1623             case NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE:
1624                 pw.print(prefix); pw.print("mNextAppTransitionPackage=");
1625                         pw.println(mNextAppTransitionPackage);
1626                 pw.print(prefix); pw.print("mNextAppTransitionInPlace=0x");
1627                         pw.print(Integer.toHexString(mNextAppTransitionInPlace));
1628                 break;
1629             case NEXT_TRANSIT_TYPE_SCALE_UP: {
1630                 getDefaultNextAppTransitionStartRect(mTmpRect);
1631                 pw.print(prefix); pw.print("mNextAppTransitionStartX=");
1632                         pw.print(mTmpRect.left);
1633                         pw.print(" mNextAppTransitionStartY=");
1634                         pw.println(mTmpRect.top);
1635                 pw.print(prefix); pw.print("mNextAppTransitionStartWidth=");
1636                         pw.print(mTmpRect.width());
1637                         pw.print(" mNextAppTransitionStartHeight=");
1638                         pw.println(mTmpRect.height());
1639                 break;
1640             }
1641             case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP:
1642             case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN:
1643             case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP:
1644             case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN: {
1645                 pw.print(prefix); pw.print("mDefaultNextAppTransitionAnimationSpec=");
1646                         pw.println(mDefaultNextAppTransitionAnimationSpec);
1647                 pw.print(prefix); pw.print("mNextAppTransitionAnimationsSpecs=");
1648                         pw.println(mNextAppTransitionAnimationsSpecs);
1649                 pw.print(prefix); pw.print("mNextAppTransitionScaleUp=");
1650                         pw.println(mNextAppTransitionScaleUp);
1651                 break;
1652             }
1653         }
1654         if (mNextAppTransitionCallback != null) {
1655             pw.print(prefix); pw.print("mNextAppTransitionCallback=");
1656                     pw.println(mNextAppTransitionCallback);
1657         }
1658         if (mLastUsedAppTransition != TRANSIT_OLD_NONE) {
1659             pw.print(prefix); pw.print("mLastUsedAppTransition=");
1660                     pw.println(appTransitionOldToString(mLastUsedAppTransition));
1661             pw.print(prefix); pw.print("mLastOpeningApp=");
1662                     pw.println(mLastOpeningApp);
1663             pw.print(prefix); pw.print("mLastClosingApp=");
1664                     pw.println(mLastClosingApp);
1665             pw.print(prefix); pw.print("mLastChangingApp=");
1666             pw.println(mLastChangingApp);
1667         }
1668     }
1669 
setCurrentUser(int newUserId)1670     public void setCurrentUser(int newUserId) {
1671         mCurrentUserId = newUserId;
1672     }
1673 
prepareAppTransition(@ransitionType int transit, @TransitionFlags int flags)1674     boolean prepareAppTransition(@TransitionType int transit, @TransitionFlags int flags) {
1675         if (mService.mAtmService.getTransitionController().getTransitionPlayer() != null) {
1676             return false;
1677         }
1678         mNextAppTransitionRequests.add(transit);
1679         mNextAppTransitionFlags |= flags;
1680         updateBooster();
1681         removeAppTransitionTimeoutCallbacks();
1682         mHandler.postDelayed(mHandleAppTransitionTimeoutRunnable,
1683                 APP_TRANSITION_TIMEOUT_MS);
1684         return prepare();
1685     }
1686 
1687     /**
1688      * @return true if {@param transit} is representing a transition in which Keyguard is going
1689      *         away, false otherwise
1690      */
isKeyguardGoingAwayTransitOld(int transit)1691     public static boolean isKeyguardGoingAwayTransitOld(int transit) {
1692         return transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY
1693                 || transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
1694     }
1695 
isKeyguardOccludeTransitOld(@ransitionOldType int transit)1696     static boolean isKeyguardOccludeTransitOld(@TransitionOldType int transit) {
1697         return transit == TRANSIT_OLD_KEYGUARD_OCCLUDE
1698                 || transit == TRANSIT_OLD_KEYGUARD_UNOCCLUDE;
1699     }
1700 
isKeyguardTransitOld(@ransitionOldType int transit)1701     static boolean isKeyguardTransitOld(@TransitionOldType int transit) {
1702         return isKeyguardGoingAwayTransitOld(transit) || isKeyguardOccludeTransitOld(transit);
1703     }
1704 
isTaskTransitOld(@ransitionOldType int transit)1705     static boolean isTaskTransitOld(@TransitionOldType int transit) {
1706         return isTaskOpenTransitOld(transit)
1707                 || isTaskCloseTransitOld(transit);
1708     }
1709 
isTaskCloseTransitOld(@ransitionOldType int transit)1710     static boolean isTaskCloseTransitOld(@TransitionOldType int transit) {
1711         return transit == TRANSIT_OLD_TASK_CLOSE
1712                 || transit == TRANSIT_OLD_TASK_TO_BACK;
1713     }
1714 
isTaskOpenTransitOld(@ransitionOldType int transit)1715     private static  boolean isTaskOpenTransitOld(@TransitionOldType int transit) {
1716         return transit == TRANSIT_OLD_TASK_OPEN
1717                 || transit == TRANSIT_OLD_TASK_OPEN_BEHIND
1718                 || transit == TRANSIT_OLD_TASK_TO_FRONT;
1719     }
1720 
isActivityTransitOld(@ransitionOldType int transit)1721     static boolean isActivityTransitOld(@TransitionOldType int transit) {
1722         return transit == TRANSIT_OLD_ACTIVITY_OPEN
1723                 || transit == TRANSIT_OLD_ACTIVITY_CLOSE
1724                 || transit == TRANSIT_OLD_ACTIVITY_RELAUNCH;
1725     }
1726 
isChangeTransitOld(@ransitionOldType int transit)1727     static boolean isChangeTransitOld(@TransitionOldType int transit) {
1728         return transit == TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE;
1729     }
1730 
isClosingTransitOld(@ransitionOldType int transit)1731     static boolean isClosingTransitOld(@TransitionOldType int transit) {
1732         return transit == TRANSIT_OLD_ACTIVITY_CLOSE
1733                 || transit == TRANSIT_OLD_TASK_CLOSE
1734                 || transit == TRANSIT_OLD_WALLPAPER_CLOSE
1735                 || transit == TRANSIT_OLD_WALLPAPER_INTRA_CLOSE
1736                 || transit == TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE
1737                 || transit == TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE;
1738     }
1739 
isNormalTransit(@ransitionType int transit)1740     static boolean isNormalTransit(@TransitionType int transit) {
1741         return transit == TRANSIT_OPEN
1742                 || transit == TRANSIT_CLOSE
1743                 || transit == TRANSIT_TO_FRONT
1744                 || transit == TRANSIT_TO_BACK;
1745     }
1746 
isKeyguardTransit(@ransitionType int transit)1747     static boolean isKeyguardTransit(@TransitionType int transit) {
1748         return transit == TRANSIT_KEYGUARD_GOING_AWAY
1749                 || transit == TRANSIT_KEYGUARD_OCCLUDE
1750                 || transit == TRANSIT_KEYGUARD_UNOCCLUDE;
1751     }
1752 
getKeyguardTransition()1753     @TransitionType int getKeyguardTransition() {
1754         // In case we unocclude Keyguard and occlude it again, meaning that we never actually
1755         // unoccclude/occlude Keyguard, but just run a normal transition.
1756         final int occludeIndex = mNextAppTransitionRequests.indexOf(TRANSIT_KEYGUARD_UNOCCLUDE);
1757         if (occludeIndex != -1
1758                 && occludeIndex < mNextAppTransitionRequests.indexOf(TRANSIT_KEYGUARD_OCCLUDE)) {
1759             return TRANSIT_NONE;
1760         }
1761 
1762         for (int i = 0; i < mNextAppTransitionRequests.size(); ++i) {
1763             final @TransitionType int transit = mNextAppTransitionRequests.get(i);
1764             if (isKeyguardTransit(transit)) {
1765                 return transit;
1766             }
1767         }
1768         return TRANSIT_NONE;
1769     }
1770 
getFirstAppTransition()1771     @TransitionType int getFirstAppTransition() {
1772         for (int i = 0; i < mNextAppTransitionRequests.size(); ++i) {
1773             final @TransitionType int transit = mNextAppTransitionRequests.get(i);
1774             if (transit != TRANSIT_NONE && !isKeyguardTransit(transit)) {
1775                 return transit;
1776             }
1777         }
1778         return TRANSIT_NONE;
1779     }
1780 
containsTransitRequest(@ransitionType int transit)1781     boolean containsTransitRequest(@TransitionType int transit) {
1782         return mNextAppTransitionRequests.contains(transit);
1783     }
1784 
1785     /**
1786      * @return whether the transition should show the thumbnail being scaled down.
1787      */
shouldScaleDownThumbnailTransition(int uiMode, int orientation)1788     private boolean shouldScaleDownThumbnailTransition(int uiMode, int orientation) {
1789         return mGridLayoutRecentsEnabled
1790                 || orientation == Configuration.ORIENTATION_PORTRAIT;
1791     }
1792 
handleAppTransitionTimeout()1793     private void handleAppTransitionTimeout() {
1794         synchronized (mService.mGlobalLock) {
1795             final DisplayContent dc = mDisplayContent;
1796             if (dc == null) {
1797                 return;
1798             }
1799             notifyAppTransitionTimeoutLocked();
1800             if (isTransitionSet() || !dc.mOpeningApps.isEmpty() || !dc.mClosingApps.isEmpty()
1801                     || !dc.mChangingContainers.isEmpty()) {
1802                 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
1803                             "*** APP TRANSITION TIMEOUT. displayId=%d isTransitionSet()=%b "
1804                                     + "mOpeningApps.size()=%d mClosingApps.size()=%d "
1805                                     + "mChangingApps.size()=%d",
1806                             dc.getDisplayId(), dc.mAppTransition.isTransitionSet(),
1807                             dc.mOpeningApps.size(), dc.mClosingApps.size(),
1808                             dc.mChangingContainers.size());
1809 
1810                 setTimeout();
1811                 mService.mWindowPlacerLocked.performSurfacePlacement();
1812             }
1813         }
1814     }
1815 
doAnimationCallback(@onNull IRemoteCallback callback)1816     private static void doAnimationCallback(@NonNull IRemoteCallback callback) {
1817         try {
1818             ((IRemoteCallback) callback).sendResult(null);
1819         } catch (RemoteException e) {
1820         }
1821     }
1822 
setAppTransitionFinishedCallbackIfNeeded(Animation anim)1823     private void setAppTransitionFinishedCallbackIfNeeded(Animation anim) {
1824         final IRemoteCallback callback = mAnimationFinishedCallback;
1825         if (callback != null && anim != null) {
1826             anim.setAnimationListener(new Animation.AnimationListener() {
1827                 @Override
1828                 public void onAnimationStart(Animation animation) { }
1829 
1830                 @Override
1831                 public void onAnimationEnd(Animation animation) {
1832                     mHandler.sendMessage(PooledLambda.obtainMessage(
1833                             AppTransition::doAnimationCallback, callback));
1834                 }
1835 
1836                 @Override
1837                 public void onAnimationRepeat(Animation animation) { }
1838             });
1839         }
1840     }
1841 
removeAppTransitionTimeoutCallbacks()1842     void removeAppTransitionTimeoutCallbacks() {
1843         mHandler.removeCallbacks(mHandleAppTransitionTimeoutRunnable);
1844     }
1845 }
1846