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

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

Merge changes from topic "caitlinshk-chips-sysuirestag" into main

* changes:
  [SB][Call] Fix `assertIsCallChip` helper method in tests.
  [SB][Chips] Add SysUI resource tag to Compose chips.
  [SB][Notif] Maintain notification chip state for a timeout period.
parents 1b3e136c 3407c387
Loading
Loading
Loading
Loading
+59 −0
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@ import com.android.systemui.statusbar.core.StatusBarConnectedDisplays
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.data.repository.addNotif
import com.android.systemui.statusbar.notification.data.repository.removeNotif
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
@@ -407,6 +409,63 @@ class StatusBarNotificationChipsInteractorTest : SysuiTestCase() {
            assertThat(latest!!.map { it.key }).containsExactly("notif1", "notif2").inOrder()
        }

    @Test
    @EnableFlags(StatusBarNotifChips.FLAG_NAME)
    fun shownNotificationChips_lastAppVisibleTimeMaintainedAcrossNotifAddsAndRemoves() =
        kosmos.runTest {
            val latest by collectLastValue(underTest.shownNotificationChips)

            val notif1Info = NotifInfo("notif1", mock<StatusBarIconView>(), uid = 100)
            val notif2Info = NotifInfo("notif2", mock<StatusBarIconView>(), uid = 200)

            // Have notif1's app start as showing and then hide later so we get the chip
            activityManagerRepository.fake.startingIsAppVisibleValue = true
            fakeSystemClock.setCurrentTimeMillis(9_000)
            activeNotificationListRepository.addNotif(
                activeNotificationModel(
                    key = notif1Info.key,
                    uid = notif1Info.uid,
                    statusBarChipIcon = notif1Info.icon,
                    promotedContent =
                        PromotedNotificationContentModel.Builder(notif1Info.key).build(),
                )
            )
            activityManagerRepository.fake.setIsAppVisible(notif1Info.uid, isAppVisible = false)

            assertThat(latest!![0].key).isEqualTo(notif1Info.key)
            assertThat(latest!![0].lastAppVisibleTime).isEqualTo(9_000)

            // WHEN a new notification is added
            activityManagerRepository.fake.startingIsAppVisibleValue = true
            fakeSystemClock.setCurrentTimeMillis(10_000)
            activeNotificationListRepository.addNotif(
                activeNotificationModel(
                    key = notif2Info.key,
                    uid = notif2Info.uid,
                    statusBarChipIcon = notif2Info.icon,
                    promotedContent =
                        PromotedNotificationContentModel.Builder(notif2Info.key).build(),
                )
            )
            activityManagerRepository.fake.setIsAppVisible(notif2Info.uid, isAppVisible = false)

            // THEN the new notification is first
            assertThat(latest!![0].key).isEqualTo(notif2Info.key)
            assertThat(latest!![0].lastAppVisibleTime).isEqualTo(10_000)

            // And THEN the original notification maintains its lastAppVisibleTime
            assertThat(latest!![1].key).isEqualTo(notif1Info.key)
            assertThat(latest!![1].lastAppVisibleTime).isEqualTo(9_000)

            // WHEN notif1 is removed
            fakeSystemClock.setCurrentTimeMillis(11_000)
            activeNotificationListRepository.removeNotif(notif1Info.key)

            // THEN notif2 still has its lastAppVisibleTime
            assertThat(latest!![0].key).isEqualTo(notif2Info.key)
            assertThat(latest!![0].lastAppVisibleTime).isEqualTo(10_000)
        }

    @Test
    @EnableFlags(StatusBarNotifChips.FLAG_NAME)
    fun shownNotificationChips_sortedByLastAppVisibleTime() =
+22 −10
Original line number Diff line number Diff line
@@ -16,18 +16,19 @@

package com.android.systemui.statusbar.chips.ui.viewmodel

import android.content.Context
import android.content.DialogInterface
import android.content.packageManager
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.drawable.BitmapDrawable
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.view.View
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.Expandable
import com.android.systemui.common.shared.model.ContentDescription.Companion.loadContentDescription
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.collectLastValue
@@ -181,7 +182,7 @@ class OngoingActivityChipsViewModelTest : SysuiTestCase() {

            val latest by collectLastValue(underTest.primaryChip)

            assertIsCallChip(latest, notificationKey)
            assertIsCallChip(latest, notificationKey, context)
        }

    @Test
@@ -196,7 +197,7 @@ class OngoingActivityChipsViewModelTest : SysuiTestCase() {

            val latest by collectLastValue(underTest.primaryChip)

            assertIsCallChip(latest, callNotificationKey)
            assertIsCallChip(latest, callNotificationKey, context)

            // WHEN the higher priority media projection chip is added
            mediaProjectionState.value =
@@ -241,7 +242,7 @@ class OngoingActivityChipsViewModelTest : SysuiTestCase() {
            mediaProjectionState.value = MediaProjectionState.NotProjecting

            // THEN the lower priority call is used
            assertIsCallChip(latest, callNotificationKey)
            assertIsCallChip(latest, callNotificationKey, context)
        }

    /** Regression test for b/347726238. */
@@ -395,18 +396,29 @@ class OngoingActivityChipsViewModelTest : SysuiTestCase() {
            assertThat(icon.res).isEqualTo(R.drawable.ic_present_to_all)
        }

        fun assertIsCallChip(latest: OngoingActivityChipModel?, notificationKey: String) {
        fun assertIsCallChip(
            latest: OngoingActivityChipModel?,
            notificationKey: String,
            context: Context,
        ) {
            assertThat(latest).isInstanceOf(OngoingActivityChipModel.Active::class.java)
            assertThat((latest as OngoingActivityChipModel.Active).key).isEqualTo(notificationKey)

            if (StatusBarConnectedDisplays.isEnabled) {
                assertNotificationIcon(latest, notificationKey)
                return
            } else {
                val contentDescription =
                    if (latest.icon is OngoingActivityChipModel.ChipIcon.SingleColorIcon) {
                        ((latest.icon) as OngoingActivityChipModel.ChipIcon.SingleColorIcon)
                            .impl
                            .contentDescription
                    } else {
                        (latest.icon as OngoingActivityChipModel.ChipIcon.StatusBarView)
                            .contentDescription
                    }
                assertThat(contentDescription.loadContentDescription(context))
                    .contains(context.getString(R.string.ongoing_call_content_description))
            }
            val icon =
                ((latest.icon) as OngoingActivityChipModel.ChipIcon.SingleColorIcon).impl
                    as Icon.Resource
            assertThat(icon.res).isEqualTo(com.android.internal.R.drawable.ic_phone)
        }

        private fun assertNotificationIcon(
+18 −18
Original line number Diff line number Diff line
@@ -254,7 +254,7 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
            val unused by collectLastValue(underTest.chips)

            assertIsScreenRecordChip(latest!!.primary)
            assertIsCallChip(latest!!.secondary, callNotificationKey)
            assertIsCallChip(latest!!.secondary, callNotificationKey, context)
            assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModel())
        }

@@ -285,7 +285,7 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {

            assertThat(latest!!.active.size).isEqualTo(2)
            assertIsScreenRecordChip(latest!!.active[0])
            assertIsCallChip(latest!!.active[1], callNotificationKey)
            assertIsCallChip(latest!!.active[1], callNotificationKey, context)
            assertThat(latest!!.overflow).isEmpty()
            assertThat(latest!!.inactive.size).isEqualTo(2)
            assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModelLegacy())
@@ -617,7 +617,7 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
            val unused by collectLastValue(underTest.chips)

            assertIsShareToAppChip(latest!!.primary)
            assertIsCallChip(latest!!.secondary, callNotificationKey)
            assertIsCallChip(latest!!.secondary, callNotificationKey, context)
            assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModel())
        }

@@ -636,7 +636,7 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {

            assertThat(latest!!.active.size).isEqualTo(2)
            assertIsShareToAppChip(latest!!.active[0])
            assertIsCallChip(latest!!.active[1], callNotificationKey)
            assertIsCallChip(latest!!.active[1], callNotificationKey, context)
            assertThat(latest!!.overflow).isEmpty()
            assertThat(latest!!.inactive.size).isEqualTo(2)
            assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModelLegacy())
@@ -654,7 +654,7 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {

            val latest by collectLastValue(underTest.primaryChip)

            assertIsCallChip(latest, callNotificationKey)
            assertIsCallChip(latest, callNotificationKey, context)
        }

    @DisableChipsModernization
@@ -671,7 +671,7 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
            val latest by collectLastValue(underTest.chipsLegacy)
            val unused by collectLastValue(underTest.chips)

            assertIsCallChip(latest!!.primary, callNotificationKey)
            assertIsCallChip(latest!!.primary, callNotificationKey, context)
            assertThat(latest!!.secondary)
                .isInstanceOf(OngoingActivityChipModel.Inactive::class.java)
            assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModel())
@@ -691,7 +691,7 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
            val unused by collectLastValue(underTest.chipsLegacy)

            assertThat(latest!!.active.size).isEqualTo(1)
            assertIsCallChip(latest!!.active[0], callNotificationKey)
            assertIsCallChip(latest!!.active[0], callNotificationKey, context)
            assertThat(latest!!.overflow).isEmpty()
            assertThat(latest!!.inactive.size).isEqualTo(3)
            assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModelLegacy())
@@ -950,7 +950,7 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
                )
            )

            assertIsCallChip(latest!!.primary, callNotificationKey)
            assertIsCallChip(latest!!.primary, callNotificationKey, context)
            assertIsNotifChip(latest!!.secondary, context, firstIcon, "firstNotif")
            assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModel())
        }
@@ -984,7 +984,7 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
            )

            assertThat(latest!!.active.size).isEqualTo(2)
            assertIsCallChip(latest!!.active[0], callNotificationKey)
            assertIsCallChip(latest!!.active[0], callNotificationKey, context)
            assertIsNotifChip(latest!!.active[1], context, firstIcon, "firstNotif")
            assertThat(latest!!.overflow.size).isEqualTo(1)
            assertIsNotifChip(latest!!.overflow[0], context, secondIcon, "secondNotif")
@@ -1011,7 +1011,7 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
            )

            assertIsScreenRecordChip(latest!!.primary)
            assertIsCallChip(latest!!.secondary, callNotificationKey)
            assertIsCallChip(latest!!.secondary, callNotificationKey, context)
            assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModel())
        }

@@ -1057,7 +1057,7 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {

            assertThat(latest!!.active.size).isEqualTo(2)
            assertIsScreenRecordChip(latest!!.active[0])
            assertIsCallChip(latest!!.active[1], callNotificationKey)
            assertIsCallChip(latest!!.active[1], callNotificationKey, context)
            assertThat(latest!!.overflow.size).isEqualTo(1)
            assertIsNotifChip(latest!!.overflow[0], context, notifIcon, "notif")
            assertThat(latest!!.inactive.size).isEqualTo(2)
@@ -1092,7 +1092,7 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
            addOngoingCallState(callNotificationKey)

            // THEN the higher priority call chip is used
            assertIsCallChip(latest, callNotificationKey)
            assertIsCallChip(latest, callNotificationKey, context)

            // WHEN the higher priority media projection chip is added
            mediaProjectionState.value =
@@ -1145,7 +1145,7 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
            mediaProjectionState.value = MediaProjectionState.NotProjecting

            // THEN the lower priority call is used
            assertIsCallChip(latest, callNotificationKey)
            assertIsCallChip(latest, callNotificationKey, context)

            // WHEN the higher priority call is removed
            removeOngoingCallState(key = callNotificationKey)
@@ -1186,7 +1186,7 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {

            // THEN the higher priority call chip is used as primary and notif is demoted to
            // secondary
            assertIsCallChip(latest!!.primary, callNotificationKey)
            assertIsCallChip(latest!!.primary, callNotificationKey, context)
            assertIsNotifChip(latest!!.secondary, context, notifIcon, "notif")
            assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModel())

@@ -1201,7 +1201,7 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
            // THEN the higher priority media projection chip is used as primary and call is demoted
            // to secondary (and notif is dropped altogether)
            assertIsShareToAppChip(latest!!.primary)
            assertIsCallChip(latest!!.secondary, callNotificationKey)
            assertIsCallChip(latest!!.secondary, callNotificationKey, context)
            assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModel())

            // WHEN the higher priority screen record chip is added
@@ -1264,7 +1264,7 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {

            // THEN the higher priority call chip and notif are active in that order
            assertThat(latest!!.active.size).isEqualTo(2)
            assertIsCallChip(latest!!.active[0], callNotificationKey)
            assertIsCallChip(latest!!.active[0], callNotificationKey, context)
            assertIsNotifChip(latest!!.active[1], context, notifIcon, "notif")
            assertThat(latest!!.overflow).isEmpty()
            assertThat(latest!!.inactive.size).isEqualTo(3)
@@ -1282,7 +1282,7 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
            // notif is demoted to overflow
            assertThat(latest!!.active.size).isEqualTo(2)
            assertIsShareToAppChip(latest!!.active[0])
            assertIsCallChip(latest!!.active[1], callNotificationKey)
            assertIsCallChip(latest!!.active[1], callNotificationKey, context)
            assertThat(latest!!.overflow.size).isEqualTo(1)
            assertIsNotifChip(latest!!.overflow[0], context, notifIcon, "notif")
            assertThat(latest!!.inactive.size).isEqualTo(2)
@@ -1295,7 +1295,7 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
            // media projection and notif are demoted in overflow
            assertThat(latest!!.active.size).isEqualTo(2)
            assertIsScreenRecordChip(latest!!.active[0])
            assertIsCallChip(latest!!.active[1], callNotificationKey)
            assertIsCallChip(latest!!.active[1], callNotificationKey, context)
            assertThat(latest!!.overflow.size).isEqualTo(2)
            assertIsShareToAppChip(latest!!.overflow[0])
            assertIsNotifChip(latest!!.overflow[1], context, notifIcon, "notif")
+1 −1
Original line number Diff line number Diff line
@@ -1018,7 +1018,7 @@ class HomeStatusBarViewModelImplTest : SysuiTestCase() {
            addOngoingCallState(key = "call")

            assertIsScreenRecordChip(latest!!.chips.active[0])
            assertIsCallChip(latest!!.chips.active[1], "call")
            assertIsCallChip(latest!!.chips.active[1], "call", context)
        }

    @Test
+1 −1
Original line number Diff line number Diff line
@@ -56,7 +56,7 @@ constructor(
    private val logger = Logger(logBuffer, "Notif".pad())
    // [StatusBarChipLogTag] recommends a max tag length of 20, so [extraLogTag] should NOT be the
    // top-level tag. It should instead be provided as the first string in each log message.
    private val extraLogTag = "SingleChipInteractor[key=$key]"
    private val extraLogTag = "SingleNotifChipInteractor[key=$key][id=${hashCode()}]"

    init {
        if (startingModel.promotedContent == null) {
Loading