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

Commit 3abfc4d5 authored by Caitlin Shkuratov's avatar Caitlin Shkuratov
Browse files

[SB][Notif] Don't allow call notif to also show in a promoted notif chip

Currently if an app posts a notification with CallStyle.Ongoing that
*also* meets the promoted notification criteria, the status bar would
incorrectly show 2 chips for the same notification: One because it's a
call, and another because it's promoted.

This CL:
1) Filters out call notifications from promoted notifications so there
   won't be duplicate chips. (Call notifications need to take priority
   over promoted notifications, which is why I'm keeping the call
   notification Flow the same and doing the filtering on the other
   Flow.)
2) Updates the call chip to use the notification's coloring if the call
   notification also matches the promotion criteria. This makes the call
   chip look like a promoted notification chip, while ensuring the call
   chip still always shows the 00:01 timer.

Fixes: 388521980
Bug: 364653005
Flag: com.android.systemui.status_bar_notification_chips

Test: Post a CallStyle.Ongoing notification that's also colorized & has
FLAG_ONGOING_EVENT set -> verify only a single chip is shown. Verify
that chip uses the notification color, not the theme color.
Test: Post a CallStyle.Ongoing notification and a different promoted
notification -> verify call chip is shown first

Change-Id: I67427a4c8aa4b0d0890f9ef621e56aa87cf67b64
parent 77fb9ee0
Loading
Loading
Loading
Loading
+87 −5
Original line number Diff line number Diff line
@@ -30,10 +30,12 @@ import com.android.systemui.kosmos.testScope
import com.android.systemui.plugins.activityStarter
import com.android.systemui.res.R
import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips
import com.android.systemui.statusbar.chips.ui.model.ColorsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.core.StatusBarConnectedDisplays
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
import com.android.systemui.statusbar.phone.ongoingcall.data.repository.ongoingCallRepository
import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallModel
import com.android.systemui.statusbar.phone.ongoingcall.shared.model.inCallModel
@@ -64,7 +66,7 @@ class CallChipViewModelTest : SysuiTestCase() {
                .thenReturn(chipBackgroundView)
        }

    private val underTest = kosmos.callChipViewModel
    private val underTest by lazy { kosmos.callChipViewModel }

    @Test
    fun chip_noCall_isHidden() =
@@ -219,27 +221,93 @@ class CallChipViewModelTest : SysuiTestCase() {
        }

    @Test
    fun chip_positiveStartTime_colorsAreThemed() =
    fun chip_positiveStartTime_notPromoted_colorsAreThemed() =
        testScope.runTest {
            val latest by collectLastValue(underTest.chip)

            repo.setOngoingCallState(inCallModel(startTimeMs = 1000))
            repo.setOngoingCallState(inCallModel(startTimeMs = 1000, promotedContent = null))

            assertThat((latest as OngoingActivityChipModel.Shown).colors)
                .isEqualTo(ColorsModel.Themed)
        }

    @Test
    fun chip_zeroStartTime_colorsAreThemed() =
    fun chip_zeroStartTime_notPromoted_colorsAreThemed() =
        testScope.runTest {
            val latest by collectLastValue(underTest.chip)

            repo.setOngoingCallState(inCallModel(startTimeMs = 0))
            repo.setOngoingCallState(inCallModel(startTimeMs = 0, promotedContent = null))

            assertThat((latest as OngoingActivityChipModel.Shown).colors)
                .isEqualTo(ColorsModel.Themed)
        }

    @Test
    @DisableFlags(StatusBarNotifChips.FLAG_NAME)
    fun chip_positiveStartTime_promoted_notifChipsFlagOff_colorsAreThemed() =
        testScope.runTest {
            val latest by collectLastValue(underTest.chip)

            repo.setOngoingCallState(
                inCallModel(startTimeMs = 1000, promotedContent = PROMOTED_CONTENT_WITH_COLOR)
            )

            assertThat((latest as OngoingActivityChipModel.Shown).colors)
                .isEqualTo(ColorsModel.Themed)
        }

    @Test
    @DisableFlags(StatusBarNotifChips.FLAG_NAME)
    fun chip_zeroStartTime_promoted_notifChipsFlagOff_colorsAreThemed() =
        testScope.runTest {
            val latest by collectLastValue(underTest.chip)

            repo.setOngoingCallState(
                inCallModel(startTimeMs = 0, promotedContent = PROMOTED_CONTENT_WITH_COLOR)
            )

            assertThat((latest as OngoingActivityChipModel.Shown).colors)
                .isEqualTo(ColorsModel.Themed)
        }

    @Test
    @EnableFlags(StatusBarNotifChips.FLAG_NAME)
    fun chip_positiveStartTime_promoted_notifChipsFlagOn_colorsAreCustom() =
        testScope.runTest {
            val latest by collectLastValue(underTest.chip)

            repo.setOngoingCallState(
                inCallModel(startTimeMs = 1000, promotedContent = PROMOTED_CONTENT_WITH_COLOR)
            )

            assertThat((latest as OngoingActivityChipModel.Shown).colors)
                .isEqualTo(
                    ColorsModel.Custom(
                        backgroundColorInt = PROMOTED_BACKGROUND_COLOR,
                        primaryTextColorInt = PROMOTED_PRIMARY_TEXT_COLOR,
                    )
                )
        }

    @Test
    @EnableFlags(StatusBarNotifChips.FLAG_NAME)
    fun chip_zeroStartTime_promoted_notifChipsFlagOff_colorsAreCustom() =
        testScope.runTest {
            val latest by collectLastValue(underTest.chip)

            repo.setOngoingCallState(
                inCallModel(startTimeMs = 0, promotedContent = PROMOTED_CONTENT_WITH_COLOR)
            )

            assertThat((latest as OngoingActivityChipModel.Shown).colors)
                .isEqualTo(
                    ColorsModel.Custom(
                        backgroundColorInt = PROMOTED_BACKGROUND_COLOR,
                        primaryTextColorInt = PROMOTED_PRIMARY_TEXT_COLOR,
                    )
                )
        }

    @Test
    fun chip_resetsCorrectly() =
        testScope.runTest {
@@ -319,5 +387,19 @@ class CallChipViewModelTest : SysuiTestCase() {
            } else {
                mock<StatusBarIconView>()
            }

        private val PROMOTED_CONTENT_WITH_COLOR =
            PromotedNotificationContentModel.Builder("notif")
                .apply {
                    this.colors =
                        PromotedNotificationContentModel.Colors(
                            backgroundColor = PROMOTED_BACKGROUND_COLOR,
                            primaryTextColor = PROMOTED_PRIMARY_TEXT_COLOR,
                        )
                }
                .build()

        private const val PROMOTED_BACKGROUND_COLOR = 65
        private const val PROMOTED_PRIMARY_TEXT_COLOR = 98
    }
}
+32 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import com.android.systemui.statusbar.notification.data.repository.ActiveNotific
import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
import com.android.systemui.statusbar.notification.shared.CallType
import com.android.systemui.testKosmos
import com.android.systemui.util.time.fakeSystemClock
import com.google.common.truth.Truth.assertThat
@@ -178,6 +179,37 @@ class StatusBarNotificationChipsInteractorTest : SysuiTestCase() {
            assertThat(latest!![1].statusBarChipIconView).isEqualTo(secondIcon)
        }

    /** Regression test for b/388521980. */
    @Test
    @EnableFlags(StatusBarNotifChips.FLAG_NAME)
    fun notificationChips_callNotifIsAlsoPromoted_callNotifExcluded() =
        kosmos.runTest {
            val latest by collectLastValue(underTest.notificationChips)

            setNotifs(
                listOf(
                    activeNotificationModel(
                        key = "promotedNormal",
                        statusBarChipIcon = mock(),
                        promotedContent =
                            PromotedNotificationContentModel.Builder("promotedNormal").build(),
                        callType = CallType.None,
                    ),
                    activeNotificationModel(
                        key = "promotedCall",
                        statusBarChipIcon = mock(),
                        promotedContent =
                            PromotedNotificationContentModel.Builder("promotedCall").build(),
                        callType = CallType.Ongoing,
                    ),
                )
            )

            // Verify the promoted call notification is not included
            assertThat(latest).hasSize(1)
            assertThat(latest!![0].key).isEqualTo("promotedNormal")
        }

    @Test
    @EnableFlags(StatusBarNotifChips.FLAG_NAME)
    fun notificationChips_notifUpdatesGoThrough() =
+22 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import com.android.systemui.statusbar.notification.data.model.activeNotification
import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationsStore
import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
import com.android.systemui.statusbar.notification.domain.interactor.activeNotificationsInteractor
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
import com.android.systemui.statusbar.notification.shared.CallType
import com.android.systemui.statusbar.phone.ongoingcall.data.repository.ongoingCallRepository
@@ -168,6 +169,27 @@ class OngoingCallControllerTest : SysuiTestCase() {
            assertThat((repoState as OngoingCallModel.InCall).notificationIconView).isEqualTo(icon)
        }

    @Test
    fun interactorHasOngoingCallNotif_repoHasPromotedContent() =
        testScope.runTest {
            val promotedContent = PromotedNotificationContentModel.Builder("ongoingNotif").build()
            setNotifOnRepo(
                activeNotificationModel(
                    key = "ongoingNotif",
                    callType = CallType.Ongoing,
                    uid = CALL_UID,
                    statusBarChipIcon = mock(),
                    whenTime = 567,
                    promotedContent = promotedContent,
                )
            )

            val repoState = ongoingCallRepository.ongoingCallState.value
            assertThat(repoState).isInstanceOf(OngoingCallModel.InCall::class.java)
            assertThat((repoState as OngoingCallModel.InCall).promotedContent)
                .isEqualTo(promotedContent)
        }

    @Test
    fun notifRepoHasOngoingCallNotif_isOngoingCallNotif_windowControllerUpdated() {
        setCallNotifOnRepo()
+8 −3
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import com.android.systemui.statusbar.gesture.swipeStatusBarAwayGestureHandler
import com.android.systemui.statusbar.notification.data.model.activeNotificationModel
import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationsStore
import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
import com.android.systemui.statusbar.notification.shared.CallType
import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallModel
import com.android.systemui.statusbar.window.fakeStatusBarWindowControllerStore
@@ -69,33 +70,37 @@ class OngoingCallInteractorTest : SysuiTestCase() {
    }

    @Test
    fun ongoingCallNotification_setsNotificationIconAndIntent() =
    fun ongoingCallNotification_setsAllFields() =
        kosmos.runTest {
            val latest by collectLastValue(underTest.ongoingCallState)

            // Set up notification with icon view and intent
            val testIconView: StatusBarIconView = mock()
            val testIntent: PendingIntent = mock()
            val testPromotedContent =
                PromotedNotificationContentModel.Builder("promotedCall").build()
            repository.activeNotifications.value =
                ActiveNotificationsStore.Builder()
                    .apply {
                        addIndividualNotif(
                            activeNotificationModel(
                                key = "notif1",
                                key = "promotedCall",
                                whenTime = 1000L,
                                callType = CallType.Ongoing,
                                statusBarChipIcon = testIconView,
                                contentIntent = testIntent,
                                promotedContent = testPromotedContent,
                            )
                        )
                    }
                    .build()

            // Verify model is InCall and has the correct icon and intent.
            // Verify model is InCall and has the correct icon, intent, and promoted content.
            assertThat(latest).isInstanceOf(OngoingCallModel.InCall::class.java)
            val model = latest as OngoingCallModel.InCall
            assertThat(model.notificationIconView).isSameInstanceAs(testIconView)
            assertThat(model.intent).isSameInstanceAs(testIntent)
            assertThat(model.promotedContent).isSameInstanceAs(testPromotedContent)
        }

    @Test
+11 −2
Original line number Diff line number Diff line
@@ -30,7 +30,9 @@ import com.android.systemui.res.R
import com.android.systemui.statusbar.chips.StatusBarChipLogTags.pad
import com.android.systemui.statusbar.chips.StatusBarChipsLog
import com.android.systemui.statusbar.chips.call.domain.interactor.CallChipInteractor
import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips
import com.android.systemui.statusbar.chips.ui.model.ColorsModel
import com.android.systemui.statusbar.chips.ui.model.ColorsModel.Companion.toCustomColorsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipViewModel
@@ -76,13 +78,20 @@ constructor(
                                OngoingActivityChipModel.ChipIcon.SingleColorIcon(phoneIcon)
                            }

                        val colors =
                            if (StatusBarNotifChips.isEnabled && state.promotedContent != null) {
                                state.promotedContent.toCustomColorsModel()
                            } else {
                                ColorsModel.Themed
                            }

                        // This block mimics OngoingCallController#updateChip.
                        if (state.startTimeMs <= 0L) {
                            // If the start time is invalid, don't show a timer and show just an
                            // icon. See b/192379214.
                            OngoingActivityChipModel.Shown.IconOnly(
                                icon = icon,
                                colors = ColorsModel.Themed,
                                colors = colors,
                                getOnClickListener(state),
                            )
                        } else {
@@ -91,7 +100,7 @@ constructor(
                                    systemClock.elapsedRealtime()
                            OngoingActivityChipModel.Shown.Timer(
                                icon = icon,
                                colors = ColorsModel.Themed,
                                colors = colors,
                                startTimeMs = startTimeInElapsedRealtime,
                                getOnClickListener(state),
                            )
Loading