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

Commit 2a5193db authored by Caitlin Shkuratov's avatar Caitlin Shkuratov Committed by Android (Google) Code Review
Browse files

Merge "[SB][Notif] Use notification color for status bar notif chip." into main

parents 12c47d99 d06f7195
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -6024,8 +6024,9 @@ public class Notification implements Parcelable
        /**
         * @param isHeader If the notification is a notification header
         * @return An instance of mColors after resolving the palette
         * @hide
         */
        private Colors getColors(boolean isHeader) {
        public Colors getColors(boolean isHeader) {
            mColors.resolvePalette(mContext, mN.color, !isHeader && mN.isColorized(), mInNightMode);
            return mColors;
        }
@@ -14765,7 +14766,6 @@ public class Notification implements Parcelable
     * A utility which stores and calculates the palette of colors used to color notifications.
     * @hide
     */
    @VisibleForTesting
    public static class Colors {
        private int mPaletteIsForRawColor = COLOR_INVALID;
        private boolean mPaletteIsForColorized = false;
+131 −14
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.chips.notification.domain.model.NotificationChipModel
import com.android.systemui.statusbar.core.StatusBarConnectedDisplays
import com.android.systemui.statusbar.notification.data.model.activeNotificationModel
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import org.junit.Test
@@ -46,7 +47,12 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() {
        kosmos.runTest {
            val icon = mock<StatusBarIconView>()
            val startingNotif =
                activeNotificationModel(key = "notif1", statusBarChipIcon = icon, whenTime = 5432)
                activeNotificationModel(
                    key = "notif1",
                    statusBarChipIcon = icon,
                    whenTime = 5432,
                    promotedContent = PROMOTED_CONTENT,
                )

            val underTest = factory.create(startingNotif)

@@ -63,7 +69,11 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() {
            val originalIconView = mock<StatusBarIconView>()
            val underTest =
                factory.create(
                    activeNotificationModel(key = "notif1", statusBarChipIcon = originalIconView)
                    activeNotificationModel(
                        key = "notif1",
                        statusBarChipIcon = originalIconView,
                        promotedContent = PROMOTED_CONTENT,
                    )
                )

            val latest by collectLastValue(underTest.notificationChip)
@@ -74,6 +84,7 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() {
                    key = "notif1",
                    statusBarChipIcon = newIconView,
                    whenTime = 6543,
                    promotedContent = PROMOTED_CONTENT,
                )
            )

@@ -88,25 +99,66 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() {
            val originalIconView = mock<StatusBarIconView>()
            val underTest =
                factory.create(
                    activeNotificationModel(key = "notif1", statusBarChipIcon = originalIconView)
                    activeNotificationModel(
                        key = "notif1",
                        statusBarChipIcon = originalIconView,
                        promotedContent = PROMOTED_CONTENT,
                    )
                )

            val latest by collectLastValue(underTest.notificationChip)

            val newIconView = mock<StatusBarIconView>()
            underTest.setNotification(
                activeNotificationModel(key = "other_notif", statusBarChipIcon = newIconView)
                activeNotificationModel(
                    key = "other_notif",
                    statusBarChipIcon = newIconView,
                    promotedContent = PROMOTED_CONTENT,
                )
            )

            assertThat(latest!!.key).isEqualTo("notif1")
            assertThat(latest!!.statusBarChipIconView).isEqualTo(originalIconView)
        }

    @Test
    fun notificationChip_ignoresSetWithNullPromotedContent() =
        kosmos.runTest {
            val originalIconView = mock<StatusBarIconView>()
            val underTest =
                factory.create(
                    activeNotificationModel(
                        key = "notif1",
                        statusBarChipIcon = originalIconView,
                        promotedContent = PROMOTED_CONTENT,
                    )
                )

            val latest by collectLastValue(underTest.notificationChip)

            val newIconView = mock<StatusBarIconView>()
            underTest.setNotification(
                activeNotificationModel(
                    key = "notif1",
                    statusBarChipIcon = newIconView,
                    promotedContent = null,
                )
            )

            assertThat(latest!!.statusBarChipIconView).isEqualTo(originalIconView)
        }

    @Test
    fun notificationChip_missingStatusBarIconChipView_inConstructor_emitsNull() =
        kosmos.runTest {
            val underTest =
                factory.create(activeNotificationModel(key = "notif1", statusBarChipIcon = null))
                factory.create(
                    activeNotificationModel(
                        key = "notif1",
                        statusBarChipIcon = null,
                        promotedContent = PROMOTED_CONTENT,
                    )
                )

            val latest by collectLastValue(underTest.notificationChip)

@@ -123,6 +175,7 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() {
                        key = "notif1",
                        statusBarChipIcon = null,
                        whenTime = 123L,
                        promotedContent = PROMOTED_CONTENT,
                    )
                )

@@ -130,20 +183,34 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() {

            assertThat(latest)
                .isEqualTo(
                    NotificationChipModel("notif1", statusBarChipIconView = null, whenTime = 123L)
                    NotificationChipModel(
                        "notif1",
                        statusBarChipIconView = null,
                        whenTime = 123L,
                        promotedContent = PROMOTED_CONTENT,
                    )
                )
        }

    @Test
    fun notificationChip_missingStatusBarIconChipView_inSet_emitsNull() =
        kosmos.runTest {
            val startingNotif = activeNotificationModel(key = "notif1", statusBarChipIcon = mock())
            val startingNotif =
                activeNotificationModel(
                    key = "notif1",
                    statusBarChipIcon = mock(),
                    promotedContent = PROMOTED_CONTENT,
                )
            val underTest = factory.create(startingNotif)
            val latest by collectLastValue(underTest.notificationChip)
            assertThat(latest).isNotNull()

            underTest.setNotification(
                activeNotificationModel(key = "notif1", statusBarChipIcon = null)
                activeNotificationModel(
                    key = "notif1",
                    statusBarChipIcon = null,
                    promotedContent = PROMOTED_CONTENT,
                )
            )

            assertThat(latest).isNull()
@@ -153,13 +220,23 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() {
    @EnableFlags(StatusBarConnectedDisplays.FLAG_NAME)
    fun notificationChip_missingStatusBarIconChipView_inSet_cdEnabled_emitsNotNull() =
        kosmos.runTest {
            val startingNotif = activeNotificationModel(key = "notif1", statusBarChipIcon = mock())
            val startingNotif =
                activeNotificationModel(
                    key = "notif1",
                    statusBarChipIcon = mock(),
                    promotedContent = PROMOTED_CONTENT,
                )
            val underTest = factory.create(startingNotif)
            val latest by collectLastValue(underTest.notificationChip)
            assertThat(latest).isNotNull()

            underTest.setNotification(
                activeNotificationModel(key = "notif1", statusBarChipIcon = null, whenTime = 123L)
                activeNotificationModel(
                    key = "notif1",
                    statusBarChipIcon = null,
                    whenTime = 123L,
                    promotedContent = PROMOTED_CONTENT,
                )
            )

            assertThat(latest)
@@ -168,10 +245,28 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() {
                        key = "notif1",
                        statusBarChipIconView = null,
                        whenTime = 123L,
                        promotedContent = PROMOTED_CONTENT,
                    )
                )
        }

    @Test
    fun notificationChip_missingPromotedContent_inConstructor_emitsNull() =
        kosmos.runTest {
            val underTest =
                factory.create(
                    activeNotificationModel(
                        key = "notif1",
                        statusBarChipIcon = mock(),
                        promotedContent = null,
                    )
                )

            val latest by collectLastValue(underTest.notificationChip)

            assertThat(latest).isNull()
        }

    @Test
    fun notificationChip_appIsVisibleOnCreation_emitsNull() =
        kosmos.runTest {
@@ -179,7 +274,12 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() {

            val underTest =
                factory.create(
                    activeNotificationModel(key = "notif", uid = UID, statusBarChipIcon = mock())
                    activeNotificationModel(
                        key = "notif",
                        uid = UID,
                        statusBarChipIcon = mock(),
                        promotedContent = PROMOTED_CONTENT,
                    )
                )

            val latest by collectLastValue(underTest.notificationChip)
@@ -194,7 +294,12 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() {

            val underTest =
                factory.create(
                    activeNotificationModel(key = "notif", uid = UID, statusBarChipIcon = mock())
                    activeNotificationModel(
                        key = "notif",
                        uid = UID,
                        statusBarChipIcon = mock(),
                        promotedContent = PROMOTED_CONTENT,
                    )
                )

            val latest by collectLastValue(underTest.notificationChip)
@@ -207,7 +312,12 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() {
        kosmos.runTest {
            val underTest =
                factory.create(
                    activeNotificationModel(key = "notif", uid = UID, statusBarChipIcon = mock())
                    activeNotificationModel(
                        key = "notif",
                        uid = UID,
                        statusBarChipIcon = mock(),
                        promotedContent = PROMOTED_CONTENT,
                    )
                )

            val latest by collectLastValue(underTest.notificationChip)
@@ -239,6 +349,7 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() {
                        key = "notif",
                        uid = hiddenUid,
                        statusBarChipIcon = mock(),
                        promotedContent = PROMOTED_CONTENT,
                    )
                )
            val latest by collectLastValue(underTest.notificationChip)
@@ -247,7 +358,12 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() {
            // WHEN the notif gets a new UID that starts as visible
            activityManagerRepository.fake.startingIsAppVisibleValue = true
            underTest.setNotification(
                activeNotificationModel(key = "notif", uid = shownUid, statusBarChipIcon = mock())
                activeNotificationModel(
                    key = "notif",
                    uid = shownUid,
                    statusBarChipIcon = mock(),
                    promotedContent = PROMOTED_CONTENT,
                )
            )

            // THEN we re-fetch the app visibility state with the new UID, and since that UID is
@@ -257,5 +373,6 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() {

    companion object {
        private const val UID = 885
        private val PROMOTED_CONTENT = PromotedNotificationContentModel.Builder("notif1").build()
    }
}
+31 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import com.android.systemui.kosmos.useUnconfinedTestDispatcher
import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.chips.notification.domain.interactor.statusBarNotificationChipsInteractor
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.core.StatusBarConnectedDisplays
import com.android.systemui.statusbar.notification.data.model.activeNotificationModel
@@ -131,6 +132,36 @@ class NotifChipsViewModelTest : SysuiTestCase() {
                .isEqualTo(OngoingActivityChipModel.ChipIcon.StatusBarNotificationIcon(notifKey))
        }

    @Test
    fun chips_onePromotedNotif_colorMatches() =
        kosmos.runTest {
            val latest by collectLastValue(underTest.chips)

            val promotedContentBuilder =
                PromotedNotificationContentModel.Builder("notif").apply {
                    this.colors =
                        PromotedNotificationContentModel.Colors(
                            backgroundColor = 56,
                            primaryTextColor = 89,
                        )
                }
            setNotifs(
                listOf(
                    activeNotificationModel(
                        key = "notif",
                        statusBarChipIcon = mock<StatusBarIconView>(),
                        promotedContent = promotedContentBuilder.build(),
                    )
                )
            )

            assertThat(latest).hasSize(1)
            val colors = latest!![0].colors
            assertThat(colors).isInstanceOf(ColorsModel.Custom::class.java)
            assertThat((colors as ColorsModel.Custom).backgroundColorInt).isEqualTo(56)
            assertThat((colors as ColorsModel.Custom).primaryTextColorInt).isEqualTo(89)
        }

    @Test
    fun chips_onlyForPromotedNotifs() =
        kosmos.runTest {
+27 −1
Original line number Diff line number Diff line
@@ -57,6 +57,14 @@ constructor(
    // top-level tag. It should instead be provided as the first string in each log message.
    private val extraLogTag = "SingleChipInteractor[key=$key]"

    init {
        if (startingModel.promotedContent == null) {
            logger.e({ "$str1: Starting model has promotedContent=null, which shouldn't happen" }) {
                str1 = extraLogTag
            }
        }
    }

    private val _notificationModel = MutableStateFlow(startingModel)

    /**
@@ -71,6 +79,14 @@ constructor(
            }
            return
        }
        if (model.promotedContent == null) {
            logger.e({
                "$str1: received model with promotedContent=null, which shouldn't happen"
            }) {
                str1 = extraLogTag
            }
            return
        }
        _notificationModel.value = model
    }

@@ -99,6 +115,15 @@ constructor(
        }

    private fun ActiveNotificationModel.toNotificationChipModel(): NotificationChipModel? {
        val promotedContent = this.promotedContent
        if (promotedContent == null) {
            logger.w({
                "$str1: Can't show chip because promotedContent=null, which shouldn't happen"
            }) {
                str1 = extraLogTag
            }
            return null
        }
        val statusBarChipIconView = this.statusBarChipIconView
        if (statusBarChipIconView == null) {
            if (!StatusBarConnectedDisplays.isEnabled) {
@@ -111,7 +136,8 @@ constructor(
                return null
            }
        }
        return NotificationChipModel(key, statusBarChipIconView, whenTime)

        return NotificationChipModel(key, statusBarChipIconView, whenTime, promotedContent)
    }

    @AssistedFactory
+3 −0
Original line number Diff line number Diff line
@@ -17,10 +17,13 @@
package com.android.systemui.statusbar.chips.notification.domain.model

import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel

/** Modeling all the data needed to render a status bar notification chip. */
data class NotificationChipModel(
    val key: String,
    val statusBarChipIconView: StatusBarIconView?,
    // TODO(b/364653005): Use [PromotedNotificationContentModel.time] instead of a custom field.
    val whenTime: Long,
    val promotedContent: PromotedNotificationContentModel,
)
Loading