1 /* 2 * Copyright (C) 2021 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.keyguard; 18 19 import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; 20 21 import android.view.View; 22 import android.view.ViewPropertyAnimator; 23 24 import com.android.systemui.animation.Interpolators; 25 import com.android.systemui.plugins.log.LogBuffer; 26 import com.android.systemui.plugins.log.LogLevel; 27 import com.android.systemui.statusbar.StatusBarState; 28 import com.android.systemui.statusbar.notification.AnimatableProperty; 29 import com.android.systemui.statusbar.notification.PropertyAnimator; 30 import com.android.systemui.statusbar.notification.stack.AnimationProperties; 31 import com.android.systemui.statusbar.phone.DozeParameters; 32 import com.android.systemui.statusbar.phone.ScreenOffAnimationController; 33 import com.android.systemui.statusbar.policy.KeyguardStateController; 34 35 import com.google.errorprone.annotations.CompileTimeConstant; 36 37 /** 38 * Helper class for updating visibility of keyguard views based on keyguard and status bar state. 39 * This logic is shared by both the keyguard status view and the keyguard user switcher. 40 */ 41 public class KeyguardVisibilityHelper { 42 private static final String TAG = "KeyguardVisibilityHelper"; 43 44 private View mView; 45 private final KeyguardStateController mKeyguardStateController; 46 private final DozeParameters mDozeParameters; 47 private final ScreenOffAnimationController mScreenOffAnimationController; 48 private boolean mAnimateYPos; 49 private boolean mKeyguardViewVisibilityAnimating; 50 private boolean mLastOccludedState = false; 51 private final AnimationProperties mAnimationProperties = new AnimationProperties(); 52 private final LogBuffer mLogBuffer; 53 KeyguardVisibilityHelper(View view, KeyguardStateController keyguardStateController, DozeParameters dozeParameters, ScreenOffAnimationController screenOffAnimationController, boolean animateYPos, LogBuffer logBuffer)54 public KeyguardVisibilityHelper(View view, 55 KeyguardStateController keyguardStateController, 56 DozeParameters dozeParameters, 57 ScreenOffAnimationController screenOffAnimationController, 58 boolean animateYPos, 59 LogBuffer logBuffer) { 60 mView = view; 61 mKeyguardStateController = keyguardStateController; 62 mDozeParameters = dozeParameters; 63 mScreenOffAnimationController = screenOffAnimationController; 64 mAnimateYPos = animateYPos; 65 mLogBuffer = logBuffer; 66 } 67 log(@ompileTimeConstant String message)68 private void log(@CompileTimeConstant String message) { 69 if (mLogBuffer != null) { 70 mLogBuffer.log(TAG, LogLevel.DEBUG, message); 71 } 72 } 73 isVisibilityAnimating()74 public boolean isVisibilityAnimating() { 75 return mKeyguardViewVisibilityAnimating; 76 } 77 78 /** 79 * Set the visibility of a keyguard view based on some new state. 80 */ setViewVisibility( int statusBarState, boolean keyguardFadingAway, boolean goingToFullShade, int oldStatusBarState)81 public void setViewVisibility( 82 int statusBarState, 83 boolean keyguardFadingAway, 84 boolean goingToFullShade, 85 int oldStatusBarState) { 86 mView.animate().cancel(); 87 boolean isOccluded = mKeyguardStateController.isOccluded(); 88 mKeyguardViewVisibilityAnimating = false; 89 90 if ((!keyguardFadingAway && oldStatusBarState == KEYGUARD 91 && statusBarState != KEYGUARD) || goingToFullShade) { 92 mKeyguardViewVisibilityAnimating = true; 93 mView.animate() 94 .alpha(0f) 95 .setStartDelay(0) 96 .setDuration(160) 97 .setInterpolator(Interpolators.ALPHA_OUT) 98 .withEndAction( 99 mAnimateKeyguardStatusViewGoneEndRunnable); 100 if (keyguardFadingAway) { 101 mView.animate() 102 .setStartDelay(mKeyguardStateController.getKeyguardFadingAwayDelay()) 103 .setDuration(mKeyguardStateController.getShortenedFadingAwayDuration()) 104 .start(); 105 log("goingToFullShade && keyguardFadingAway"); 106 } else { 107 log("goingToFullShade && !keyguardFadingAway"); 108 } 109 } else if (oldStatusBarState == StatusBarState.SHADE_LOCKED && statusBarState == KEYGUARD) { 110 mView.setVisibility(View.VISIBLE); 111 mKeyguardViewVisibilityAnimating = true; 112 mView.setAlpha(0f); 113 mView.animate() 114 .alpha(1f) 115 .setStartDelay(0) 116 .setDuration(320) 117 .setInterpolator(Interpolators.ALPHA_IN) 118 .withEndAction(mAnimateKeyguardStatusViewVisibleEndRunnable); 119 log("keyguardFadingAway transition w/ Y Aniamtion"); 120 } else if (statusBarState == KEYGUARD) { 121 if (keyguardFadingAway) { 122 mKeyguardViewVisibilityAnimating = true; 123 ViewPropertyAnimator animator = mView.animate() 124 .alpha(0) 125 .setInterpolator(Interpolators.FAST_OUT_LINEAR_IN) 126 .withEndAction(mAnimateKeyguardStatusViewInvisibleEndRunnable); 127 if (mAnimateYPos) { 128 float target = mView.getY() - mView.getHeight() * 0.05f; 129 int delay = 0; 130 int duration = 125; 131 // We animate the Y property separately using the PropertyAnimator, as the panel 132 // view also needs to update the end position. 133 mAnimationProperties.setDuration(duration).setDelay(delay); 134 PropertyAnimator.cancelAnimation(mView, AnimatableProperty.Y); 135 PropertyAnimator.setProperty(mView, AnimatableProperty.Y, target, 136 mAnimationProperties, 137 true /* animate */); 138 animator.setDuration(duration) 139 .setStartDelay(delay); 140 log("keyguardFadingAway transition w/ Y Aniamtion"); 141 } else { 142 log("keyguardFadingAway transition w/o Y Animation"); 143 } 144 animator.start(); 145 } else if (mScreenOffAnimationController.shouldAnimateInKeyguard()) { 146 log("ScreenOff transition"); 147 mKeyguardViewVisibilityAnimating = true; 148 149 // Ask the screen off animation controller to animate the keyguard visibility for us 150 // since it may need to be cancelled due to keyguard lifecycle events. 151 mScreenOffAnimationController.animateInKeyguard( 152 mView, mAnimateKeyguardStatusViewVisibleEndRunnable); 153 } else { 154 log("Direct set Visibility to VISIBLE"); 155 mView.setVisibility(View.VISIBLE); 156 } 157 } else { 158 log("Direct set Visibility to GONE"); 159 mView.setVisibility(View.GONE); 160 mView.setAlpha(1f); 161 } 162 163 mLastOccludedState = isOccluded; 164 } 165 166 private final Runnable mAnimateKeyguardStatusViewInvisibleEndRunnable = () -> { 167 mKeyguardViewVisibilityAnimating = false; 168 mView.setVisibility(View.INVISIBLE); 169 log("Callback Set Visibility to INVISIBLE"); 170 }; 171 172 private final Runnable mAnimateKeyguardStatusViewGoneEndRunnable = () -> { 173 mKeyguardViewVisibilityAnimating = false; 174 mView.setVisibility(View.GONE); 175 log("CallbackSet Visibility to GONE"); 176 }; 177 178 private final Runnable mAnimateKeyguardStatusViewVisibleEndRunnable = () -> { 179 mKeyguardViewVisibilityAnimating = false; 180 mView.setVisibility(View.VISIBLE); 181 log("Callback Set Visibility to VISIBLE"); 182 }; 183 } 184