Loading core/java/android/app/Notification.java +7 −0 Original line number Original line Diff line number Diff line Loading @@ -3907,6 +3907,13 @@ public class Notification implements Parcelable return mLargeIcon; return mLargeIcon; } } /** * @hide */ public boolean hasAppProvidedWhen() { return when != 0 && when != creationTime; } /** /** * @hide * @hide */ */ Loading core/java/android/app/notification.aconfig +7 −0 Original line number Original line Diff line number Diff line Loading @@ -82,3 +82,10 @@ flag { purpose: PURPOSE_BUGFIX purpose: PURPOSE_BUGFIX } } } } flag { name: "sort_section_by_time" namespace: "systemui" description: "Changes notification sort order to be by time within a section" bug: "330193582" } No newline at end of file packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SortBySectionTimeFlag.kt 0 → 100644 +53 −0 Original line number Original line Diff line number Diff line /* * 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.collection import android.app.Flags; import com.android.systemui.flags.FlagToken import com.android.systemui.flags.RefactorFlagUtils /** * Helper for android.app.Flags.FLAG_SORT_BY_SECTION_TIME */ @Suppress("NOTHING_TO_INLINE") object SortBySectionTimeFlag { const val FLAG_NAME = Flags.FLAG_SORT_SECTION_BY_TIME /** 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.sortSectionByTime() /** * 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) } No newline at end of file packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt +25 −6 Original line number Original line Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator import com.android.systemui.statusbar.notification.collection.ListEntry import com.android.systemui.statusbar.notification.collection.ListEntry import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.SortBySectionTimeFlag import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifComparator import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifComparator Loading Loading @@ -80,11 +81,20 @@ class ConversationCoordinator @Inject constructor( } } } } // TODO(b/330193582): Rename to just "People" val peopleAlertingSectioner = object : NotifSectioner("People(alerting)", BUCKET_PEOPLE) { val peopleAlertingSectioner = object : NotifSectioner("People(alerting)", BUCKET_PEOPLE) { override fun isInSection(entry: ListEntry): Boolean = override fun isInSection(entry: ListEntry): Boolean { highPriorityProvider.isHighPriorityConversation(entry) if (SortBySectionTimeFlag.isEnabled) { return highPriorityProvider.isHighPriorityConversation(entry) || isConversation(entry) } else { return highPriorityProvider.isHighPriorityConversation(entry) } } override fun getComparator(): NotifComparator = notifComparator override fun getComparator(): NotifComparator? { return if (SortBySectionTimeFlag.isEnabled) null else notifComparator } override fun getHeaderNodeController(): NodeController? = conversationHeaderNodeController override fun getHeaderNodeController(): NodeController? = conversationHeaderNodeController } } Loading @@ -92,11 +102,20 @@ class ConversationCoordinator @Inject constructor( val peopleSilentSectioner = object : NotifSectioner("People(silent)", BUCKET_PEOPLE) { val peopleSilentSectioner = object : NotifSectioner("People(silent)", BUCKET_PEOPLE) { // Because the peopleAlertingSectioner is above this one, it will claim all conversations that are alerting. // Because the peopleAlertingSectioner is above this one, it will claim all conversations that are alerting. // All remaining conversations must be silent. // All remaining conversations must be silent. override fun isInSection(entry: ListEntry): Boolean = isConversation(entry) override fun isInSection(entry: ListEntry): Boolean { SortBySectionTimeFlag.assertInLegacyMode() return isConversation(entry) } override fun getComparator(): NotifComparator = notifComparator override fun getComparator(): NotifComparator { SortBySectionTimeFlag.assertInLegacyMode() return notifComparator } override fun getHeaderNodeController(): NodeController? = conversationHeaderNodeController override fun getHeaderNodeController(): NodeController? { SortBySectionTimeFlag.assertInLegacyMode() return conversationHeaderNodeController } } } override fun attach(pipeline: NotifPipeline) { override fun attach(pipeline: NotifPipeline) { Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt +16 −6 Original line number Original line Diff line number Diff line Loading @@ -20,6 +20,7 @@ import com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.PipelineDumpable import com.android.systemui.statusbar.notification.collection.PipelineDumpable import com.android.systemui.statusbar.notification.collection.PipelineDumper import com.android.systemui.statusbar.notification.collection.PipelineDumper import com.android.systemui.statusbar.notification.collection.SortBySectionTimeFlag import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider Loading Loading @@ -114,18 +115,27 @@ class NotifCoordinatorsImpl @Inject constructor( mOrderedSections.add(headsUpCoordinator.sectioner) // HeadsUp mOrderedSections.add(headsUpCoordinator.sectioner) // HeadsUp mOrderedSections.add(colorizedFgsCoordinator.sectioner) // ForegroundService mOrderedSections.add(colorizedFgsCoordinator.sectioner) // ForegroundService mOrderedSections.add(conversationCoordinator.peopleAlertingSectioner) // People Alerting mOrderedSections.add(conversationCoordinator.peopleAlertingSectioner) // People Alerting if (!SortBySectionTimeFlag.isEnabled) { mOrderedSections.add(conversationCoordinator.peopleSilentSectioner) // People Silent mOrderedSections.add(conversationCoordinator.peopleSilentSectioner) // People Silent } mOrderedSections.add(rankingCoordinator.alertingSectioner) // Alerting mOrderedSections.add(rankingCoordinator.alertingSectioner) // Alerting mOrderedSections.add(rankingCoordinator.silentSectioner) // Silent mOrderedSections.add(rankingCoordinator.silentSectioner) // Silent mOrderedSections.add(rankingCoordinator.minimizedSectioner) // Minimized mOrderedSections.add(rankingCoordinator.minimizedSectioner) // Minimized sectionStyleProvider.setMinimizedSections(setOf(rankingCoordinator.minimizedSectioner)) sectionStyleProvider.setMinimizedSections(setOf(rankingCoordinator.minimizedSectioner)) if (SortBySectionTimeFlag.isEnabled) { sectionStyleProvider.setSilentSections(listOf( rankingCoordinator.silentSectioner, rankingCoordinator.minimizedSectioner, )) } else { sectionStyleProvider.setSilentSections(listOf( sectionStyleProvider.setSilentSections(listOf( conversationCoordinator.peopleSilentSectioner, conversationCoordinator.peopleSilentSectioner, rankingCoordinator.silentSectioner, rankingCoordinator.silentSectioner, rankingCoordinator.minimizedSectioner, rankingCoordinator.minimizedSectioner, )) )) } } } /** /** * Sends the pipeline to each coordinator when the pipeline is ready to accept * Sends the pipeline to each coordinator when the pipeline is ready to accept Loading Loading
core/java/android/app/Notification.java +7 −0 Original line number Original line Diff line number Diff line Loading @@ -3907,6 +3907,13 @@ public class Notification implements Parcelable return mLargeIcon; return mLargeIcon; } } /** * @hide */ public boolean hasAppProvidedWhen() { return when != 0 && when != creationTime; } /** /** * @hide * @hide */ */ Loading
core/java/android/app/notification.aconfig +7 −0 Original line number Original line Diff line number Diff line Loading @@ -82,3 +82,10 @@ flag { purpose: PURPOSE_BUGFIX purpose: PURPOSE_BUGFIX } } } } flag { name: "sort_section_by_time" namespace: "systemui" description: "Changes notification sort order to be by time within a section" bug: "330193582" } No newline at end of file
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SortBySectionTimeFlag.kt 0 → 100644 +53 −0 Original line number Original line Diff line number Diff line /* * 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.collection import android.app.Flags; import com.android.systemui.flags.FlagToken import com.android.systemui.flags.RefactorFlagUtils /** * Helper for android.app.Flags.FLAG_SORT_BY_SECTION_TIME */ @Suppress("NOTHING_TO_INLINE") object SortBySectionTimeFlag { const val FLAG_NAME = Flags.FLAG_SORT_SECTION_BY_TIME /** 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.sortSectionByTime() /** * 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) } No newline at end of file
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt +25 −6 Original line number Original line Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator import com.android.systemui.statusbar.notification.collection.ListEntry import com.android.systemui.statusbar.notification.collection.ListEntry import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.SortBySectionTimeFlag import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifComparator import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifComparator Loading Loading @@ -80,11 +81,20 @@ class ConversationCoordinator @Inject constructor( } } } } // TODO(b/330193582): Rename to just "People" val peopleAlertingSectioner = object : NotifSectioner("People(alerting)", BUCKET_PEOPLE) { val peopleAlertingSectioner = object : NotifSectioner("People(alerting)", BUCKET_PEOPLE) { override fun isInSection(entry: ListEntry): Boolean = override fun isInSection(entry: ListEntry): Boolean { highPriorityProvider.isHighPriorityConversation(entry) if (SortBySectionTimeFlag.isEnabled) { return highPriorityProvider.isHighPriorityConversation(entry) || isConversation(entry) } else { return highPriorityProvider.isHighPriorityConversation(entry) } } override fun getComparator(): NotifComparator = notifComparator override fun getComparator(): NotifComparator? { return if (SortBySectionTimeFlag.isEnabled) null else notifComparator } override fun getHeaderNodeController(): NodeController? = conversationHeaderNodeController override fun getHeaderNodeController(): NodeController? = conversationHeaderNodeController } } Loading @@ -92,11 +102,20 @@ class ConversationCoordinator @Inject constructor( val peopleSilentSectioner = object : NotifSectioner("People(silent)", BUCKET_PEOPLE) { val peopleSilentSectioner = object : NotifSectioner("People(silent)", BUCKET_PEOPLE) { // Because the peopleAlertingSectioner is above this one, it will claim all conversations that are alerting. // Because the peopleAlertingSectioner is above this one, it will claim all conversations that are alerting. // All remaining conversations must be silent. // All remaining conversations must be silent. override fun isInSection(entry: ListEntry): Boolean = isConversation(entry) override fun isInSection(entry: ListEntry): Boolean { SortBySectionTimeFlag.assertInLegacyMode() return isConversation(entry) } override fun getComparator(): NotifComparator = notifComparator override fun getComparator(): NotifComparator { SortBySectionTimeFlag.assertInLegacyMode() return notifComparator } override fun getHeaderNodeController(): NodeController? = conversationHeaderNodeController override fun getHeaderNodeController(): NodeController? { SortBySectionTimeFlag.assertInLegacyMode() return conversationHeaderNodeController } } } override fun attach(pipeline: NotifPipeline) { override fun attach(pipeline: NotifPipeline) { Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt +16 −6 Original line number Original line Diff line number Diff line Loading @@ -20,6 +20,7 @@ import com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.PipelineDumpable import com.android.systemui.statusbar.notification.collection.PipelineDumpable import com.android.systemui.statusbar.notification.collection.PipelineDumper import com.android.systemui.statusbar.notification.collection.PipelineDumper import com.android.systemui.statusbar.notification.collection.SortBySectionTimeFlag import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider Loading Loading @@ -114,18 +115,27 @@ class NotifCoordinatorsImpl @Inject constructor( mOrderedSections.add(headsUpCoordinator.sectioner) // HeadsUp mOrderedSections.add(headsUpCoordinator.sectioner) // HeadsUp mOrderedSections.add(colorizedFgsCoordinator.sectioner) // ForegroundService mOrderedSections.add(colorizedFgsCoordinator.sectioner) // ForegroundService mOrderedSections.add(conversationCoordinator.peopleAlertingSectioner) // People Alerting mOrderedSections.add(conversationCoordinator.peopleAlertingSectioner) // People Alerting if (!SortBySectionTimeFlag.isEnabled) { mOrderedSections.add(conversationCoordinator.peopleSilentSectioner) // People Silent mOrderedSections.add(conversationCoordinator.peopleSilentSectioner) // People Silent } mOrderedSections.add(rankingCoordinator.alertingSectioner) // Alerting mOrderedSections.add(rankingCoordinator.alertingSectioner) // Alerting mOrderedSections.add(rankingCoordinator.silentSectioner) // Silent mOrderedSections.add(rankingCoordinator.silentSectioner) // Silent mOrderedSections.add(rankingCoordinator.minimizedSectioner) // Minimized mOrderedSections.add(rankingCoordinator.minimizedSectioner) // Minimized sectionStyleProvider.setMinimizedSections(setOf(rankingCoordinator.minimizedSectioner)) sectionStyleProvider.setMinimizedSections(setOf(rankingCoordinator.minimizedSectioner)) if (SortBySectionTimeFlag.isEnabled) { sectionStyleProvider.setSilentSections(listOf( rankingCoordinator.silentSectioner, rankingCoordinator.minimizedSectioner, )) } else { sectionStyleProvider.setSilentSections(listOf( sectionStyleProvider.setSilentSections(listOf( conversationCoordinator.peopleSilentSectioner, conversationCoordinator.peopleSilentSectioner, rankingCoordinator.silentSectioner, rankingCoordinator.silentSectioner, rankingCoordinator.minimizedSectioner, rankingCoordinator.minimizedSectioner, )) )) } } } /** /** * Sends the pipeline to each coordinator when the pipeline is ready to accept * Sends the pipeline to each coordinator when the pipeline is ready to accept Loading