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 import static com.android.systemui.statusbar.StatusBarState.SHADE; 21 22 import android.util.Property; 23 import android.view.View; 24 25 import com.android.app.animation.Interpolators; 26 import com.android.systemui.log.LogBuffer; 27 import com.android.systemui.log.core.LogLevel; 28 import com.android.systemui.statusbar.StatusBarState; 29 import com.android.systemui.statusbar.notification.AnimatableProperty; 30 import com.android.systemui.statusbar.notification.PropertyAnimator; 31 import com.android.systemui.statusbar.notification.stack.AnimationProperties; 32 import com.android.systemui.statusbar.phone.DozeParameters; 33 import com.android.systemui.statusbar.phone.ScreenOffAnimationController; 34 import com.android.systemui.statusbar.policy.KeyguardStateController; 35 import com.android.systemui.util.Assert; 36 37 import com.google.errorprone.annotations.CompileTimeConstant; 38 39 import java.util.function.Consumer; 40 41 /** 42 * Helper class for updating visibility of keyguard views based on keyguard and status bar state. 43 * This logic is shared by both the keyguard status view and the keyguard user switcher. 44 */ 45 public class KeyguardVisibilityHelper { 46 private static final String TAG = "KeyguardVisibilityHelper"; 47 48 private View mView; 49 private final KeyguardStateController mKeyguardStateController; 50 private final DozeParameters mDozeParameters; 51 private final ScreenOffAnimationController mScreenOffAnimationController; 52 private boolean mAnimateYPos; 53 private boolean mKeyguardViewVisibilityAnimating; 54 private boolean mLastOccludedState = false; 55 private final AnimationProperties mAnimationProperties = new AnimationProperties(); 56 private final LogBuffer mLogBuffer; 57 KeyguardVisibilityHelper(View view, KeyguardStateController keyguardStateController, DozeParameters dozeParameters, ScreenOffAnimationController screenOffAnimationController, boolean animateYPos, LogBuffer logBuffer)58 public KeyguardVisibilityHelper(View view, 59 KeyguardStateController keyguardStateController, 60 DozeParameters dozeParameters, 61 ScreenOffAnimationController screenOffAnimationController, 62 boolean animateYPos, 63 LogBuffer logBuffer) { 64 mView = view; 65 mKeyguardStateController = keyguardStateController; 66 mDozeParameters = dozeParameters; 67 mScreenOffAnimationController = screenOffAnimationController; 68 mAnimateYPos = animateYPos; 69 mLogBuffer = logBuffer; 70 } 71 log(@ompileTimeConstant String message)72 private void log(@CompileTimeConstant String message) { 73 if (mLogBuffer != null) { 74 mLogBuffer.log(TAG, LogLevel.DEBUG, message); 75 } 76 } 77 isVisibilityAnimating()78 public boolean isVisibilityAnimating() { 79 return mKeyguardViewVisibilityAnimating; 80 } 81 82 /** 83 * Set the visibility of a keyguard view based on some new state. 84 */ setViewVisibility( int statusBarState, boolean keyguardFadingAway, boolean goingToFullShade, int oldStatusBarState)85 public void setViewVisibility( 86 int statusBarState, 87 boolean keyguardFadingAway, 88 boolean goingToFullShade, 89 int oldStatusBarState) { 90 Assert.isMainThread(); 91 PropertyAnimator.cancelAnimation(mView, AnimatableProperty.ALPHA); 92 boolean isOccluded = mKeyguardStateController.isOccluded(); 93 mKeyguardViewVisibilityAnimating = false; 94 95 if ((!keyguardFadingAway && oldStatusBarState == KEYGUARD 96 && statusBarState != KEYGUARD) || goingToFullShade) { 97 mKeyguardViewVisibilityAnimating = true; 98 99 AnimationProperties animProps = new AnimationProperties() 100 .setCustomInterpolator(View.ALPHA, Interpolators.ALPHA_OUT) 101 .setAnimationEndAction(mSetGoneEndAction); 102 if (keyguardFadingAway) { 103 animProps 104 .setDelay(mKeyguardStateController.getKeyguardFadingAwayDelay()) 105 .setDuration(mKeyguardStateController.getShortenedFadingAwayDuration()); 106 log("goingToFullShade && keyguardFadingAway"); 107 } else { 108 animProps.setDelay(0).setDuration(160); 109 log("goingToFullShade && !keyguardFadingAway"); 110 } 111 PropertyAnimator.setProperty( 112 mView, AnimatableProperty.ALPHA, 0f, animProps, true /* animate */); 113 } else if (oldStatusBarState == StatusBarState.SHADE_LOCKED && statusBarState == KEYGUARD) { 114 mView.setVisibility(View.VISIBLE); 115 mKeyguardViewVisibilityAnimating = true; 116 mView.setAlpha(0f); 117 PropertyAnimator.setProperty( 118 mView, AnimatableProperty.ALPHA, 1f, 119 new AnimationProperties() 120 .setDelay(0) 121 .setDuration(320) 122 .setCustomInterpolator(View.ALPHA, Interpolators.ALPHA_IN) 123 .setAnimationEndAction( 124 property -> mSetVisibleEndRunnable.run()), 125 true /* animate */); 126 log("keyguardFadingAway transition w/ Y Aniamtion"); 127 } else if (statusBarState == KEYGUARD) { 128 // Sometimes, device will be unlocked and then locked very quickly. 129 // keyguardFadingAway hasn't been set to false cause unlock animation hasn't finished 130 // So we should not animate keyguard fading away in this case (when oldState is SHADE) 131 if (oldStatusBarState != SHADE) { 132 log("statusBarState == KEYGUARD && oldStatusBarState != SHADE"); 133 } else { 134 log("statusBarState == KEYGUARD && oldStatusBarState == SHADE"); 135 } 136 137 if (keyguardFadingAway && oldStatusBarState != SHADE) { 138 mKeyguardViewVisibilityAnimating = true; 139 AnimationProperties animProps = new AnimationProperties() 140 .setDelay(0) 141 .setCustomInterpolator(View.ALPHA, Interpolators.FAST_OUT_LINEAR_IN) 142 .setAnimationEndAction(mSetInvisibleEndAction); 143 if (mAnimateYPos) { 144 float target = mView.getY() - mView.getHeight() * 0.05f; 145 int delay = 0; 146 int duration = 125; 147 // We animate the Y property separately using the PropertyAnimator, as the panel 148 // view also needs to update the end position. 149 mAnimationProperties.setDuration(duration).setDelay(delay); 150 PropertyAnimator.cancelAnimation(mView, AnimatableProperty.Y); 151 PropertyAnimator.setProperty(mView, AnimatableProperty.Y, target, 152 mAnimationProperties, 153 true /* animate */); 154 animProps.setDuration(duration) 155 .setDelay(delay); 156 log("keyguardFadingAway transition w/ Y Aniamtion"); 157 } else { 158 log("keyguardFadingAway transition w/o Y Animation"); 159 } 160 PropertyAnimator.setProperty( 161 mView, AnimatableProperty.ALPHA, 0f, 162 animProps, 163 true /* animate */); 164 } else if (mScreenOffAnimationController.shouldAnimateInKeyguard()) { 165 log("ScreenOff transition"); 166 mKeyguardViewVisibilityAnimating = true; 167 168 // Ask the screen off animation controller to animate the keyguard visibility for us 169 // since it may need to be cancelled due to keyguard lifecycle events. 170 mScreenOffAnimationController.animateInKeyguard( 171 mView, mSetVisibleEndRunnable); 172 } else { 173 log("Direct set Visibility to VISIBLE"); 174 mView.setVisibility(View.VISIBLE); 175 } 176 } else { 177 log("Direct set Visibility to GONE"); 178 mView.setVisibility(View.GONE); 179 mView.setAlpha(1f); 180 } 181 182 mLastOccludedState = isOccluded; 183 } 184 185 private final Consumer<Property> mSetInvisibleEndAction = new Consumer<>() { 186 @Override 187 public void accept(Property property) { 188 mKeyguardViewVisibilityAnimating = false; 189 mView.setVisibility(View.INVISIBLE); 190 log("Callback Set Visibility to INVISIBLE"); 191 } 192 }; 193 194 private final Consumer<Property> mSetGoneEndAction = new Consumer<>() { 195 @Override 196 public void accept(Property property) { 197 mKeyguardViewVisibilityAnimating = false; 198 mView.setVisibility(View.GONE); 199 log("CallbackSet Visibility to GONE"); 200 } 201 }; 202 203 private final Runnable mSetVisibleEndRunnable = () -> { 204 mKeyguardViewVisibilityAnimating = false; 205 mView.setVisibility(View.VISIBLE); 206 log("Callback Set Visibility to VISIBLE"); 207 }; 208 } 209