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