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 
17 package com.android.keyguard;
18 
19 import android.graphics.Rect;
20 import android.util.Slog;
21 
22 import com.android.keyguard.KeyguardClockSwitch.ClockSize;
23 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
24 import com.android.systemui.shared.system.smartspace.SmartspaceTransitionController;
25 import com.android.systemui.statusbar.notification.AnimatableProperty;
26 import com.android.systemui.statusbar.notification.PropertyAnimator;
27 import com.android.systemui.statusbar.notification.stack.AnimationProperties;
28 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
29 import com.android.systemui.statusbar.phone.DozeParameters;
30 import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
31 import com.android.systemui.statusbar.policy.ConfigurationController;
32 import com.android.systemui.statusbar.policy.KeyguardStateController;
33 import com.android.systemui.util.ViewController;
34 
35 import java.util.TimeZone;
36 
37 import javax.inject.Inject;
38 
39 /**
40  * Injectable controller for {@link KeyguardStatusView}.
41  */
42 public class KeyguardStatusViewController extends ViewController<KeyguardStatusView> {
43     private static final boolean DEBUG = KeyguardConstants.DEBUG;
44     private static final String TAG = "KeyguardStatusViewController";
45 
46     private static final AnimationProperties CLOCK_ANIMATION_PROPERTIES =
47             new AnimationProperties().setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
48 
49     private final KeyguardSliceViewController mKeyguardSliceViewController;
50     private final KeyguardClockSwitchController mKeyguardClockSwitchController;
51     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
52     private final ConfigurationController mConfigurationController;
53     private final DozeParameters mDozeParameters;
54     private final KeyguardVisibilityHelper mKeyguardVisibilityHelper;
55     private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
56     private final KeyguardStateController mKeyguardStateController;
57     private SmartspaceTransitionController mSmartspaceTransitionController;
58     private final Rect mClipBounds = new Rect();
59 
60     @Inject
KeyguardStatusViewController( KeyguardStatusView keyguardStatusView, KeyguardSliceViewController keyguardSliceViewController, KeyguardClockSwitchController keyguardClockSwitchController, KeyguardStateController keyguardStateController, KeyguardUpdateMonitor keyguardUpdateMonitor, ConfigurationController configurationController, DozeParameters dozeParameters, KeyguardUnlockAnimationController keyguardUnlockAnimationController, SmartspaceTransitionController smartspaceTransitionController, UnlockedScreenOffAnimationController unlockedScreenOffAnimationController)61     public KeyguardStatusViewController(
62             KeyguardStatusView keyguardStatusView,
63             KeyguardSliceViewController keyguardSliceViewController,
64             KeyguardClockSwitchController keyguardClockSwitchController,
65             KeyguardStateController keyguardStateController,
66             KeyguardUpdateMonitor keyguardUpdateMonitor,
67             ConfigurationController configurationController,
68             DozeParameters dozeParameters,
69             KeyguardUnlockAnimationController keyguardUnlockAnimationController,
70             SmartspaceTransitionController smartspaceTransitionController,
71             UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) {
72         super(keyguardStatusView);
73         mKeyguardSliceViewController = keyguardSliceViewController;
74         mKeyguardClockSwitchController = keyguardClockSwitchController;
75         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
76         mConfigurationController = configurationController;
77         mDozeParameters = dozeParameters;
78         mKeyguardStateController = keyguardStateController;
79         mKeyguardVisibilityHelper = new KeyguardVisibilityHelper(mView, keyguardStateController,
80                 dozeParameters, unlockedScreenOffAnimationController, /* animateYPos= */ true);
81         mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
82         mSmartspaceTransitionController = smartspaceTransitionController;
83     }
84 
85     @Override
onInit()86     public void onInit() {
87         mKeyguardClockSwitchController.init();
88     }
89 
90     @Override
onViewAttached()91     protected void onViewAttached() {
92         mKeyguardUpdateMonitor.registerCallback(mInfoCallback);
93         mConfigurationController.addCallback(mConfigurationListener);
94         mKeyguardStateController.addCallback(mKeyguardStateControllerCallback);
95     }
96 
97     @Override
onViewDetached()98     protected void onViewDetached() {
99         mKeyguardUpdateMonitor.removeCallback(mInfoCallback);
100         mConfigurationController.removeCallback(mConfigurationListener);
101         mKeyguardStateController.removeCallback(mKeyguardStateControllerCallback);
102     }
103 
104     /**
105      * Updates views on doze time tick.
106      */
dozeTimeTick()107     public void dozeTimeTick() {
108         refreshTime();
109         mKeyguardSliceViewController.refresh();
110     }
111 
112     /**
113      * The amount we're in doze.
114      */
setDarkAmount(float darkAmount)115     public void setDarkAmount(float darkAmount) {
116         mView.setDarkAmount(darkAmount);
117     }
118 
119     /**
120      * Set which clock should be displayed on the keyguard. The other one will be automatically
121      * hidden.
122      */
displayClock(@lockSize int clockSize)123     public void displayClock(@ClockSize int clockSize) {
124         mKeyguardClockSwitchController.displayClock(clockSize);
125     }
126 
127     /**
128      * If we're presenting a custom clock of just the default one.
129      */
hasCustomClock()130     public boolean hasCustomClock() {
131         return mKeyguardClockSwitchController.hasCustomClock();
132     }
133 
134     /**
135      * Set keyguard status view alpha.
136      */
setAlpha(float alpha)137     public void setAlpha(float alpha) {
138         if (!mKeyguardVisibilityHelper.isVisibilityAnimating()) {
139             // If we're capable of performing the SmartSpace shared element transition, and we are
140             // going to (we're swiping to dismiss vs. bringing up the PIN screen), then fade out
141             // everything except for the SmartSpace.
142             if (mKeyguardUnlockAnimationController.isUnlockingWithSmartSpaceTransition()) {
143                 mView.setChildrenAlphaExcludingClockView(alpha);
144                 mKeyguardClockSwitchController.setChildrenAlphaExcludingSmartspace(alpha);
145             } else if (!mKeyguardVisibilityHelper.isVisibilityAnimating()) {
146                 // Otherwise, we can just set the alpha for the entire container.
147                 mView.setAlpha(alpha);
148 
149                 // If we previously unlocked with the shared element transition, some child views
150                 // might still have alpha = 0f. Set them back to 1f since we're just using the
151                 // parent container's alpha.
152                 if (mView.getChildrenAlphaExcludingSmartSpace() < 1f) {
153                     mView.setChildrenAlphaExcludingClockView(1f);
154                     mKeyguardClockSwitchController.setChildrenAlphaExcludingSmartspace(1f);
155                 }
156             }
157         }
158     }
159 
160     /**
161      * Set pivot x.
162      */
setPivotX(float pivot)163     public void setPivotX(float pivot) {
164         mView.setPivotX(pivot);
165     }
166 
167     /**
168      * Set pivot y.
169      */
setPivotY(float pivot)170     public void setPivotY(float pivot) {
171         mView.setPivotY(pivot);
172     }
173 
174     /**
175      * Get the clock text size.
176      */
getClockTextSize()177     public float getClockTextSize() {
178         return mKeyguardClockSwitchController.getClockTextSize();
179     }
180 
181     /**
182      * Get the height of the keyguard status view without the notification icon area, as that's
183      * only visible on AOD.
184      */
getLockscreenHeight()185     public int getLockscreenHeight() {
186         return mView.getHeight() - mKeyguardClockSwitchController.getNotificationIconAreaHeight();
187     }
188 
189     /**
190      * Get y-bottom position of the currently visible clock.
191      */
getClockBottom(int statusBarHeaderHeight)192     public int getClockBottom(int statusBarHeaderHeight) {
193         return mKeyguardClockSwitchController.getClockBottom(statusBarHeaderHeight);
194     }
195 
196     /**
197      * @return true if the currently displayed clock is top aligned (as opposed to center aligned)
198      */
isClockTopAligned()199     public boolean isClockTopAligned() {
200         return mKeyguardClockSwitchController.isClockTopAligned();
201     }
202 
203     /**
204      * Set whether the view accessibility importance mode.
205      */
setStatusAccessibilityImportance(int mode)206     public void setStatusAccessibilityImportance(int mode) {
207         mView.setImportantForAccessibility(mode);
208     }
209 
210     /**
211      * Update position of the view with an optional animation
212      */
updatePosition(int x, int y, float scale, boolean animate)213     public void updatePosition(int x, int y, float scale, boolean animate) {
214         PropertyAnimator.setProperty(mView, AnimatableProperty.Y, y, CLOCK_ANIMATION_PROPERTIES,
215                 animate);
216 
217         mKeyguardClockSwitchController.updatePosition(x, scale, CLOCK_ANIMATION_PROPERTIES,
218                 animate);
219     }
220 
221     /**
222      * Set the visibility of the keyguard status view based on some new state.
223      */
setKeyguardStatusViewVisibility( int statusBarState, boolean keyguardFadingAway, boolean goingToFullShade, int oldStatusBarState)224     public void setKeyguardStatusViewVisibility(
225             int statusBarState,
226             boolean keyguardFadingAway,
227             boolean goingToFullShade,
228             int oldStatusBarState) {
229         mKeyguardVisibilityHelper.setViewVisibility(
230                 statusBarState, keyguardFadingAway, goingToFullShade, oldStatusBarState);
231     }
232 
refreshTime()233     private void refreshTime() {
234         mKeyguardClockSwitchController.refresh();
235     }
236 
237     private final ConfigurationController.ConfigurationListener mConfigurationListener =
238             new ConfigurationController.ConfigurationListener() {
239         @Override
240         public void onLocaleListChanged() {
241             refreshTime();
242         }
243 
244         @Override
245         public void onDensityOrFontScaleChanged() {
246             mKeyguardClockSwitchController.onDensityOrFontScaleChanged();
247         }
248     };
249 
250     private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
251         @Override
252         public void onTimeChanged() {
253             refreshTime();
254         }
255 
256         @Override
257         public void onTimeFormatChanged(String timeFormat) {
258             mKeyguardClockSwitchController.refreshFormat();
259         }
260 
261         @Override
262         public void onTimeZoneChanged(TimeZone timeZone) {
263             mKeyguardClockSwitchController.updateTimeZone(timeZone);
264         }
265 
266         @Override
267         public void onKeyguardVisibilityChanged(boolean showing) {
268             if (showing) {
269                 if (DEBUG) Slog.v(TAG, "refresh statusview showing:" + showing);
270                 refreshTime();
271             }
272         }
273 
274         @Override
275         public void onUserSwitchComplete(int userId) {
276             mKeyguardClockSwitchController.refreshFormat();
277         }
278     };
279 
280     private KeyguardStateController.Callback mKeyguardStateControllerCallback =
281             new KeyguardStateController.Callback() {
282         @Override
283         public void onKeyguardShowingChanged() {
284             // If we explicitly re-show the keyguard, make sure that all the child views are
285             // visible. They might have been animating out as part of the SmartSpace shared
286             // element transition.
287             if (mKeyguardStateController.isShowing()) {
288                 mView.setChildrenAlphaExcludingClockView(1f);
289             }
290         }
291     };
292 
293     /**
294      * Rect that specifies how KSV should be clipped, on its parent's coordinates.
295      */
setClipBounds(Rect clipBounds)296     public void setClipBounds(Rect clipBounds) {
297         if (clipBounds != null) {
298             mClipBounds.set(clipBounds.left, (int) (clipBounds.top - mView.getY()),
299                     clipBounds.right, (int) (clipBounds.bottom - mView.getY()));
300             mView.setClipBounds(mClipBounds);
301         } else {
302             mView.setClipBounds(null);
303         }
304     }
305 }
306