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