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