Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 826eefe0 authored by Jeff DeCew's avatar Jeff DeCew
Browse files

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
parent ef056c36
Loading
Loading
Loading
Loading
+57 −4
Original line number Diff line number Diff line
@@ -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")
+19 −0
Original line number Diff line number Diff line
@@ -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,