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