diff options
author | 2024-05-15 14:36:27 +0000 | |
---|---|---|
committer | 2024-05-15 14:36:27 +0000 | |
commit | e3a190635b11f09a9c2febe9ec6f0890d070cbee (patch) | |
tree | f60099b28bdfabd3d4752122cf91b0b6561a361d | |
parent | 9ae3f701a580f155451d21e8002f15ca0b54c104 (diff) | |
parent | 91e01cbc0d3b02c09f490bab9a7929b654730867 (diff) |
Merge "Add a section just for priority people" into main
10 files changed, 198 insertions, 75 deletions
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig index 582b6a1489f7..204429b53674 100644 --- a/packages/SystemUI/aconfig/systemui.aconfig +++ b/packages/SystemUI/aconfig/systemui.aconfig @@ -34,6 +34,13 @@ flag { } 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 index c5d7e1f490ee..285326421a14 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_HIGH 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.GroupMember 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 @@ class ConversationCoordinatorTest : SysuiTestCase() { 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 @@ class ConversationCoordinatorTest : SysuiTestCase() { HighPriorityProvider(peopleNotificationIdentifier, GroupMembershipManagerImpl()), headerController ) - whenever(channel.isImportantConversation).thenReturn(true) coordinator.attach(pipeline) @@ -110,49 +110,65 @@ class ConversationCoordinatorTest : SysuiTestCase() { 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 @@ class ConversationCoordinatorTest : SysuiTestCase() { @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 @@ class ConversationCoordinatorTest : SysuiTestCase() { @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 @@ class ConversationCoordinatorTest : SysuiTestCase() { @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 @@ class ConversationCoordinatorTest : SysuiTestCase() { 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 @@ class ConversationCoordinatorTest : SysuiTestCase() { @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 @@ class ConversationCoordinatorTest : SysuiTestCase() { @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 @@ class ConversationCoordinatorTest : SysuiTestCase() { 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 67c556409615..140434040ca7 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.KeyguardBottomAreaRefactor 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 @@ class FlagDependencies @Inject constructor(featureFlags: FeatureFlagsClassic, ha 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 3d0fd89dce88..af2c1979ff77 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.dagger.PeopleHeader 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 @@ class ConversationCoordinator @Inject constructor( } } + 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 387444bec1c0..4506385a2fb9 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.listbuilder.plugga 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 @@ constructor( 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 89aa3ab9c84d..9e0dd8fc4d92 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.NotificationPrio 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 @@ public interface NotificationPanelLogger { 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 000000000000..472fd9564963 --- /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 31f4857e4b04..fc28a99ef4ef 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 @@ package com.android.systemui.statusbar.notification.stack 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_UNKNOWN = 0 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 749c241ce00c..4b0b1e0029f3 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 @@ constructor( 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 2bd584eac5e3..562ac0c15a0b 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.NotificationListenerService.Ranking; 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 com.android.systemui.util.time.FakeSystemClock; 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 @@ public class NotificationEntryBuilder { 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); |