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.systemui.statusbar.phone;
18 
19 import static android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS;
20 import static android.app.StatusBarManager.DISABLE_SYSTEM_INFO;
21 
22 import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
23 
24 import android.content.res.Configuration;
25 import android.content.res.Resources;
26 import android.database.ContentObserver;
27 import android.hardware.biometrics.BiometricSourceType;
28 import android.os.UserHandle;
29 import android.os.UserManager;
30 import android.provider.Settings;
31 import android.util.MathUtils;
32 import android.view.View;
33 
34 import androidx.annotation.NonNull;
35 import androidx.annotation.VisibleForTesting;
36 import androidx.core.animation.Animator;
37 import androidx.core.animation.AnimatorListenerAdapter;
38 import androidx.core.animation.ValueAnimator;
39 
40 import com.android.app.animation.InterpolatorsAndroidX;
41 import com.android.keyguard.CarrierTextController;
42 import com.android.keyguard.KeyguardUpdateMonitor;
43 import com.android.keyguard.KeyguardUpdateMonitorCallback;
44 import com.android.keyguard.logging.KeyguardLogger;
45 import com.android.systemui.R;
46 import com.android.systemui.battery.BatteryMeterViewController;
47 import com.android.systemui.dagger.qualifiers.Main;
48 import com.android.systemui.log.core.LogLevel;
49 import com.android.systemui.plugins.statusbar.StatusBarStateController;
50 import com.android.systemui.shade.ShadeViewStateProvider;
51 import com.android.systemui.statusbar.CommandQueue;
52 import com.android.systemui.statusbar.NotificationMediaManager;
53 import com.android.systemui.statusbar.StatusBarState;
54 import com.android.systemui.statusbar.SysuiStatusBarStateController;
55 import com.android.systemui.statusbar.disableflags.DisableStateTracker;
56 import com.android.systemui.statusbar.events.SystemStatusAnimationCallback;
57 import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
58 import com.android.systemui.statusbar.notification.AnimatableProperty;
59 import com.android.systemui.statusbar.notification.PropertyAnimator;
60 import com.android.systemui.statusbar.notification.stack.AnimationProperties;
61 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
62 import com.android.systemui.statusbar.phone.fragment.StatusBarIconBlocklistKt;
63 import com.android.systemui.statusbar.phone.fragment.StatusBarSystemEventDefaultAnimator;
64 import com.android.systemui.statusbar.policy.BatteryController;
65 import com.android.systemui.statusbar.policy.ConfigurationController;
66 import com.android.systemui.statusbar.policy.KeyguardStateController;
67 import com.android.systemui.statusbar.policy.UserInfoController;
68 import com.android.systemui.user.ui.viewmodel.StatusBarUserChipViewModel;
69 import com.android.systemui.util.ViewController;
70 import com.android.systemui.util.settings.SecureSettings;
71 
72 import java.io.PrintWriter;
73 import java.util.ArrayList;
74 import java.util.List;
75 import java.util.concurrent.Executor;
76 
77 import javax.inject.Inject;
78 
79 import kotlin.Unit;
80 
81 /** View Controller for {@link com.android.systemui.statusbar.phone.KeyguardStatusBarView}. */
82 public class KeyguardStatusBarViewController extends ViewController<KeyguardStatusBarView> {
83     private static final String TAG = "KeyguardStatusBarViewController";
84     private static final AnimationProperties KEYGUARD_HUN_PROPERTIES =
85             new AnimationProperties().setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
86 
87     private float mKeyguardHeadsUpShowingAmount = 0.0f;
88     private final AnimatableProperty mHeadsUpShowingAmountAnimation = AnimatableProperty.from(
89             "KEYGUARD_HEADS_UP_SHOWING_AMOUNT",
90             (view, aFloat) -> {
91                 mKeyguardHeadsUpShowingAmount = aFloat;
92                 updateViewState();
93             },
94             view -> mKeyguardHeadsUpShowingAmount,
95             R.id.keyguard_hun_animator_tag,
96             R.id.keyguard_hun_animator_end_tag,
97             R.id.keyguard_hun_animator_start_tag);
98 
99     private final CarrierTextController mCarrierTextController;
100     private final ConfigurationController mConfigurationController;
101     private final SystemStatusAnimationScheduler mAnimationScheduler;
102     private final BatteryController mBatteryController;
103     private final UserInfoController mUserInfoController;
104     private final StatusBarIconController mStatusBarIconController;
105     private final StatusBarIconController.TintedIconManager.Factory mTintedIconManagerFactory;
106     private final BatteryMeterViewController mBatteryMeterViewController;
107     private final ShadeViewStateProvider mShadeViewStateProvider;
108     private final KeyguardStateController mKeyguardStateController;
109     private final KeyguardBypassController mKeyguardBypassController;
110     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
111     private final BiometricUnlockController mBiometricUnlockController;
112     private final SysuiStatusBarStateController mStatusBarStateController;
113     private final StatusBarContentInsetsProvider mInsetsProvider;
114     private final UserManager mUserManager;
115     private final StatusBarUserChipViewModel mStatusBarUserChipViewModel;
116     private final SecureSettings mSecureSettings;
117     private final CommandQueue mCommandQueue;
118     private final Executor mMainExecutor;
119     private final Object mLock = new Object();
120     private final KeyguardLogger mLogger;
121 
122     private View mSystemIconsContainer;
123     private final StatusOverlayHoverListenerFactory mStatusOverlayHoverListenerFactory;
124 
125     // TODO(b/273443374): remove
126     private NotificationMediaManager mNotificationMediaManager;
127 
128     private final ConfigurationController.ConfigurationListener mConfigurationListener =
129             new ConfigurationController.ConfigurationListener() {
130                 @Override
131                 public void onDensityOrFontScaleChanged() {
132                     mView.loadDimens();
133                     // The animator is dependent on resources for offsets
134                     mSystemEventAnimator =
135                             getSystemEventAnimator(mSystemEventAnimator.isAnimationRunning());
136                 }
137 
138                 @Override
139                 public void onThemeChanged() {
140                     mView.onOverlayChanged();
141                     KeyguardStatusBarViewController.this.onThemeChanged();
142                 }
143 
144                 @Override
145                 public void onConfigChanged(Configuration newConfig) {
146                     updateUserSwitcher();
147                 }
148             };
149 
150     private final SystemStatusAnimationCallback mAnimationCallback =
151             new SystemStatusAnimationCallback() {
152                 @NonNull
153                 @Override
154                 public Animator onSystemEventAnimationFinish(boolean hasPersistentDot) {
155                     return mSystemEventAnimator.onSystemEventAnimationFinish(hasPersistentDot);
156                 }
157 
158                 @NonNull
159                 @Override
160                 public Animator onSystemEventAnimationBegin() {
161                     return mSystemEventAnimator.onSystemEventAnimationBegin();
162                 }
163             };
164 
165     private final BatteryController.BatteryStateChangeCallback mBatteryStateChangeCallback =
166             new BatteryController.BatteryStateChangeCallback() {
167                 @Override
168                 public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
169                     mView.onBatteryLevelChanged(charging);
170                 }
171             };
172 
173     private final UserInfoController.OnUserInfoChangedListener mOnUserInfoChangedListener =
174             (name, picture, userAccount) -> mView.onUserInfoChanged(picture);
175 
176     private final ValueAnimator.AnimatorUpdateListener mAnimatorUpdateListener =
177             animation -> {
178                 mKeyguardStatusBarAnimateAlpha =
179                         (float) ((ValueAnimator) animation).getAnimatedValue();
180                 updateViewState();
181             };
182 
183     private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
184             new KeyguardUpdateMonitorCallback() {
185                 @Override
186                 public void onBiometricAuthenticated(
187                         int userId,
188                         BiometricSourceType biometricSourceType,
189                         boolean isStrongBiometric) {
190                     if (mFirstBypassAttempt
191                             && mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
192                                     isStrongBiometric)) {
193                         mDelayShowingKeyguardStatusBar = true;
194                     }
195                 }
196 
197                 @Override
198                 public void onKeyguardVisibilityChanged(boolean visible) {
199                     if (visible) {
200                         updateUserSwitcher();
201                     }
202                 }
203 
204                 @Override
205                 public void onBiometricRunningStateChanged(
206                         boolean running,
207                         BiometricSourceType biometricSourceType) {
208                     boolean keyguardOrShadeLocked =
209                             mStatusBarState == KEYGUARD
210                                     || mStatusBarState == StatusBarState.SHADE_LOCKED;
211                     if (!running
212                             && mFirstBypassAttempt
213                             && keyguardOrShadeLocked
214                             && !mDozing
215                             && !mDelayShowingKeyguardStatusBar
216                             && !mBiometricUnlockController.isBiometricUnlock()) {
217                         mFirstBypassAttempt = false;
218                         animateKeyguardStatusBarIn();
219                     }
220                 }
221 
222                 @Override
223                 public void onFinishedGoingToSleep(int why) {
224                     mFirstBypassAttempt = mKeyguardBypassController.getBypassEnabled();
225                     mDelayShowingKeyguardStatusBar = false;
226                 }
227             };
228 
229     private final StatusBarStateController.StateListener mStatusBarStateListener =
230             new StatusBarStateController.StateListener() {
231                 @Override
232                 public void onStateChanged(int newState) {
233                     mStatusBarState = newState;
234                 }
235             };
236 
237 
238     private final DisableStateTracker mDisableStateTracker;
239 
240     private final List<String> mBlockedIcons = new ArrayList<>();
241     private final int mNotificationsHeaderCollideDistance;
242 
243     private boolean mBatteryListening;
244     private StatusBarIconController.TintedIconManager mTintedIconManager;
245 
246     private float mKeyguardStatusBarAnimateAlpha = 1f;
247     /**
248      * If face auth with bypass is running for the first time after you turn on the screen.
249      * (From aod or screen off)
250      */
251     private boolean mFirstBypassAttempt;
252     /**
253      * If auth happens successfully during {@code mFirstBypassAttempt}, and we should wait until
254      * the keyguard is dismissed to show the status bar.
255      */
256     private boolean mDelayShowingKeyguardStatusBar;
257     private int mStatusBarState;
258     private boolean mDozing;
259     private boolean mShowingKeyguardHeadsUp;
260     private StatusBarSystemEventDefaultAnimator mSystemEventAnimator;
261     private float mSystemEventAnimatorAlpha = 1;
262 
263     /**
264      * The alpha value to be set on the View. If -1, this value is to be ignored.
265      */
266     private float mExplicitAlpha = -1f;
267 
268     @Inject
KeyguardStatusBarViewController( KeyguardStatusBarView view, CarrierTextController carrierTextController, ConfigurationController configurationController, SystemStatusAnimationScheduler animationScheduler, BatteryController batteryController, UserInfoController userInfoController, StatusBarIconController statusBarIconController, StatusBarIconController.TintedIconManager.Factory tintedIconManagerFactory, BatteryMeterViewController batteryMeterViewController, ShadeViewStateProvider shadeViewStateProvider, KeyguardStateController keyguardStateController, KeyguardBypassController bypassController, KeyguardUpdateMonitor keyguardUpdateMonitor, BiometricUnlockController biometricUnlockController, SysuiStatusBarStateController statusBarStateController, StatusBarContentInsetsProvider statusBarContentInsetsProvider, UserManager userManager, StatusBarUserChipViewModel userChipViewModel, SecureSettings secureSettings, CommandQueue commandQueue, @Main Executor mainExecutor, KeyguardLogger logger, NotificationMediaManager notificationMediaManager, StatusOverlayHoverListenerFactory statusOverlayHoverListenerFactory )269     public KeyguardStatusBarViewController(
270             KeyguardStatusBarView view,
271             CarrierTextController carrierTextController,
272             ConfigurationController configurationController,
273             SystemStatusAnimationScheduler animationScheduler,
274             BatteryController batteryController,
275             UserInfoController userInfoController,
276             StatusBarIconController statusBarIconController,
277             StatusBarIconController.TintedIconManager.Factory tintedIconManagerFactory,
278             BatteryMeterViewController batteryMeterViewController,
279             ShadeViewStateProvider shadeViewStateProvider,
280             KeyguardStateController keyguardStateController,
281             KeyguardBypassController bypassController,
282             KeyguardUpdateMonitor keyguardUpdateMonitor,
283             BiometricUnlockController biometricUnlockController,
284             SysuiStatusBarStateController statusBarStateController,
285             StatusBarContentInsetsProvider statusBarContentInsetsProvider,
286             UserManager userManager,
287             StatusBarUserChipViewModel userChipViewModel,
288             SecureSettings secureSettings,
289             CommandQueue commandQueue,
290             @Main Executor mainExecutor,
291             KeyguardLogger logger,
292             NotificationMediaManager notificationMediaManager,
293             StatusOverlayHoverListenerFactory statusOverlayHoverListenerFactory
294     ) {
295         super(view);
296         mCarrierTextController = carrierTextController;
297         mConfigurationController = configurationController;
298         mAnimationScheduler = animationScheduler;
299         mBatteryController = batteryController;
300         mUserInfoController = userInfoController;
301         mStatusBarIconController = statusBarIconController;
302         mTintedIconManagerFactory = tintedIconManagerFactory;
303         mBatteryMeterViewController = batteryMeterViewController;
304         mShadeViewStateProvider = shadeViewStateProvider;
305         mKeyguardStateController = keyguardStateController;
306         mKeyguardBypassController = bypassController;
307         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
308         mBiometricUnlockController = biometricUnlockController;
309         mStatusBarStateController = statusBarStateController;
310         mInsetsProvider = statusBarContentInsetsProvider;
311         mUserManager = userManager;
312         mStatusBarUserChipViewModel = userChipViewModel;
313         mSecureSettings = secureSettings;
314         mCommandQueue = commandQueue;
315         mMainExecutor = mainExecutor;
316         mLogger = logger;
317 
318         mFirstBypassAttempt = mKeyguardBypassController.getBypassEnabled();
319         mKeyguardStateController.addCallback(
320                 new KeyguardStateController.Callback() {
321                     @Override
322                     public void onKeyguardFadingAwayChanged() {
323                         if (!mKeyguardStateController.isKeyguardFadingAway()) {
324                             mFirstBypassAttempt = false;
325                             mDelayShowingKeyguardStatusBar = false;
326                         }
327                     }
328                 }
329         );
330 
331         Resources r = getResources();
332         updateBlockedIcons();
333         mNotificationsHeaderCollideDistance = r.getDimensionPixelSize(
334                 R.dimen.header_notifications_collide_distance);
335 
336         mView.setKeyguardUserAvatarEnabled(
337                 !mStatusBarUserChipViewModel.getChipEnabled());
338         mSystemEventAnimator = getSystemEventAnimator(/* isAnimationRunning */ false);
339 
340         mDisableStateTracker = new DisableStateTracker(
341                 /* mask1= */ DISABLE_SYSTEM_INFO,
342                 /* mask2= */ DISABLE2_SYSTEM_ICONS,
343                 this::updateViewState
344         );
345         mNotificationMediaManager = notificationMediaManager;
346         mStatusOverlayHoverListenerFactory = statusOverlayHoverListenerFactory;
347     }
348 
349     @Override
onInit()350     protected void onInit() {
351         super.onInit();
352         mCarrierTextController.init();
353         mBatteryMeterViewController.init();
354     }
355 
356     @Override
onViewAttached()357     protected void onViewAttached() {
358         mView.init(mStatusBarUserChipViewModel);
359         mConfigurationController.addCallback(mConfigurationListener);
360         mAnimationScheduler.addCallback(mAnimationCallback);
361         mUserInfoController.addCallback(mOnUserInfoChangedListener);
362         mStatusBarStateController.addCallback(mStatusBarStateListener);
363         mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
364         mDisableStateTracker.startTracking(mCommandQueue, mView.getDisplay().getDisplayId());
365         if (mTintedIconManager == null) {
366             mTintedIconManager = mTintedIconManagerFactory.create(
367                     mView.findViewById(R.id.statusIcons), StatusBarLocation.KEYGUARD);
368             mTintedIconManager.setBlockList(getBlockedIcons());
369             mStatusBarIconController.addIconGroup(mTintedIconManager);
370         }
371         mSystemIconsContainer = mView.findViewById(R.id.system_icons);
372         StatusOverlayHoverListener hoverListener = mStatusOverlayHoverListenerFactory
373                 .createDarkAwareListener(mSystemIconsContainer, mView.darkChangeFlow());
374         mSystemIconsContainer.setOnHoverListener(hoverListener);
375         mView.setOnApplyWindowInsetsListener(
376                 (view, windowInsets) -> mView.updateWindowInsets(windowInsets, mInsetsProvider));
377         mSecureSettings.registerContentObserverForUser(
378                 Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON,
379                 false,
380                 mVolumeSettingObserver,
381                 UserHandle.USER_ALL);
382         updateUserSwitcher();
383         onThemeChanged();
384     }
385 
386     @Override
onViewDetached()387     protected void onViewDetached() {
388         mSystemIconsContainer.setOnHoverListener(null);
389         mConfigurationController.removeCallback(mConfigurationListener);
390         mAnimationScheduler.removeCallback(mAnimationCallback);
391         mUserInfoController.removeCallback(mOnUserInfoChangedListener);
392         mStatusBarStateController.removeCallback(mStatusBarStateListener);
393         mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateMonitorCallback);
394         mDisableStateTracker.stopTracking(mCommandQueue);
395         mSecureSettings.unregisterContentObserver(mVolumeSettingObserver);
396         if (mTintedIconManager != null) {
397             mStatusBarIconController.removeIconGroup(mTintedIconManager);
398         }
399     }
400 
401     /** Should be called when the theme changes. */
onThemeChanged()402     public void onThemeChanged() {
403         mView.onThemeChanged(mTintedIconManager);
404     }
405 
406     /** Sets whether user switcher is enabled. */
setKeyguardUserSwitcherEnabled(boolean enabled)407     public void setKeyguardUserSwitcherEnabled(boolean enabled) {
408         mView.setKeyguardUserSwitcherEnabled(enabled);
409     }
410 
411     /** Sets whether this controller should listen to battery updates. */
setBatteryListening(boolean listening)412     public void setBatteryListening(boolean listening) {
413         if (listening == mBatteryListening) {
414             return;
415         }
416         mBatteryListening = listening;
417         if (mBatteryListening) {
418             mBatteryController.addCallback(mBatteryStateChangeCallback);
419         } else {
420             mBatteryController.removeCallback(mBatteryStateChangeCallback);
421         }
422     }
423 
424     /** Set the view to have no top clipping. */
setNoTopClipping()425     public void setNoTopClipping() {
426         mView.setTopClipping(0);
427     }
428 
429     /**
430      * Update the view's top clipping based on the value of notificationPanelTop and the view's
431      * current top.
432      *
433      * @param notificationPanelTop the current top of the notification panel view.
434      */
updateTopClipping(int notificationPanelTop)435     public void updateTopClipping(int notificationPanelTop) {
436         mView.setTopClipping(notificationPanelTop - mView.getTop());
437     }
438 
439     /** Sets the dozing state. */
setDozing(boolean dozing)440     public void setDozing(boolean dozing) {
441         mDozing = dozing;
442     }
443 
444     /** Animate the keyguard status bar in. */
animateKeyguardStatusBarIn()445     public void animateKeyguardStatusBarIn() {
446         mLogger.log(TAG, LogLevel.DEBUG, "animating status bar in");
447         if (mDisableStateTracker.isDisabled()) {
448             // If our view is disabled, don't allow us to animate in.
449             return;
450         }
451         mView.setVisibility(View.VISIBLE);
452         mView.setAlpha(0f);
453         ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
454         anim.addUpdateListener(mAnimatorUpdateListener);
455         anim.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
456         anim.setInterpolator(InterpolatorsAndroidX.LINEAR_OUT_SLOW_IN);
457         anim.start();
458     }
459 
460     /** Animate the keyguard status bar out. */
animateKeyguardStatusBarOut(long startDelay, long duration)461     public void animateKeyguardStatusBarOut(long startDelay, long duration) {
462         mLogger.log(TAG, LogLevel.DEBUG, "animating status bar out");
463         ValueAnimator anim = ValueAnimator.ofFloat(mView.getAlpha(), 0f);
464         anim.addUpdateListener(mAnimatorUpdateListener);
465         anim.setStartDelay(startDelay);
466         anim.setDuration(duration);
467         anim.setInterpolator(InterpolatorsAndroidX.LINEAR_OUT_SLOW_IN);
468         anim.addListener(new AnimatorListenerAdapter() {
469             @Override
470             public void onAnimationEnd(Animator animation) {
471                 mView.setVisibility(View.INVISIBLE);
472                 mView.setAlpha(1f);
473                 mKeyguardStatusBarAnimateAlpha = 1f;
474             }
475         });
476         anim.start();
477     }
478 
479     /**
480      * Updates the {@link KeyguardStatusBarView} state based on what the
481      * {@link ShadeViewController.NotificationPanelViewStateProvider} and other
482      * controllers provide.
483      */
updateViewState()484     public void updateViewState() {
485         if (!isKeyguardShowing()) {
486             return;
487         }
488 
489         float alphaQsExpansion = 1 - Math.min(
490                 1, mShadeViewStateProvider.getLockscreenShadeDragProgress() * 2);
491 
492         float newAlpha;
493         if (mExplicitAlpha != -1) {
494             newAlpha = mExplicitAlpha;
495         } else {
496             newAlpha = Math.min(getKeyguardContentsAlpha(), alphaQsExpansion)
497                     * mKeyguardStatusBarAnimateAlpha
498                     * (1.0f - mKeyguardHeadsUpShowingAmount);
499         }
500 
501         if (mSystemEventAnimator.isAnimationRunning()
502                 && !mNotificationMediaManager.isLockscreenWallpaperOnNotificationShade()) {
503             newAlpha = Math.min(newAlpha, mSystemEventAnimatorAlpha);
504         } else {
505             mView.setTranslationX(0);
506         }
507 
508         boolean hideForBypass =
509                 mFirstBypassAttempt && mKeyguardUpdateMonitor.shouldListenForFace()
510                         || mDelayShowingKeyguardStatusBar;
511         int newVisibility =
512                 newAlpha != 0f
513                         && !mDozing
514                         && !hideForBypass
515                         && !mDisableStateTracker.isDisabled()
516                         ? View.VISIBLE : View.INVISIBLE;
517 
518         updateViewState(newAlpha, newVisibility);
519     }
520 
521     /**
522      * Updates the {@link KeyguardStatusBarView} state based on the provided values.
523      */
updateViewState(float alpha, int visibility)524     public void updateViewState(float alpha, int visibility) {
525         if (mDisableStateTracker.isDisabled()) {
526             visibility = View.INVISIBLE;
527         }
528         mView.setAlpha(alpha);
529         mView.setVisibility(visibility);
530     }
531 
532     /**
533      * @return the alpha to be used to fade out the contents on Keyguard (status bar, bottom area)
534      * during swiping up.
535      */
getKeyguardContentsAlpha()536     private float getKeyguardContentsAlpha() {
537         float alpha;
538         if (isKeyguardShowing()) {
539             // When on Keyguard, we hide the header as soon as we expanded close enough to the
540             // header
541             alpha = mShadeViewStateProvider.getPanelViewExpandedHeight()
542                     / (mView.getHeight() + mNotificationsHeaderCollideDistance);
543         } else {
544             // In SHADE_LOCKED, the top card is already really close to the header. Hide it as
545             // soon as we start translating the stack.
546             alpha = mShadeViewStateProvider.getPanelViewExpandedHeight()
547                     / mView.getHeight();
548         }
549         alpha = MathUtils.saturate(alpha);
550         alpha = (float) Math.pow(alpha, 0.75);
551         return alpha;
552     }
553 
554     /**
555      * Updates visibility of the user switcher button based on {@link android.os.UserManager} state.
556      */
updateUserSwitcher()557     private void updateUserSwitcher() {
558         mView.setUserSwitcherEnabled(mUserManager.isUserSwitcherEnabled(getResources().getBoolean(
559                 R.bool.qs_show_user_switcher_for_single_user)));
560     }
561 
562     @VisibleForTesting
updateBlockedIcons()563     void updateBlockedIcons() {
564         List<String> newBlockList = StatusBarIconBlocklistKt
565                 .getStatusBarIconBlocklist(getResources(), mSecureSettings);
566 
567         synchronized (mLock) {
568             mBlockedIcons.clear();
569             mBlockedIcons.addAll(newBlockList);
570         }
571 
572         mMainExecutor.execute(() -> {
573             if (mTintedIconManager != null) {
574                 mTintedIconManager.setBlockList(getBlockedIcons());
575             }
576         });
577     }
578 
579     @VisibleForTesting
getBlockedIcons()580     List<String> getBlockedIcons() {
581         synchronized (mLock) {
582             return new ArrayList<>(mBlockedIcons);
583         }
584     }
585 
586     /**
587       Update {@link KeyguardStatusBarView}'s visibility based on whether keyguard is showing and
588      * whether heads up is visible.
589      */
updateForHeadsUp()590     public void updateForHeadsUp() {
591         updateForHeadsUp(true);
592     }
593 
updateForHeadsUp(boolean animate)594     void updateForHeadsUp(boolean animate) {
595         boolean showingKeyguardHeadsUp =
596                 isKeyguardShowing() && mShadeViewStateProvider.shouldHeadsUpBeVisible();
597         if (mShowingKeyguardHeadsUp != showingKeyguardHeadsUp) {
598             mShowingKeyguardHeadsUp = showingKeyguardHeadsUp;
599             if (isKeyguardShowing()) {
600                 PropertyAnimator.setProperty(
601                         mView,
602                         mHeadsUpShowingAmountAnimation,
603                         showingKeyguardHeadsUp ? 1.0f : 0.0f,
604                         KEYGUARD_HUN_PROPERTIES,
605                         animate);
606             } else {
607                 PropertyAnimator.applyImmediately(mView, mHeadsUpShowingAmountAnimation, 0.0f);
608             }
609         }
610     }
611 
isKeyguardShowing()612     private boolean isKeyguardShowing() {
613         return mStatusBarState == KEYGUARD;
614     }
615 
616     /** */
dump(PrintWriter pw, String[] args)617     public void dump(PrintWriter pw, String[] args) {
618         pw.println("KeyguardStatusBarView:");
619         pw.println("  mBatteryListening: " + mBatteryListening);
620         pw.println("  mExplicitAlpha: " + mExplicitAlpha);
621         pw.println("  alpha: " + mView.getAlpha());
622         pw.println("  visibility: " + mView.getVisibility());
623         mView.dump(pw, args);
624     }
625 
626     /**
627      * Sets the alpha to be set on the view.
628      *
629      * @param alpha a value between 0 and 1. -1 if the value is to be reset/ignored.
630      */
setAlpha(float alpha)631     public void setAlpha(float alpha) {
632         mExplicitAlpha = alpha;
633         updateViewState();
634     }
635 
636     private final ContentObserver mVolumeSettingObserver = new ContentObserver(null) {
637         @Override
638         public void onChange(boolean selfChange) {
639             updateBlockedIcons();
640         }
641     };
642 
getSystemEventAnimator(boolean isAnimationRunning)643     private StatusBarSystemEventDefaultAnimator getSystemEventAnimator(boolean isAnimationRunning) {
644         return new StatusBarSystemEventDefaultAnimator(getResources(), (alpha) -> {
645             // TODO(b/273443374): remove if-else condition
646             if (!mNotificationMediaManager.isLockscreenWallpaperOnNotificationShade()) {
647                 mSystemEventAnimatorAlpha = alpha;
648             } else {
649                 mSystemEventAnimatorAlpha = 1f;
650             }
651             updateViewState();
652             return Unit.INSTANCE;
653         }, (translationX) -> {
654             // TODO(b/273443374): remove if-else condition
655             if (!mNotificationMediaManager.isLockscreenWallpaperOnNotificationShade()) {
656                 mView.setTranslationX(translationX);
657             } else {
658                 mView.setTranslationX(0);
659             }
660             return Unit.INSTANCE;
661         }, isAnimationRunning);
662     }
663 }
664