diff options
6 files changed, 94 insertions, 14 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt index 40f13bbbf908..17076b4d7505 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt @@ -306,12 +306,13 @@ class NotifChipsViewModelTest : SysuiTestCase() { @Test @EnableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY) - fun chips_basicTime_hiddenIfAutomaticallyPromoted() = + fun chips_basicTime_timeHiddenIfAutomaticallyPromoted() = kosmos.runTest { val latest by collectLastValue(underTest.chips) val promotedContentBuilder = PromotedNotificationContentModel.Builder("notif").apply { + this.wasPromotedAutomatically = true this.time = PromotedNotificationContentModel.When( time = 6543L, @@ -334,6 +335,36 @@ class NotifChipsViewModelTest : SysuiTestCase() { } @Test + @EnableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY) + fun chips_basicTime_timeShownIfNotAutomaticallyPromoted() = + kosmos.runTest { + val latest by collectLastValue(underTest.chips) + + val promotedContentBuilder = + PromotedNotificationContentModel.Builder("notif").apply { + this.wasPromotedAutomatically = false + this.time = + PromotedNotificationContentModel.When( + time = 6543L, + mode = PromotedNotificationContentModel.When.Mode.BasicTime, + ) + } + setNotifs( + listOf( + activeNotificationModel( + key = "notif", + statusBarChipIcon = mock<StatusBarIconView>(), + promotedContent = promotedContentBuilder.build(), + ) + ) + ) + + assertThat(latest).hasSize(1) + assertThat(latest!![0]) + .isInstanceOf(OngoingActivityChipModel.Shown.ShortTimeDelta::class.java) + } + + @Test @DisableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY) fun chips_basicTime_isShortTimeDelta() = kosmos.runTest { diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt index 26c6eb5dc47a..92271198cac0 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt @@ -35,6 +35,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder +import com.android.systemui.statusbar.notification.promoted.AutomaticPromotionCoordinator.Companion.EXTRA_WAS_AUTOMATICALLY_PROMOTED import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.Style import com.android.systemui.testKosmos @@ -110,6 +111,26 @@ class PromotedNotificationContentExtractorImplTest : SysuiTestCase() { @Test @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME) + fun extractContent_wasPromotedAutomatically_false() { + val entry = createEntry { extras.putBoolean(EXTRA_WAS_AUTOMATICALLY_PROMOTED, false) } + + val content = extractContent(entry) + + assertThat(content!!.wasPromotedAutomatically).isFalse() + } + + @Test + @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME) + fun extractContent_wasPromotedAutomatically_true() { + val entry = createEntry { extras.putBoolean(EXTRA_WAS_AUTOMATICALLY_PROMOTED, true) } + + val content = extractContent(entry) + + assertThat(content!!.wasPromotedAutomatically).isTrue() + } + + @Test + @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME) @DisableFlags(android.app.Flags.FLAG_API_RICH_ONGOING) fun extractContent_apiFlagOff_shortCriticalTextNotExtracted() { val entry = createEntry { setShortCriticalText(TEST_SHORT_CRITICAL_TEXT) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt index a7dbb47bc609..bcd8cfaa5c5a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt @@ -100,14 +100,14 @@ constructor( ) } - if (Flags.promoteNotificationsAutomatically()) { + if ( + Flags.promoteNotificationsAutomatically() && + this.promotedContent.wasPromotedAutomatically + ) { // When we're promoting notifications automatically, the `when` time set on the // notification will likely just be set to the current time, which would cause the chip // to always show "now". We don't want early testers to get that experience since it's // not what will happen at launch, so just don't show any time. - // TODO(b/364653005): Only ignore the `when` time if the notification was - // *automatically* promoted (as opposed to being legitimately promoted by the - // criteria). We'll need to track that status somehow. return OngoingActivityChipModel.Shown.IconOnly(icon, colors, onClickListener) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AutomaticPromotionCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AutomaticPromotionCoordinator.kt index bb164848320e..395746280f6a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AutomaticPromotionCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AutomaticPromotionCoordinator.kt @@ -22,7 +22,16 @@ import com.android.systemui.statusbar.notification.collection.coordinator.dagger import javax.inject.Inject /** A coordinator that may automatically promote certain notifications. */ -interface AutomaticPromotionCoordinator : Coordinator +interface AutomaticPromotionCoordinator : Coordinator { + companion object { + /** + * An extra that should be set on notifications that were automatically promoted. Used in + * case we want to disable certain features for only automatically promoted notifications + * (but not normally promoted notifications). + */ + const val EXTRA_WAS_AUTOMATICALLY_PROMOTED = "android.wasAutomaticallyPromoted" + } +} /** A default implementation of [AutomaticPromotionCoordinator] that doesn't promote anything. */ @CoordinatorScope diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt index 7d2827666227..df2eb08e8fa4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt @@ -24,14 +24,14 @@ import android.app.Notification.EXTRA_CHRONOMETER_COUNT_DOWN import android.app.Notification.EXTRA_SUB_TEXT import android.app.Notification.EXTRA_TEXT import android.app.Notification.EXTRA_TITLE -import android.app.Notification.FLAG_PROMOTED_ONGOING import android.app.Notification.ProgressStyle import android.content.Context import com.android.systemui.dagger.SysUISingleton import com.android.systemui.shade.ShadeDisplayAware -import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips import com.android.systemui.statusbar.notification.collection.NotificationEntry +import com.android.systemui.statusbar.notification.promoted.AutomaticPromotionCoordinator.Companion.EXTRA_WAS_AUTOMATICALLY_PROMOTED import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel +import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.Companion.isPromotedForStatusBarChip import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.Style import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.When import javax.inject.Inject @@ -65,12 +65,8 @@ constructor( return null } - // Notification.isPromotedOngoing checks the ui_rich_ongoing flag, but we want the status - // bar chip to be ready before all the features behind the ui_rich_ongoing flag are ready. - val isPromotedForStatusBarChip = - StatusBarNotifChips.isEnabled && (notification.flags and FLAG_PROMOTED_ONGOING) != 0 - val isPromoted = notification.isPromotedOngoing() || isPromotedForStatusBarChip - if (!isPromoted) { + // The status bar chips rely on this extractor, so take them into account for promotion. + if (!isPromotedForStatusBarChip(notification)) { logger.logExtractionSkipped(entry, "isPromotedOngoing returned false") return null } @@ -80,6 +76,8 @@ constructor( // TODO: Pitch a fit if style is unsupported or mandatory fields are missing once // FLAG_PROMOTED_ONGOING is set reliably and we're not testing status bar chips. + contentBuilder.wasPromotedAutomatically = + notification.extras.getBoolean(EXTRA_WAS_AUTOMATICALLY_PROMOTED, false) contentBuilder.skeletonSmallIcon = entry.icons.aodIcon?.sourceIcon contentBuilder.appName = notification.loadHeaderAppName(context) contentBuilder.subText = notification.subText() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/shared/model/PromotedNotificationContentModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/shared/model/PromotedNotificationContentModel.kt index 74809fd8622f..258d80c60cd7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/shared/model/PromotedNotificationContentModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/shared/model/PromotedNotificationContentModel.kt @@ -17,6 +17,8 @@ package com.android.systemui.statusbar.notification.promoted.shared.model import android.annotation.DrawableRes +import android.app.Notification +import android.app.Notification.FLAG_PROMOTED_ONGOING import android.graphics.drawable.Icon import androidx.annotation.ColorInt import com.android.internal.widget.NotificationProgressModel @@ -31,6 +33,10 @@ data class PromotedNotificationContentModel( val identity: Identity, // for all styles: + /** + * True if this notification was automatically promoted - see [AutomaticPromotionCoordinator]. + */ + val wasPromotedAutomatically: Boolean, val skeletonSmallIcon: Icon?, // TODO(b/377568176): Make into an IconModel. val appName: CharSequence?, val subText: CharSequence?, @@ -58,6 +64,7 @@ data class PromotedNotificationContentModel( val progress: NotificationProgressModel?, ) { class Builder(val key: String) { + var wasPromotedAutomatically: Boolean = false var skeletonSmallIcon: Icon? = null var appName: CharSequence? = null var subText: CharSequence? = null @@ -83,6 +90,7 @@ data class PromotedNotificationContentModel( fun build() = PromotedNotificationContentModel( identity = Identity(key, style), + wasPromotedAutomatically = wasPromotedAutomatically, skeletonSmallIcon = skeletonSmallIcon, appName = appName, subText = subText, @@ -134,5 +142,18 @@ data class PromotedNotificationContentModel( @JvmStatic fun featureFlagEnabled(): Boolean = PromotedNotificationUi.isEnabled || StatusBarNotifChips.isEnabled + + /** + * Returns true if the given notification should be considered promoted when deciding + * whether or not to show the status bar chip UI. + */ + fun isPromotedForStatusBarChip(notification: Notification): Boolean { + // Notification.isPromotedOngoing checks the ui_rich_ongoing flag, but we want the + // status bar chip to be ready before all the features behind the ui_rich_ongoing flag + // are ready. + val isPromotedForStatusBarChip = + StatusBarNotifChips.isEnabled && (notification.flags and FLAG_PROMOTED_ONGOING) != 0 + return notification.isPromotedOngoing() || isPromotedForStatusBarChip + } } } |