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