1 /* 2 * Copyright (C) 2020 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 package com.android.wm.shell.startingsurface; 17 18 import static android.view.View.GONE; 19 20 import static com.android.internal.jank.InteractionJankMonitor.CUJ_SPLASHSCREEN_EXIT_ANIM; 21 22 import android.animation.Animator; 23 import android.content.Context; 24 import android.graphics.Rect; 25 import android.util.Slog; 26 import android.view.SurfaceControl; 27 import android.view.View; 28 import android.window.SplashScreenView; 29 30 import com.android.internal.jank.InteractionJankMonitor; 31 import com.android.wm.shell.R; 32 import com.android.wm.shell.common.TransactionPool; 33 34 /** 35 * Default animation for exiting the splash screen window. 36 * @hide 37 */ 38 public class SplashScreenExitAnimation implements Animator.AnimatorListener { 39 private static final boolean DEBUG_EXIT_ANIMATION = false; 40 private static final String TAG = StartingWindowController.TAG; 41 42 private final SurfaceControl mFirstWindowSurface; 43 private final Rect mFirstWindowFrame = new Rect(); 44 private final SplashScreenView mSplashScreenView; 45 private final int mMainWindowShiftLength; 46 private final int mIconFadeOutDuration; 47 private final int mAppRevealDelay; 48 private final int mAppRevealDuration; 49 private final int mAnimationDuration; 50 private final float mIconStartAlpha; 51 private final float mBrandingStartAlpha; 52 private final TransactionPool mTransactionPool; 53 // TODO(b/261167708): Clean enter animation code after moving Letterbox code to Shell 54 private final float mRoundedCornerRadius; 55 56 private Runnable mFinishCallback; 57 SplashScreenExitAnimation(Context context, SplashScreenView view, SurfaceControl leash, Rect frame, int mainWindowShiftLength, TransactionPool pool, Runnable handleFinish, float roundedCornerRadius)58 SplashScreenExitAnimation(Context context, SplashScreenView view, SurfaceControl leash, 59 Rect frame, int mainWindowShiftLength, TransactionPool pool, Runnable handleFinish, 60 float roundedCornerRadius) { 61 mSplashScreenView = view; 62 mFirstWindowSurface = leash; 63 mRoundedCornerRadius = roundedCornerRadius; 64 if (frame != null) { 65 mFirstWindowFrame.set(frame); 66 } 67 68 View iconView = view.getIconView(); 69 70 // If the icon and the background are invisible, don't animate it 71 if (iconView == null || iconView.getLayoutParams().width == 0 72 || iconView.getLayoutParams().height == 0) { 73 mIconFadeOutDuration = 0; 74 mIconStartAlpha = 0; 75 mBrandingStartAlpha = 0; 76 mAppRevealDelay = 0; 77 } else { 78 iconView.setLayerType(View.LAYER_TYPE_HARDWARE, null); 79 // The branding view could only exists when the icon is present. 80 final View brandingView = view.getBrandingView(); 81 if (brandingView != null) { 82 mBrandingStartAlpha = brandingView.getAlpha(); 83 } else { 84 mBrandingStartAlpha = 0; 85 } 86 mIconFadeOutDuration = context.getResources().getInteger( 87 R.integer.starting_window_app_reveal_icon_fade_out_duration); 88 mAppRevealDelay = context.getResources().getInteger( 89 R.integer.starting_window_app_reveal_anim_delay); 90 mIconStartAlpha = iconView.getAlpha(); 91 } 92 mAppRevealDuration = context.getResources().getInteger( 93 R.integer.starting_window_app_reveal_anim_duration); 94 mAnimationDuration = Math.max(mIconFadeOutDuration, mAppRevealDelay + mAppRevealDuration); 95 mMainWindowShiftLength = mainWindowShiftLength; 96 mFinishCallback = handleFinish; 97 mTransactionPool = pool; 98 } 99 startAnimations()100 void startAnimations() { 101 SplashScreenExitAnimationUtils.startAnimations(mSplashScreenView, mFirstWindowSurface, 102 mMainWindowShiftLength, mTransactionPool, mFirstWindowFrame, mAnimationDuration, 103 mIconFadeOutDuration, mIconStartAlpha, mBrandingStartAlpha, mAppRevealDelay, 104 mAppRevealDuration, this, mRoundedCornerRadius); 105 } 106 reset()107 private void reset() { 108 if (DEBUG_EXIT_ANIMATION) { 109 Slog.v(TAG, "vanish animation finished"); 110 } 111 112 if (mSplashScreenView.isAttachedToWindow()) { 113 mSplashScreenView.setVisibility(GONE); 114 if (mFinishCallback != null) { 115 mFinishCallback.run(); 116 mFinishCallback = null; 117 } 118 } 119 } 120 121 @Override onAnimationStart(Animator animation)122 public void onAnimationStart(Animator animation) { 123 InteractionJankMonitor.getInstance().begin(mSplashScreenView, CUJ_SPLASHSCREEN_EXIT_ANIM); 124 } 125 126 @Override onAnimationEnd(Animator animation)127 public void onAnimationEnd(Animator animation) { 128 reset(); 129 InteractionJankMonitor.getInstance().end(CUJ_SPLASHSCREEN_EXIT_ANIM); 130 } 131 132 @Override onAnimationCancel(Animator animation)133 public void onAnimationCancel(Animator animation) { 134 reset(); 135 InteractionJankMonitor.getInstance().cancel(CUJ_SPLASHSCREEN_EXIT_ANIM); 136 } 137 138 @Override onAnimationRepeat(Animator animation)139 public void onAnimationRepeat(Animator animation) { 140 // ignore 141 } 142 } 143