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