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.statusbar.StatusBarState;
26 import com.android.systemui.statusbar.notification.AnimatableProperty;
27 import com.android.systemui.statusbar.notification.PropertyAnimator;
28 import com.android.systemui.statusbar.notification.stack.AnimationProperties;
29 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
30 import com.android.systemui.statusbar.phone.DozeParameters;
31 import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
32 import com.android.systemui.statusbar.policy.KeyguardStateController;
33 
34 /**
35  * Helper class for updating visibility of keyguard views based on keyguard and status bar state.
36  * This logic is shared by both the keyguard status view and the keyguard user switcher.
37  */
38 public class KeyguardVisibilityHelper {
39 
40     private View mView;
41     private final KeyguardStateController mKeyguardStateController;
42     private final DozeParameters mDozeParameters;
43     private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
44     private boolean mAnimateYPos;
45     private boolean mKeyguardViewVisibilityAnimating;
46     private boolean mLastOccludedState = false;
47     private final AnimationProperties mAnimationProperties = new AnimationProperties();
48 
KeyguardVisibilityHelper(View view, KeyguardStateController keyguardStateController, DozeParameters dozeParameters, UnlockedScreenOffAnimationController unlockedScreenOffAnimationController, boolean animateYPos)49     public KeyguardVisibilityHelper(View view,
50             KeyguardStateController keyguardStateController,
51             DozeParameters dozeParameters,
52             UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
53             boolean animateYPos) {
54         mView = view;
55         mKeyguardStateController = keyguardStateController;
56         mDozeParameters = dozeParameters;
57         mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
58         mAnimateYPos = animateYPos;
59     }
60 
isVisibilityAnimating()61     public boolean isVisibilityAnimating() {
62         return mKeyguardViewVisibilityAnimating;
63     }
64 
65     /**
66      * Set the visibility of a keyguard view based on some new state.
67      */
setViewVisibility( int statusBarState, boolean keyguardFadingAway, boolean goingToFullShade, int oldStatusBarState)68     public void setViewVisibility(
69             int statusBarState,
70             boolean keyguardFadingAway,
71             boolean goingToFullShade,
72             int oldStatusBarState) {
73         mView.animate().cancel();
74         boolean isOccluded = mKeyguardStateController.isOccluded();
75         mKeyguardViewVisibilityAnimating = false;
76         if ((!keyguardFadingAway && oldStatusBarState == KEYGUARD
77                 && statusBarState != KEYGUARD) || goingToFullShade) {
78             mKeyguardViewVisibilityAnimating = true;
79             mView.animate()
80                     .alpha(0f)
81                     .setStartDelay(0)
82                     .setDuration(160)
83                     .setInterpolator(Interpolators.ALPHA_OUT)
84                     .withEndAction(
85                             mAnimateKeyguardStatusViewGoneEndRunnable);
86             if (keyguardFadingAway) {
87                 mView.animate()
88                         .setStartDelay(mKeyguardStateController.getKeyguardFadingAwayDelay())
89                         .setDuration(mKeyguardStateController.getShortenedFadingAwayDuration())
90                         .start();
91             }
92         } else if (oldStatusBarState == StatusBarState.SHADE_LOCKED && statusBarState == KEYGUARD) {
93             mView.setVisibility(View.VISIBLE);
94             mKeyguardViewVisibilityAnimating = true;
95             mView.setAlpha(0f);
96             mView.animate()
97                     .alpha(1f)
98                     .setStartDelay(0)
99                     .setDuration(320)
100                     .setInterpolator(Interpolators.ALPHA_IN)
101                     .withEndAction(mAnimateKeyguardStatusViewVisibleEndRunnable);
102         } else if (statusBarState == KEYGUARD) {
103             if (keyguardFadingAway) {
104                 mKeyguardViewVisibilityAnimating = true;
105                 ViewPropertyAnimator animator = mView.animate()
106                         .alpha(0)
107                         .setInterpolator(Interpolators.FAST_OUT_LINEAR_IN)
108                         .withEndAction(mAnimateKeyguardStatusViewInvisibleEndRunnable);
109                 if (mAnimateYPos) {
110                     float target = mView.getY() - mView.getHeight() * 0.05f;
111                     int delay = 0;
112                     int duration = 125;
113                     // We animate the Y property separately using the PropertyAnimator, as the panel
114                     // view also needs to update the end position.
115                     mAnimationProperties.setDuration(duration).setDelay(delay);
116                     PropertyAnimator.cancelAnimation(mView, AnimatableProperty.Y);
117                     PropertyAnimator.setProperty(mView, AnimatableProperty.Y, target,
118                             mAnimationProperties,
119                             true /* animate */);
120                     animator.setDuration(duration)
121                             .setStartDelay(delay);
122                 }
123                 animator.start();
124             } else if (mUnlockedScreenOffAnimationController.shouldAnimateInKeyguard()) {
125                 mKeyguardViewVisibilityAnimating = true;
126 
127                 // Ask the screen off animation controller to animate the keyguard visibility for us
128                 // since it may need to be cancelled due to keyguard lifecycle events.
129                 mUnlockedScreenOffAnimationController.animateInKeyguard(
130                         mView, mAnimateKeyguardStatusViewVisibleEndRunnable);
131             } else if (mLastOccludedState && !isOccluded) {
132                 // An activity was displayed over the lock screen, and has now gone away
133                 mView.setVisibility(View.VISIBLE);
134                 mView.setAlpha(0f);
135 
136                 mView.animate()
137                         .setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP)
138                         .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
139                         .alpha(1f)
140                         .withEndAction(mAnimateKeyguardStatusViewVisibleEndRunnable)
141                         .start();
142             } else {
143                 mView.setVisibility(View.VISIBLE);
144                 mView.setAlpha(1f);
145             }
146         } else {
147             mView.setVisibility(View.GONE);
148             mView.setAlpha(1f);
149         }
150 
151         mLastOccludedState = isOccluded;
152     }
153 
154     private final Runnable mAnimateKeyguardStatusViewInvisibleEndRunnable = () -> {
155         mKeyguardViewVisibilityAnimating = false;
156         mView.setVisibility(View.INVISIBLE);
157     };
158 
159     private final Runnable mAnimateKeyguardStatusViewGoneEndRunnable = () -> {
160         mKeyguardViewVisibilityAnimating = false;
161         mView.setVisibility(View.GONE);
162     };
163 
164     private final Runnable mAnimateKeyguardStatusViewVisibleEndRunnable = () -> {
165         mKeyguardViewVisibilityAnimating = false;
166     };
167 }
168