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