From 826eefe0ee7d844080c779cdab16b755dc497983 Mon Sep 17 00:00:00 2001 From: Jeff DeCew Date: Thu, 19 Jan 2023 21:21:05 +0000 Subject: [PATCH] Hack: Clear the mDozeAmount=1 override when switching to SHADE to fix notifications going invisible Another bug has come up where the (AmbientState) dozeAmount==1 triggers notifications to disappear when expansion==1. The NotificationWakeUpCoordinator state and logs indicate that this state persists because of the bypass override. Digging in, this appears to be the result of the bypass state changing in a way that class never expected. This change attempts to track when the doze amount is overridden to 1, and allow that override to be reset when the keyguard state changes away from KEYGUARD. Additionally, when unfolding from the LS, the bypass state change wasn't triggering the clear, so before this change even if the eventual unlock fixed the notification state, the inside lockscreen could be left in the wrong state. The bypass state listener which checks and conditionally clears the override is enough to fix that bug as well. Fixes: 265626464 Test: manual repro of notifications disappearing: 1) tap to wake, 2) trigger face auth, 3) unfold quickly, 4) check shade (and logs) for symptom. Test: manual repro of bypass state when unfolded: 1) tap to wake, 2) do not show face 3) unfold, 4) see only icons (no notifications) on inside screen. Change-Id: I8dacae4aeb0dbb6c744643acd1b0122fd4f3eb22 --- .../NotificationWakeUpCoordinator.kt | 61 +++++++++++++++++-- .../NotificationWakeUpCoordinatorLogger.kt | 19 ++++++ 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt index aeae89cb3223e..7e53d5431353f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt @@ -31,6 +31,7 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackScroll import com.android.systemui.statusbar.notification.stack.StackStateAnimator import com.android.systemui.statusbar.phone.DozeParameters import com.android.systemui.statusbar.phone.KeyguardBypassController +import com.android.systemui.statusbar.phone.KeyguardBypassController.OnBypassStateChangedListener import com.android.systemui.statusbar.phone.ScreenOffAnimationController import com.android.systemui.statusbar.policy.HeadsUpManager import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener @@ -38,7 +39,6 @@ import java.io.PrintWriter import javax.inject.Inject import kotlin.math.min - @SysUISingleton class NotificationWakeUpCoordinator @Inject constructor( dumpManager: DumpManager, @@ -68,6 +68,7 @@ class NotificationWakeUpCoordinator @Inject constructor( private var mLinearDozeAmount: Float = 0.0f private var mDozeAmount: Float = 0.0f private var mDozeAmountSource: String = "init" + private var mNotifsHiddenByDozeAmountOverride: Boolean = false private var mNotificationVisibleAmount = 0.0f private var mNotificationsVisible = false private var mNotificationsVisibleForExpansion = false @@ -130,6 +131,7 @@ class NotificationWakeUpCoordinator @Inject constructor( } } } + /** * True if we can show pulsing heads up notifications */ @@ -149,10 +151,19 @@ class NotificationWakeUpCoordinator @Inject constructor( return canShow } + private val bypassStateChangedListener = object : OnBypassStateChangedListener { + override fun onBypassStateChanged(isEnabled: Boolean) { + // When the bypass state changes, we have to check whether we should re-show the + // notifications by clearing the doze amount override which hides them. + maybeClearDozeAmountOverrideHidingNotifs() + } + } + init { dumpManager.registerDumpable(this) mHeadsUpManager.addListener(this) statusBarStateController.addCallback(this) + bypassController.registerOnBypassStateChangedListener(bypassStateChangedListener) addListener(object : WakeUpListener { override fun onFullyHiddenChanged(isFullyHidden: Boolean) { if (isFullyHidden && mNotificationsVisibleForExpansion) { @@ -261,12 +272,18 @@ class NotificationWakeUpCoordinator @Inject constructor( setDozeAmount(linear, eased, source = "StatusBar") } - fun setDozeAmount(linear: Float, eased: Float, source: String) { + fun setDozeAmount( + linear: Float, + eased: Float, + source: String, + hidesNotifsByOverride: Boolean = false + ) { val changed = linear != mLinearDozeAmount logger.logSetDozeAmount(linear, eased, source, statusBarStateController.state, changed) mLinearDozeAmount = linear mDozeAmount = eased mDozeAmountSource = source + mNotifsHiddenByDozeAmountOverride = hidesNotifsByOverride mStackScrollerController.setDozeAmount(mDozeAmount) updateHideAmount() if (changed && linear == 0.0f) { @@ -295,6 +312,8 @@ class NotificationWakeUpCoordinator @Inject constructor( return } + maybeClearDozeAmountOverrideHidingNotifs() + if (bypassController.bypassEnabled && newState == StatusBarState.KEYGUARD && state == StatusBarState.SHADE_LOCKED && (!statusBarStateController.isDozing || shouldAnimateVisibility())) { @@ -325,7 +344,8 @@ class NotificationWakeUpCoordinator @Inject constructor( private fun overrideDozeAmountIfBypass(): Boolean { if (bypassController.bypassEnabled) { if (statusBarStateController.state == StatusBarState.KEYGUARD) { - setDozeAmount(1f, 1f, source = "Override: bypass (keyguard)") + setDozeAmount(1f, 1f, source = "Override: bypass (keyguard)", + hidesNotifsByOverride = true) } else { setDozeAmount(0f, 0f, source = "Override: bypass (shade)") } @@ -334,6 +354,37 @@ class NotificationWakeUpCoordinator @Inject constructor( return false } + /** + * If the last [setDozeAmount] call was an override to hide notifications, then this call will + * check for the set of states that may have caused that override, and if none of them still + * apply, and the device is awake or not on the keyguard, then dozeAmount will be reset to 0. + * This fixes bugs where the bypass state changing could result in stale overrides, hiding + * notifications either on the inside screen or even after unlock. + */ + private fun maybeClearDozeAmountOverrideHidingNotifs() { + if (mNotifsHiddenByDozeAmountOverride) { + val onKeyguard = statusBarStateController.state == StatusBarState.KEYGUARD + val dozing = statusBarStateController.isDozing + val bypass = bypassController.bypassEnabled + val animating = + screenOffAnimationController.overrideNotificationsFullyDozingOnKeyguard() + // Overrides are set by [overrideDozeAmountIfAnimatingScreenOff] and + // [overrideDozeAmountIfBypass] based on 'animating' and 'bypass' respectively, so only + // clear the override if both those conditions are cleared. But also require either + // !dozing or !onKeyguard because those conditions should indicate that we intend + // notifications to be visible, and thus it is safe to unhide them. + val willRemove = (!onKeyguard || !dozing) && !bypass && !animating + logger.logMaybeClearDozeAmountOverrideHidingNotifs( + willRemove = willRemove, + onKeyguard = onKeyguard, dozing = dozing, + bypass = bypass, animating = animating, + ) + if (willRemove) { + setDozeAmount(0f, 0f, source = "Removed: $mDozeAmountSource") + } + } + } + /** * If we're playing the screen off animation, force the notification doze amount to be 1f (fully * dozing). This is needed so that the notifications aren't briefly visible as the screen turns @@ -344,7 +395,8 @@ class NotificationWakeUpCoordinator @Inject constructor( */ private fun overrideDozeAmountIfAnimatingScreenOff(linearDozeAmount: Float): Boolean { if (screenOffAnimationController.overrideNotificationsFullyDozingOnKeyguard()) { - setDozeAmount(1f, 1f, source = "Override: animating screen off") + setDozeAmount(1f, 1f, source = "Override: animating screen off", + hidesNotifsByOverride = true) return true } @@ -430,6 +482,7 @@ class NotificationWakeUpCoordinator @Inject constructor( pw.println("mLinearDozeAmount: $mLinearDozeAmount") pw.println("mDozeAmount: $mDozeAmount") pw.println("mDozeAmountSource: $mDozeAmountSource") + pw.println("mNotifsHiddenByDozeAmountOverride: $mNotifsHiddenByDozeAmountOverride") pw.println("mNotificationVisibleAmount: $mNotificationVisibleAmount") pw.println("mNotificationsVisible: $mNotificationsVisible") pw.println("mNotificationsVisibleForExpansion: $mNotificationsVisibleForExpansion") diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt index de18b0c4307d1..44645315ca802 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt @@ -46,6 +46,25 @@ constructor(@NotificationLog private val buffer: LogBuffer) { ) } + fun logMaybeClearDozeAmountOverrideHidingNotifs( + willRemove: Boolean, + onKeyguard: Boolean, + dozing: Boolean, + bypass: Boolean, + animating: Boolean, + ) { + buffer.log( + TAG, + DEBUG, + { + str1 = + "willRemove=$willRemove onKeyguard=$onKeyguard dozing=$dozing" + + " bypass=$bypass animating=$animating" + }, + { "maybeClearDozeAmountOverrideHidingNotifs() $str1" } + ) + } + fun logOnDozeAmountChanged(linear: Float, eased: Float) { buffer.log( TAG,