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