Add a section just for priority people
Bug: 340294566
Test: atest SystemUITests
Flag: com.android.systemui.priority_people_section
Change-Id: I1911d744e4018233d65d9002801e723ac0500720
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index de090f4..bd8ea93 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -34,6 +34,13 @@
}
flag {
+ name: "priority_people_section"
+ namespace: "systemui"
+ description: "Add a new section for priority people (aka important conversations)."
+ bug: "340294566"
+}
+
+flag {
name: "notification_minimalism_prototype"
namespace: "systemui"
description: "Prototype of notification minimalism; the new 'Intermediate' lockscreen customization proposal."
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
similarity index 62%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
index c5d7e1f..2853264 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
@@ -23,9 +23,8 @@
import android.app.NotificationManager.IMPORTANCE_LOW
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
-import android.platform.test.flag.junit.SetFlagsRule
-import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.notification.collection.GroupEntry
@@ -44,25 +43,29 @@
import com.android.systemui.statusbar.notification.collection.render.NodeController
import com.android.systemui.statusbar.notification.icon.ConversationIconManager
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier
+import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.PeopleNotificationType
+import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_FULL_PERSON
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_IMPORTANT_PERSON
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_NON_PERSON
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_PERSON
+import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifierImpl
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.withArgCaptor
import com.google.common.truth.Truth.assertThat
+import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
-import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations
import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
+import org.mockito.kotlin.mock
@SmallTest
-@RunWith(AndroidTestingRunner::class)
+@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
class ConversationCoordinatorTest : SysuiTestCase() {
// captured listeners and pluggables:
@@ -72,22 +75,20 @@
private lateinit var peopleComparator: NotifComparator
private lateinit var beforeRenderListListener: OnBeforeRenderListListener
+ private lateinit var peopleNotificationIdentifier: PeopleNotificationIdentifier
+ private lateinit var peopleAlertingSection: NotifSection
+
@Mock private lateinit var pipeline: NotifPipeline
@Mock private lateinit var conversationIconManager: ConversationIconManager
- @Mock private lateinit var peopleNotificationIdentifier: PeopleNotificationIdentifier
- @Mock private lateinit var channel: NotificationChannel
@Mock private lateinit var headerController: NodeController
- private lateinit var entry: NotificationEntry
- private lateinit var entryA: NotificationEntry
- private lateinit var entryB: NotificationEntry
private lateinit var coordinator: ConversationCoordinator
- @Rule @JvmField public val setFlagsRule = SetFlagsRule()
-
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
+ peopleNotificationIdentifier =
+ PeopleNotificationIdentifierImpl(mock(), GroupMembershipManagerImpl())
coordinator =
ConversationCoordinator(
peopleNotificationIdentifier,
@@ -95,7 +96,6 @@
HighPriorityProvider(peopleNotificationIdentifier, GroupMembershipManagerImpl()),
headerController
)
- whenever(channel.isImportantConversation).thenReturn(true)
coordinator.attach(pipeline)
@@ -110,49 +110,65 @@
if (!SortBySectionTimeFlag.isEnabled)
peopleComparator = peopleAlertingSectioner.comparator!!
- entry = NotificationEntryBuilder().setChannel(channel).build()
+ peopleAlertingSection = NotifSection(peopleAlertingSectioner, 0)
+ }
- val section = NotifSection(peopleAlertingSectioner, 0)
- entryA =
- NotificationEntryBuilder().setChannel(channel).setSection(section).setTag("A").build()
- entryB =
- NotificationEntryBuilder().setChannel(channel).setSection(section).setTag("B").build()
+ @Test
+ fun priorityPeopleSectionerClaimsOnlyImportantConversations() {
+ val sectioner = coordinator.priorityPeopleSectioner
+ assertTrue(sectioner.isInSection(makeEntryOfPeopleType(TYPE_IMPORTANT_PERSON)))
+ assertFalse(sectioner.isInSection(makeEntryOfPeopleType(TYPE_FULL_PERSON)))
+ assertFalse(sectioner.isInSection(makeEntryOfPeopleType(TYPE_PERSON)))
+ assertFalse(sectioner.isInSection(makeEntryOfPeopleType(TYPE_NON_PERSON)))
+ assertFalse(sectioner.isInSection(NotificationEntryBuilder().build()))
}
@Test
fun testPromotesImportantConversations() {
- // only promote important conversations
- assertTrue(promoter.shouldPromoteToTopLevel(entry))
+ assertTrue(promoter.shouldPromoteToTopLevel(makeEntryOfPeopleType(TYPE_IMPORTANT_PERSON)))
+ assertFalse(promoter.shouldPromoteToTopLevel(makeEntryOfPeopleType(TYPE_FULL_PERSON)))
+ assertFalse(promoter.shouldPromoteToTopLevel(makeEntryOfPeopleType(TYPE_PERSON)))
+ assertFalse(promoter.shouldPromoteToTopLevel(makeEntryOfPeopleType(TYPE_NON_PERSON)))
assertFalse(promoter.shouldPromoteToTopLevel(NotificationEntryBuilder().build()))
}
@Test
fun testPromotedImportantConversationsMakesSummaryUnimportant() {
- val altChildA = NotificationEntryBuilder().setTag("A").build()
- val altChildB = NotificationEntryBuilder().setTag("B").build()
- val summary = NotificationEntryBuilder().setId(2).setChannel(channel).build()
+ val importantChannel =
+ mock<NotificationChannel>().also {
+ whenever(it.isImportantConversation).thenReturn(true)
+ }
+ val otherChannel =
+ mock<NotificationChannel>().also {
+ whenever(it.isImportantConversation).thenReturn(false)
+ }
+ val importantChild =
+ makeEntryOfPeopleType(TYPE_IMPORTANT_PERSON) { setChannel(importantChannel) }
+ val altChildA =
+ makeEntryOfPeopleType(TYPE_FULL_PERSON) { setChannel(otherChannel).setTag("A") }
+ val altChildB =
+ makeEntryOfPeopleType(TYPE_FULL_PERSON) { setChannel(otherChannel).setTag("B") }
+ val summary =
+ makeEntryOfPeopleType(TYPE_IMPORTANT_PERSON) { setChannel(importantChannel).setId(2) }
val groupEntry =
GroupEntryBuilder()
.setParent(GroupEntry.ROOT_ENTRY)
.setSummary(summary)
- .setChildren(listOf(entry, altChildA, altChildB))
+ .setChildren(listOf(importantChild, altChildA, altChildB))
.build()
- assertTrue(promoter.shouldPromoteToTopLevel(entry))
+ assertTrue(promoter.shouldPromoteToTopLevel(importantChild))
assertFalse(promoter.shouldPromoteToTopLevel(altChildA))
assertFalse(promoter.shouldPromoteToTopLevel(altChildB))
- NotificationEntryBuilder.setNewParent(entry, GroupEntry.ROOT_ENTRY)
- GroupEntryBuilder.getRawChildren(groupEntry).remove(entry)
- beforeRenderListListener.onBeforeRenderList(listOf(entry, groupEntry))
+ NotificationEntryBuilder.setNewParent(importantChild, GroupEntry.ROOT_ENTRY)
+ GroupEntryBuilder.getRawChildren(groupEntry).remove(importantChild)
+ beforeRenderListListener.onBeforeRenderList(listOf(importantChild, groupEntry))
verify(conversationIconManager).setUnimportantConversations(eq(listOf(summary.key)))
}
@Test
fun testInAlertingPeopleSectionWhenTheImportanceIsAtLeastDefault() {
// GIVEN
- val alertingEntry =
- NotificationEntryBuilder().setChannel(channel).setImportance(IMPORTANCE_DEFAULT).build()
- whenever(peopleNotificationIdentifier.getPeopleNotificationType(alertingEntry))
- .thenReturn(TYPE_PERSON)
+ val alertingEntry = makeEntryOfPeopleType(TYPE_PERSON) { setImportance(IMPORTANCE_DEFAULT) }
// put alerting people notifications in this section
assertThat(peopleAlertingSectioner.isInSection(alertingEntry)).isTrue()
@@ -162,10 +178,7 @@
@EnableFlags(Flags.FLAG_SORT_SECTION_BY_TIME)
fun testInAlertingPeopleSectionWhenTheImportanceIsLowerThanDefault() {
// GIVEN
- val silentEntry =
- NotificationEntryBuilder().setChannel(channel).setImportance(IMPORTANCE_LOW).build()
- whenever(peopleNotificationIdentifier.getPeopleNotificationType(silentEntry))
- .thenReturn(TYPE_PERSON)
+ val silentEntry = makeEntryOfPeopleType(TYPE_PERSON) { setImportance(IMPORTANCE_LOW) }
// THEN put silent people notifications in alerting section
assertThat(peopleAlertingSectioner.isInSection(silentEntry)).isTrue()
@@ -175,10 +188,7 @@
@DisableFlags(Flags.FLAG_SORT_SECTION_BY_TIME)
fun testInSilentPeopleSectionWhenTheImportanceIsLowerThanDefault() {
// GIVEN
- val silentEntry =
- NotificationEntryBuilder().setChannel(channel).setImportance(IMPORTANCE_LOW).build()
- whenever(peopleNotificationIdentifier.getPeopleNotificationType(silentEntry))
- .thenReturn(TYPE_PERSON)
+ val silentEntry = makeEntryOfPeopleType(TYPE_PERSON) { setImportance(IMPORTANCE_LOW) }
// THEN put silent people notifications in this section
assertThat(peopleSilentSectioner.isInSection(silentEntry)).isTrue()
@@ -191,18 +201,14 @@
@Test
fun testNotInPeopleSection() {
// GIVEN
- val entry =
- NotificationEntryBuilder().setChannel(channel).setImportance(IMPORTANCE_LOW).build()
+ val entry = makeEntryOfPeopleType(TYPE_NON_PERSON) { setImportance(IMPORTANCE_LOW) }
val importantEntry =
- NotificationEntryBuilder().setChannel(channel).setImportance(IMPORTANCE_HIGH).build()
- whenever(peopleNotificationIdentifier.getPeopleNotificationType(entry))
- .thenReturn(TYPE_NON_PERSON)
- whenever(peopleNotificationIdentifier.getPeopleNotificationType(importantEntry))
- .thenReturn(TYPE_NON_PERSON)
+ makeEntryOfPeopleType(TYPE_NON_PERSON) { setImportance(IMPORTANCE_HIGH) }
// THEN - only put people notification either silent or alerting
- if (!SortBySectionTimeFlag.isEnabled)
+ if (!SortBySectionTimeFlag.isEnabled) {
assertThat(peopleSilentSectioner.isInSection(entry)).isFalse()
+ }
assertThat(peopleAlertingSectioner.isInSection(importantEntry)).isFalse()
}
@@ -210,22 +216,16 @@
fun testInAlertingPeopleSectionWhenThereIsAnImportantChild() {
// GIVEN
val altChildA =
- NotificationEntryBuilder().setTag("A").setImportance(IMPORTANCE_DEFAULT).build()
- val altChildB = NotificationEntryBuilder().setTag("B").setImportance(IMPORTANCE_LOW).build()
- val summary =
- NotificationEntryBuilder()
- .setId(2)
- .setImportance(IMPORTANCE_LOW)
- .setChannel(channel)
- .build()
+ makeEntryOfPeopleType(TYPE_NON_PERSON) { setTag("A").setImportance(IMPORTANCE_DEFAULT) }
+ val altChildB =
+ makeEntryOfPeopleType(TYPE_NON_PERSON) { setTag("B").setImportance(IMPORTANCE_LOW) }
+ val summary = makeEntryOfPeopleType(TYPE_PERSON) { setId(2).setImportance(IMPORTANCE_LOW) }
val groupEntry =
GroupEntryBuilder()
.setParent(GroupEntry.ROOT_ENTRY)
.setSummary(summary)
.setChildren(listOf(altChildA, altChildB))
.build()
- whenever(peopleNotificationIdentifier.getPeopleNotificationType(summary))
- .thenReturn(TYPE_PERSON)
// THEN
assertThat(peopleAlertingSectioner.isInSection(groupEntry)).isTrue()
}
@@ -233,10 +233,12 @@
@Test
@DisableFlags(Flags.FLAG_SORT_SECTION_BY_TIME)
fun testComparatorPutsImportantPeopleFirst() {
- whenever(peopleNotificationIdentifier.getPeopleNotificationType(entryA))
- .thenReturn(TYPE_IMPORTANT_PERSON)
- whenever(peopleNotificationIdentifier.getPeopleNotificationType(entryB))
- .thenReturn(TYPE_PERSON)
+ val entryA =
+ makeEntryOfPeopleType(TYPE_IMPORTANT_PERSON) {
+ setSection(peopleAlertingSection).setTag("A")
+ }
+ val entryB =
+ makeEntryOfPeopleType(TYPE_PERSON) { setSection(peopleAlertingSection).setTag("B") }
// only put people notifications in this section
assertThat(peopleComparator.compare(entryA, entryB)).isEqualTo(-1)
@@ -245,10 +247,10 @@
@Test
@DisableFlags(Flags.FLAG_SORT_SECTION_BY_TIME)
fun testComparatorEquatesPeopleWithSameType() {
- whenever(peopleNotificationIdentifier.getPeopleNotificationType(entryA))
- .thenReturn(TYPE_PERSON)
- whenever(peopleNotificationIdentifier.getPeopleNotificationType(entryB))
- .thenReturn(TYPE_PERSON)
+ val entryA =
+ makeEntryOfPeopleType(TYPE_PERSON) { setSection(peopleAlertingSection).setTag("A") }
+ val entryB =
+ makeEntryOfPeopleType(TYPE_PERSON) { setSection(peopleAlertingSection).setTag("B") }
// only put people notifications in this section
assertThat(peopleComparator.compare(entryA, entryB)).isEqualTo(0)
@@ -259,4 +261,23 @@
fun testNoSecondarySortForConversations() {
assertThat(peopleAlertingSectioner.comparator).isNull()
}
+
+ private fun makeEntryOfPeopleType(
+ @PeopleNotificationType type: Int,
+ buildBlock: NotificationEntryBuilder.() -> Unit = {}
+ ): NotificationEntry {
+ val channel: NotificationChannel = mock()
+ whenever(channel.isImportantConversation).thenReturn(type == TYPE_IMPORTANT_PERSON)
+ val entry =
+ NotificationEntryBuilder()
+ .updateRanking {
+ it.setIsConversation(type != TYPE_NON_PERSON)
+ it.setShortcutInfo(if (type >= TYPE_FULL_PERSON) mock() else null)
+ it.setChannel(channel)
+ }
+ .also(buildBlock)
+ .build()
+ assertEquals(type, peopleNotificationIdentifier.getPeopleNotificationType(entry))
+ return entry
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt b/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
index 67c5564..1404340 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
@@ -29,11 +29,13 @@
import com.android.systemui.keyguard.MigrateClocksToBlueprint
import com.android.systemui.keyguard.shared.ComposeLockscreen
import com.android.systemui.scene.shared.flag.SceneContainerFlag
+import com.android.systemui.statusbar.notification.collection.SortBySectionTimeFlag
import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor
import com.android.systemui.statusbar.notification.interruption.VisualInterruptionRefactor
import com.android.systemui.statusbar.notification.shared.NotificationAvalancheSuppression
import com.android.systemui.statusbar.notification.shared.NotificationIconContainerRefactor
import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
+import com.android.systemui.statusbar.notification.shared.PriorityPeopleSection
import javax.inject.Inject
/** A class in which engineers can define flag dependencies */
@@ -49,6 +51,7 @@
NotificationsLiveDataStoreRefactor.token dependsOn NotificationIconContainerRefactor.token
FooterViewRefactor.token dependsOn NotificationIconContainerRefactor.token
NotificationAvalancheSuppression.token dependsOn VisualInterruptionRefactor.token
+ PriorityPeopleSection.token dependsOn SortBySectionTimeFlag.token
// SceneContainer dependencies
SceneContainerFlag.getFlagDependencies().forEach { (alpha, beta) -> alpha dependsOn beta }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
index 3d0fd89..af2c197 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
@@ -31,8 +31,10 @@
import com.android.systemui.statusbar.notification.icon.ConversationIconManager
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.PeopleNotificationType
+import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_IMPORTANT_PERSON
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_NON_PERSON
import com.android.systemui.statusbar.notification.stack.BUCKET_PEOPLE
+import com.android.systemui.statusbar.notification.stack.BUCKET_PRIORITY_PEOPLE
import javax.inject.Inject
/**
@@ -81,6 +83,13 @@
}
}
+ val priorityPeopleSectioner =
+ object : NotifSectioner("Priority People", BUCKET_PRIORITY_PEOPLE) {
+ override fun isInSection(entry: ListEntry): Boolean {
+ return getPeopleType(entry) == TYPE_IMPORTANT_PERSON
+ }
+ }
+
// TODO(b/330193582): Rename to just "People"
val peopleAlertingSectioner = object : NotifSectioner("People(alerting)", BUCKET_PEOPLE) {
override fun isInSection(entry: ListEntry): Boolean {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
index 387444b..4506385 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
@@ -26,6 +26,7 @@
import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider
import com.android.systemui.statusbar.notification.shared.NotificationMinimalismPrototype
import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
+import com.android.systemui.statusbar.notification.shared.PriorityPeopleSection
import javax.inject.Inject
/**
@@ -120,6 +121,9 @@
if (NotificationMinimalismPrototype.V2.isEnabled) {
mOrderedSections.add(keyguardCoordinator.unseenNotifSectioner) // Unseen (FGS)
}
+ if (PriorityPeopleSection.isEnabled) {
+ mOrderedSections.add(conversationCoordinator.priorityPeopleSectioner) // Priority People
+ }
mOrderedSections.add(conversationCoordinator.peopleAlertingSectioner) // People Alerting
if (!SortBySectionTimeFlag.isEnabled) {
mOrderedSections.add(conversationCoordinator.peopleSilentSectioner) // People Silent
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationPanelLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationPanelLogger.java
index 89aa3ab..9e0dd8fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationPanelLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationPanelLogger.java
@@ -21,6 +21,7 @@
import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_HEADS_UP;
import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_MEDIA_CONTROLS;
import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_PEOPLE;
+import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_PRIORITY_PEOPLE;
import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_SILENT;
import android.annotation.Nullable;
@@ -130,7 +131,8 @@
case BUCKET_HEADS_UP: return Notifications.Notification.SECTION_HEADS_UP;
case BUCKET_FOREGROUND_SERVICE:
return Notifications.Notification.SECTION_FOREGROUND_SERVICE;
- case BUCKET_PEOPLE: return Notifications.Notification.SECTION_PEOPLE;
+ case BUCKET_PEOPLE, BUCKET_PRIORITY_PEOPLE:
+ return Notifications.Notification.SECTION_PEOPLE;
case BUCKET_ALERTING: return Notifications.Notification.SECTION_ALERTING;
case BUCKET_SILENT: return Notifications.Notification.SECTION_SILENT;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/PriorityPeopleSection.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/PriorityPeopleSection.kt
new file mode 100644
index 0000000..472fd95
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/PriorityPeopleSection.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.statusbar.notification.shared
+
+import com.android.systemui.Flags
+import com.android.systemui.flags.FlagToken
+import com.android.systemui.flags.RefactorFlagUtils
+
+/** Helper for com.android.systemui.Flags.FLAG_PRIORITY_PEOPLE_SECTION */
+@Suppress("NOTHING_TO_INLINE")
+object PriorityPeopleSection {
+ const val FLAG_NAME = Flags.FLAG_PRIORITY_PEOPLE_SECTION
+
+ /** A token used for dependency declaration */
+ val token: FlagToken
+ get() = FlagToken(FLAG_NAME, isEnabled)
+
+ /** Are sections sorted by time? */
+ @JvmStatic
+ inline val isEnabled
+ get() = Flags.priorityPeopleSection()
+
+ /**
+ * Called to ensure code is only run when the flag is enabled. This protects users from the
+ * unintended behaviors caused by accidentally running new logic, while also crashing on an eng
+ * build to ensure that the refactor author catches issues in testing.
+ */
+ @JvmStatic
+ inline fun isUnexpectedlyInLegacyMode() =
+ RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME)
+
+ /**
+ * Called to ensure code is only run when the flag is disabled. This will throw an exception if
+ * the flag is enabled to ensure that the refactor author catches issues in testing.
+ */
+ @JvmStatic
+ inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationPriorityBucket.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationPriorityBucket.kt
index 31f4857..fc28a99 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationPriorityBucket.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationPriorityBucket.kt
@@ -3,15 +3,22 @@
import android.annotation.IntDef
/**
- * For now, declare the available notification buckets (sections) here so that other
- * presentation code can decide what to do based on an entry's buckets
+ * For now, declare the available notification buckets (sections) here so that other presentation
+ * code can decide what to do based on an entry's buckets
*/
@Retention(AnnotationRetention.SOURCE)
@IntDef(
- prefix = ["BUCKET_"],
- value = [
- BUCKET_UNKNOWN, BUCKET_MEDIA_CONTROLS, BUCKET_HEADS_UP, BUCKET_FOREGROUND_SERVICE,
- BUCKET_PEOPLE, BUCKET_ALERTING, BUCKET_SILENT
+ prefix = ["BUCKET_"],
+ value =
+ [
+ BUCKET_UNKNOWN,
+ BUCKET_MEDIA_CONTROLS,
+ BUCKET_HEADS_UP,
+ BUCKET_FOREGROUND_SERVICE,
+ BUCKET_PRIORITY_PEOPLE,
+ BUCKET_PEOPLE,
+ BUCKET_ALERTING,
+ BUCKET_SILENT
]
)
annotation class PriorityBucket
@@ -20,6 +27,7 @@
const val BUCKET_MEDIA_CONTROLS = 1
const val BUCKET_HEADS_UP = 2
const val BUCKET_FOREGROUND_SERVICE = 3
+const val BUCKET_PRIORITY_PEOPLE = 7
const val BUCKET_PEOPLE = 4
const val BUCKET_ALERTING = 5
const val BUCKET_SILENT = 6
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt
index 749c241..4b0b1e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt
@@ -388,7 +388,8 @@
null,
BUCKET_MEDIA_CONTROLS,
BUCKET_HEADS_UP,
- BUCKET_FOREGROUND_SERVICE -> false
+ BUCKET_FOREGROUND_SERVICE,
+ BUCKET_PRIORITY_PEOPLE -> false
else -> true
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java
index 2bd584e..562ac0c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java
@@ -27,6 +27,8 @@
import android.service.notification.SnoozeCriterion;
import android.service.notification.StatusBarNotification;
+import androidx.annotation.NonNull;
+
import com.android.internal.logging.InstanceId;
import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.SbnBuilder;
@@ -36,6 +38,7 @@
import kotlin.Unit;
import java.util.ArrayList;
+import java.util.function.Consumer;
/**
* Combined builder for constructing a NotificationEntry and its associated StatusBarNotification
@@ -73,6 +76,20 @@
mCreationTime = source.getCreationTime();
}
+ /** Allows the caller to sub-build the ranking */
+ @NonNull
+ public NotificationEntryBuilder updateRanking(@NonNull Consumer<RankingBuilder> rankingUpdater) {
+ rankingUpdater.accept(mRankingBuilder);
+ return this;
+ }
+
+ /** Allows the caller to sub-build the SBN */
+ @NonNull
+ public NotificationEntryBuilder updateSbn(@NonNull Consumer<SbnBuilder> sbnUpdater) {
+ sbnUpdater.accept(mSbnBuilder);
+ return this;
+ }
+
/** Update an the parent on an existing entry */
public static void setNewParent(NotificationEntry entry, GroupEntry parent) {
entry.setParent(parent);