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