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

Commit a720cb3a authored by Lyn's avatar Lyn Committed by Lyn Han
Browse files

Visual suppression: add emergency HUNs to allowlist

Fixes: 340550243
Test: VisualInterruptionDecisionProviderImplTest
Flag: ACONFIG notification_avalanche_suppression TEAMFOOD
Change-Id: I3a68def2906973b3ed67a15513a9e8c7aeb4b4ca
parent f5bd0fcd
Loading
Loading
Loading
Loading
+16 −4
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.systemui.statusbar.notification.interruption

import android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST
import android.app.Notification
import android.app.Notification.BubbleMetadata
import android.app.Notification.CATEGORY_EVENT
@@ -23,6 +24,8 @@ import android.app.Notification.CATEGORY_REMINDER
import android.app.Notification.VISIBILITY_PRIVATE
import android.app.NotificationManager.IMPORTANCE_DEFAULT
import android.app.NotificationManager.IMPORTANCE_HIGH
import android.content.pm.PackageManager
import android.content.pm.PackageManager.PERMISSION_GRANTED
import android.database.ContentObserver
import android.hardware.display.AmbientDisplayConfiguration
import android.os.Handler
@@ -234,6 +237,7 @@ class AvalancheSuppressor(
    private val avalancheProvider: AvalancheProvider,
    private val systemClock: SystemClock,
    private val systemSettings: SystemSettings,
    private val packageManager: PackageManager,
) :
    VisualInterruptionFilter(
        types = setOf(PEEK, PULSE),
@@ -249,6 +253,7 @@ class AvalancheSuppressor(
        ALLOW_CATEGORY_EVENT,
        ALLOW_FSI_WITH_PERMISSION_ON,
        ALLOW_COLORIZED,
        ALLOW_EMERGENCY,
        SUPPRESS
    }

@@ -299,13 +304,20 @@ class AvalancheSuppressor(
        if (entry.sbn.notification.isColorized) {
            return State.ALLOW_COLORIZED
        }
        if (entry.sbn.notification.isColorized) {
            return State.ALLOW_COLORIZED
        }
        if (
            packageManager.checkPermission(RECEIVE_EMERGENCY_BROADCAST, entry.sbn.packageName) ==
                PERMISSION_GRANTED
        ) {
            return State.ALLOW_EMERGENCY
        }
        return State.SUPPRESS
    }

    private fun isCooldownEnabled(): Boolean {
        return systemSettings.getInt(
            Settings.System.NOTIFICATION_COOLDOWN_ENABLED,
            /* def */ 1
        ) == 1
        return systemSettings.getInt(Settings.System.NOTIFICATION_COOLDOWN_ENABLED, /* def */ 1) ==
            1
    }
}
+18 −9
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */
package com.android.systemui.statusbar.notification.interruption

import android.content.pm.PackageManager
import android.hardware.display.AmbientDisplayConfiguration
import android.os.Handler
import android.os.PowerManager
@@ -63,7 +64,8 @@ constructor(
    private val uiEventLogger: UiEventLogger,
    private val userTracker: UserTracker,
    private val avalancheProvider: AvalancheProvider,
    private val systemSettings: SystemSettings
    private val systemSettings: SystemSettings,
    private val packageManager: PackageManager
) : VisualInterruptionDecisionProvider {

    init {
@@ -172,7 +174,9 @@ constructor(
        addFilter(AlertKeyguardVisibilitySuppressor(keyguardNotificationVisibilityProvider))

        if (NotificationAvalancheSuppression.isEnabled) {
            addFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings))
            addFilter(
                AvalancheSuppressor(avalancheProvider, systemClock, systemSettings, packageManager)
            )
            avalancheProvider.register()
        }
        started = true
@@ -232,13 +236,16 @@ constructor(

    private fun makeLoggablePeekDecision(entry: NotificationEntry): LoggableDecision =
        checkConditions(PEEK)
            ?: checkFilters(PEEK, entry) ?: checkSuppressInterruptions(entry)
                ?: checkSuppressAwakeInterruptions(entry) ?: checkSuppressAwakeHeadsUp(entry)
            ?: checkFilters(PEEK, entry)
            ?: checkSuppressInterruptions(entry)
            ?: checkSuppressAwakeInterruptions(entry)
            ?: checkSuppressAwakeHeadsUp(entry)
            ?: LoggableDecision.unsuppressed

    private fun makeLoggablePulseDecision(entry: NotificationEntry): LoggableDecision =
        checkConditions(PULSE)
            ?: checkFilters(PULSE, entry) ?: checkSuppressInterruptions(entry)
            ?: checkFilters(PULSE, entry)
            ?: checkSuppressInterruptions(entry)
            ?: LoggableDecision.unsuppressed

    override fun makeAndLogBubbleDecision(entry: NotificationEntry): Decision =
@@ -252,8 +259,10 @@ constructor(

    private fun makeLoggableBubbleDecision(entry: NotificationEntry): LoggableDecision =
        checkConditions(BUBBLE)
            ?: checkFilters(BUBBLE, entry) ?: checkSuppressInterruptions(entry)
                ?: checkSuppressAwakeInterruptions(entry) ?: LoggableDecision.unsuppressed
            ?: checkFilters(BUBBLE, entry)
            ?: checkSuppressInterruptions(entry)
            ?: checkSuppressAwakeInterruptions(entry)
            ?: LoggableDecision.unsuppressed

    private fun logDecision(
        type: VisualInterruptionType,
+100 −41
Original line number Diff line number Diff line
@@ -16,9 +16,11 @@

package com.android.systemui.statusbar.notification.interruption

import android.Manifest.permission
import android.app.Notification.CATEGORY_EVENT
import android.app.Notification.CATEGORY_REMINDER
import android.app.NotificationManager
import android.content.pm.PackageManager.PERMISSION_GRANTED
import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -28,6 +30,8 @@ import com.android.systemui.statusbar.notification.interruption.VisualInterrupti
import com.android.systemui.statusbar.notification.interruption.VisualInterruptionType.PULSE
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.anyString
import org.mockito.Mockito.`when`

@SmallTest
@RunWith(AndroidJUnit4::class)
@@ -51,7 +55,8 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro
            uiEventLogger,
            userTracker,
            avalancheProvider,
            systemSettings
            systemSettings,
            packageManager
        )
    }

@@ -83,14 +88,18 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro
    fun testAvalancheFilter_duringAvalanche_allowConversationFromAfterEvent() {
        avalancheProvider.startTime = whenAgo(10)

        withFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings)) {
        withFilter(
            AvalancheSuppressor(avalancheProvider, systemClock, systemSettings, packageManager)
        ) {
            ensurePeekState()
            assertShouldHeadsUp(buildEntry {
            assertShouldHeadsUp(
                buildEntry {
                    importance = NotificationManager.IMPORTANCE_HIGH
                    isConversation = true
                    isImportantConversation = false
                    whenMs = whenAgo(5)
            })
                }
            )
        }
    }

@@ -98,14 +107,18 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro
    fun testAvalancheFilter_duringAvalanche_suppressConversationFromBeforeEvent() {
        avalancheProvider.startTime = whenAgo(10)

        withFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings)) {
        withFilter(
            AvalancheSuppressor(avalancheProvider, systemClock, systemSettings, packageManager)
        ) {
            ensurePeekState()
            assertShouldNotHeadsUp(buildEntry {
            assertShouldNotHeadsUp(
                buildEntry {
                    importance = NotificationManager.IMPORTANCE_DEFAULT
                    isConversation = true
                    isImportantConversation = false
                    whenMs = whenAgo(15)
            })
                }
            )
        }
    }

@@ -113,12 +126,16 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro
    fun testAvalancheFilter_duringAvalanche_allowHighPriorityConversation() {
        avalancheProvider.startTime = whenAgo(10)

        withFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings)) {
        withFilter(
            AvalancheSuppressor(avalancheProvider, systemClock, systemSettings, packageManager)
        ) {
            ensurePeekState()
            assertShouldHeadsUp(buildEntry {
            assertShouldHeadsUp(
                buildEntry {
                    importance = NotificationManager.IMPORTANCE_HIGH
                    isImportantConversation = true
            })
                }
            )
        }
    }

@@ -126,12 +143,16 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro
    fun testAvalancheFilter_duringAvalanche_allowCall() {
        avalancheProvider.startTime = whenAgo(10)

        withFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings)) {
        withFilter(
            AvalancheSuppressor(avalancheProvider, systemClock, systemSettings, packageManager)
        ) {
            ensurePeekState()
            assertShouldHeadsUp(buildEntry {
            assertShouldHeadsUp(
                buildEntry {
                    importance = NotificationManager.IMPORTANCE_HIGH
                    isCall = true
            })
                }
            )
        }
    }

@@ -139,12 +160,16 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro
    fun testAvalancheFilter_duringAvalanche_allowCategoryReminder() {
        avalancheProvider.startTime = whenAgo(10)

        withFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings)) {
        withFilter(
            AvalancheSuppressor(avalancheProvider, systemClock, systemSettings, packageManager)
        ) {
            ensurePeekState()
            assertShouldHeadsUp(buildEntry {
            assertShouldHeadsUp(
                buildEntry {
                    importance = NotificationManager.IMPORTANCE_HIGH
                    category = CATEGORY_REMINDER
            })
                }
            )
        }
    }

@@ -152,12 +177,16 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro
    fun testAvalancheFilter_duringAvalanche_allowCategoryEvent() {
        avalancheProvider.startTime = whenAgo(10)

        withFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings)) {
        withFilter(
            AvalancheSuppressor(avalancheProvider, systemClock, systemSettings, packageManager)
        ) {
            ensurePeekState()
            assertShouldHeadsUp(buildEntry {
            assertShouldHeadsUp(
                buildEntry {
                    importance = NotificationManager.IMPORTANCE_HIGH
                    category = CATEGORY_EVENT
            })
                }
            )
        }
    }

@@ -165,7 +194,9 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro
    fun testAvalancheFilter_duringAvalanche_allowFsi() {
        avalancheProvider.startTime = whenAgo(10)

        withFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings)) {
        withFilter(
            AvalancheSuppressor(avalancheProvider, systemClock, systemSettings, packageManager)
        ) {
            assertFsiNotSuppressed()
        }
    }
@@ -174,15 +205,43 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro
    fun testAvalancheFilter_duringAvalanche_allowColorized() {
        avalancheProvider.startTime = whenAgo(10)

        withFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings)) {
        withFilter(
            AvalancheSuppressor(avalancheProvider, systemClock, systemSettings, packageManager)
        ) {
            ensurePeekState()
            assertShouldHeadsUp(buildEntry {
            assertShouldHeadsUp(
                buildEntry {
                    importance = NotificationManager.IMPORTANCE_HIGH
                    isColorized = true
            })
                }
            )
        }
    }

    @Test
    fun testAvalancheFilter_duringAvalanche_allowEmergency() {
        avalancheProvider.startTime = whenAgo(10)

        `when`(
            packageManager.checkPermission(
                org.mockito.Mockito.eq(permission.RECEIVE_EMERGENCY_BROADCAST),
                anyString()
            )
        ).thenReturn(PERMISSION_GRANTED)

        withFilter(
            AvalancheSuppressor(avalancheProvider, systemClock, systemSettings, packageManager)
        ) {
            ensurePeekState()
            assertShouldHeadsUp(
                buildEntry {
                    importance = NotificationManager.IMPORTANCE_HIGH
                }
            )
        }
    }


    @Test
    fun testPeekCondition_suppressesOnlyPeek() {
        withCondition(TestCondition(types = setOf(PEEK)) { true }) {
+2 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ import android.app.PendingIntent
import android.app.PendingIntent.FLAG_MUTABLE
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.content.pm.UserInfo
import android.graphics.drawable.Icon
import android.hardware.display.FakeAmbientDisplayConfiguration
@@ -129,6 +130,7 @@ abstract class VisualInterruptionDecisionProviderTestBase : SysuiTestCase() {
    protected val userTracker = FakeUserTracker()
    protected val avalancheProvider: AvalancheProvider = mock()
    lateinit var systemSettings: SystemSettings
    protected val packageManager: PackageManager = mock()

    protected abstract val provider: VisualInterruptionDecisionProvider

+5 −3
Original line number Diff line number Diff line
@@ -15,11 +15,11 @@
 */
package com.android.systemui.statusbar.notification.interruption

import android.content.pm.PackageManager
import android.hardware.display.AmbientDisplayConfiguration
import android.os.Handler
import android.os.PowerManager
import com.android.internal.logging.UiEventLogger
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.settings.UserTracker
@@ -53,7 +53,8 @@ object VisualInterruptionDecisionProviderTestUtil {
        uiEventLogger: UiEventLogger,
        userTracker: UserTracker,
        avalancheProvider: AvalancheProvider,
        systemSettings: SystemSettings
        systemSettings: SystemSettings,
        packageManager: PackageManager,
    ): VisualInterruptionDecisionProvider {
        return if (VisualInterruptionRefactor.isEnabled) {
            VisualInterruptionDecisionProviderImpl(
@@ -73,7 +74,8 @@ object VisualInterruptionDecisionProviderTestUtil {
                uiEventLogger,
                userTracker,
                avalancheProvider,
                systemSettings
                systemSettings,
                packageManager
            )
        } else {
            NotificationInterruptStateProviderWrapper(
Loading