summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt63
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinator.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt57
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/ActiveNotificationListRepository.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/SeenNotificationsInteractor.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationPriorityBucket.kt21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt52
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt69
9 files changed, 206 insertions, 110 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
index 2f293e072c84..f62b24aa96a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
@@ -18,33 +18,29 @@ package com.android.systemui.statusbar.notification
import android.content.Context
import android.provider.DeviceConfig
-
import com.android.internal.annotations.VisibleForTesting
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.NOTIFICATIONS_USE_PEOPLE_FILTERING
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.notification.shared.NotificationMinimalismPrototype
import com.android.systemui.statusbar.notification.shared.PriorityPeopleSection
import com.android.systemui.statusbar.notification.stack.BUCKET_ALERTING
import com.android.systemui.statusbar.notification.stack.BUCKET_FOREGROUND_SERVICE
import com.android.systemui.statusbar.notification.stack.BUCKET_HEADS_UP
import com.android.systemui.statusbar.notification.stack.BUCKET_MEDIA_CONTROLS
import com.android.systemui.statusbar.notification.stack.BUCKET_PEOPLE
-import com.android.systemui.statusbar.notification.stack.BUCKET_PRIORITY_PEOPLE
import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT
+import com.android.systemui.statusbar.notification.stack.PriorityBucket
import com.android.systemui.util.DeviceConfigProxy
import com.android.systemui.util.Utils
-
import javax.inject.Inject
private var sUsePeopleFiltering: Boolean? = null
-/**
- * Feature controller for the NOTIFICATIONS_USE_PEOPLE_FILTERING config.
- */
+/** Feature controller for the NOTIFICATIONS_USE_PEOPLE_FILTERING config. */
@SysUISingleton
-class NotificationSectionsFeatureManager @Inject constructor(
- val proxy: DeviceConfigProxy,
- val context: Context
-) {
+class NotificationSectionsFeatureManager
+@Inject
+constructor(val proxy: DeviceConfigProxy, val context: Context) {
fun isFilteringEnabled(): Boolean {
return usePeopleFiltering(proxy)
@@ -55,30 +51,37 @@ class NotificationSectionsFeatureManager @Inject constructor(
}
fun getNotificationBuckets(): IntArray {
- if (PriorityPeopleSection.isEnabled) {
+ if (PriorityPeopleSection.isEnabled || NotificationMinimalismPrototype.V2.isEnabled) {
// We don't need this list to be adaptive, it can be the superset of all features.
- return intArrayOf(
- BUCKET_MEDIA_CONTROLS,
+ return PriorityBucket.getAllInOrder()
+ }
+ return when {
+ isFilteringEnabled() && isMediaControlsEnabled() ->
+ intArrayOf(
BUCKET_HEADS_UP,
BUCKET_FOREGROUND_SERVICE,
- BUCKET_PRIORITY_PEOPLE,
+ BUCKET_MEDIA_CONTROLS,
BUCKET_PEOPLE,
BUCKET_ALERTING,
- BUCKET_SILENT,
+ BUCKET_SILENT
)
- }
- return when {
- isFilteringEnabled() && isMediaControlsEnabled() ->
- intArrayOf(BUCKET_HEADS_UP, BUCKET_FOREGROUND_SERVICE, BUCKET_MEDIA_CONTROLS,
- BUCKET_PEOPLE, BUCKET_ALERTING, BUCKET_SILENT)
!isFilteringEnabled() && isMediaControlsEnabled() ->
- intArrayOf(BUCKET_HEADS_UP, BUCKET_FOREGROUND_SERVICE, BUCKET_MEDIA_CONTROLS,
- BUCKET_ALERTING, BUCKET_SILENT)
+ intArrayOf(
+ BUCKET_HEADS_UP,
+ BUCKET_FOREGROUND_SERVICE,
+ BUCKET_MEDIA_CONTROLS,
+ BUCKET_ALERTING,
+ BUCKET_SILENT
+ )
isFilteringEnabled() && !isMediaControlsEnabled() ->
- intArrayOf(BUCKET_HEADS_UP, BUCKET_FOREGROUND_SERVICE, BUCKET_PEOPLE,
- BUCKET_ALERTING, BUCKET_SILENT)
- else ->
- intArrayOf(BUCKET_ALERTING, BUCKET_SILENT)
+ intArrayOf(
+ BUCKET_HEADS_UP,
+ BUCKET_FOREGROUND_SERVICE,
+ BUCKET_PEOPLE,
+ BUCKET_ALERTING,
+ BUCKET_SILENT
+ )
+ else -> intArrayOf(BUCKET_ALERTING, BUCKET_SILENT)
}
}
@@ -94,8 +97,12 @@ class NotificationSectionsFeatureManager @Inject constructor(
private fun usePeopleFiltering(proxy: DeviceConfigProxy): Boolean {
if (sUsePeopleFiltering == null) {
- sUsePeopleFiltering = proxy.getBoolean(
- DeviceConfig.NAMESPACE_SYSTEMUI, NOTIFICATIONS_USE_PEOPLE_FILTERING, true)
+ sUsePeopleFiltering =
+ proxy.getBoolean(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ NOTIFICATIONS_USE_PEOPLE_FILTERING,
+ true
+ )
}
return sUsePeopleFiltering!!
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinator.java
index 63997f8f2457..47a04291dd49 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinator.java
@@ -60,22 +60,27 @@ public class ColorizedFgsCoordinator implements Coordinator {
public boolean isInSection(ListEntry entry) {
NotificationEntry notificationEntry = entry.getRepresentativeEntry();
if (notificationEntry != null) {
- return isColorizedForegroundService(notificationEntry) || isCall(notificationEntry);
+ return isRichOngoing(notificationEntry);
}
return false;
}
+ };
- private boolean isColorizedForegroundService(NotificationEntry entry) {
- Notification notification = entry.getSbn().getNotification();
- return notification.isForegroundService()
- && notification.isColorized()
- && entry.getImportance() > IMPORTANCE_MIN;
- }
+ /** Determines if the given notification is a colorized or call notification */
+ public static boolean isRichOngoing(NotificationEntry entry) {
+ return isColorizedForegroundService(entry) || isCall(entry);
+ }
- private boolean isCall(NotificationEntry entry) {
- Notification notification = entry.getSbn().getNotification();
- return entry.getImportance() > IMPORTANCE_MIN
- && notification.isStyle(Notification.CallStyle.class);
- }
- };
+ private static boolean isColorizedForegroundService(NotificationEntry entry) {
+ Notification notification = entry.getSbn().getNotification();
+ return notification.isForegroundService()
+ && notification.isColorized()
+ && entry.getImportance() > IMPORTANCE_MIN;
+ }
+
+ private static boolean isCall(NotificationEntry entry) {
+ Notification notification = entry.getSbn().getNotification();
+ return entry.getImportance() > IMPORTANCE_MIN
+ && notification.isStyle(Notification.CallStyle.class);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt
index 071192b02ee0..5a1146d2472f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt
@@ -18,6 +18,7 @@
package com.android.systemui.statusbar.notification.collection.coordinator
+import android.app.NotificationManager
import android.os.UserHandle
import android.provider.Settings
import androidx.annotation.VisibleForTesting
@@ -44,7 +45,8 @@ import com.android.systemui.statusbar.notification.collection.provider.SectionHe
import com.android.systemui.statusbar.notification.domain.interactor.SeenNotificationsInteractor
import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider
import com.android.systemui.statusbar.notification.shared.NotificationMinimalismPrototype
-import com.android.systemui.statusbar.notification.stack.BUCKET_FOREGROUND_SERVICE
+import com.android.systemui.statusbar.notification.stack.BUCKET_TOP_ONGOING
+import com.android.systemui.statusbar.notification.stack.BUCKET_TOP_UNSEEN
import com.android.systemui.statusbar.policy.HeadsUpManager
import com.android.systemui.statusbar.policy.headsUpEvents
import com.android.systemui.util.asIndenting
@@ -113,7 +115,7 @@ constructor(
private fun attachUnseenFilter(pipeline: NotifPipeline) {
if (NotificationMinimalismPrototype.V2.isEnabled) {
pipeline.addPromoter(unseenNotifPromoter)
- pipeline.addOnBeforeTransformGroupsListener(::pickOutTopUnseenNotif)
+ pipeline.addOnBeforeTransformGroupsListener(::pickOutTopUnseenNotifs)
}
pipeline.addFinalizeFilter(unseenNotifFilter)
pipeline.addCollectionListener(collectionListener)
@@ -347,15 +349,16 @@ constructor(
}
}
- private fun pickOutTopUnseenNotif(list: List<ListEntry>) {
+ private fun pickOutTopUnseenNotifs(list: List<ListEntry>) {
if (NotificationMinimalismPrototype.V2.isUnexpectedlyInLegacyMode()) return
// Only ever elevate a top unseen notification on keyguard, not even locked shade
if (statusBarStateController.state != StatusBarState.KEYGUARD) {
+ seenNotificationsInteractor.setTopOngoingNotification(null)
seenNotificationsInteractor.setTopUnseenNotification(null)
return
}
// On keyguard pick the top-ranked unseen or ongoing notification to elevate
- seenNotificationsInteractor.setTopUnseenNotification(
+ val nonSummaryEntries: Sequence<NotificationEntry> =
list
.asSequence()
.flatMap {
@@ -365,7 +368,15 @@ constructor(
else -> error("unhandled type of $it")
}
}
- .filter { shouldIgnoreUnseenCheck(it) || it in unseenNotifications }
+ .filter { it.importance >= NotificationManager.IMPORTANCE_DEFAULT }
+ seenNotificationsInteractor.setTopOngoingNotification(
+ nonSummaryEntries
+ .filter { ColorizedFgsCoordinator.isRichOngoing(it) }
+ .minByOrNull { it.ranking.rank }
+ )
+ seenNotificationsInteractor.setTopUnseenNotification(
+ nonSummaryEntries
+ .filter { !ColorizedFgsCoordinator.isRichOngoing(it) && it in unseenNotifications }
.minByOrNull { it.ranking.rank }
)
}
@@ -375,29 +386,39 @@ constructor(
object : NotifPromoter("$TAG-unseen") {
override fun shouldPromoteToTopLevel(child: NotificationEntry): Boolean =
if (NotificationMinimalismPrototype.V2.isUnexpectedlyInLegacyMode()) false
+ else if (!NotificationMinimalismPrototype.V2.ungroupTopUnseen) false
else
- seenNotificationsInteractor.isTopUnseenNotification(child) &&
- NotificationMinimalismPrototype.V2.ungroupTopUnseen
+ seenNotificationsInteractor.isTopOngoingNotification(child) ||
+ seenNotificationsInteractor.isTopUnseenNotification(child)
}
- val unseenNotifSectioner =
- object : NotifSectioner("Unseen", BUCKET_FOREGROUND_SERVICE) {
+ val topOngoingSectioner =
+ object : NotifSectioner("TopOngoing", BUCKET_TOP_ONGOING) {
override fun isInSection(entry: ListEntry): Boolean {
if (NotificationMinimalismPrototype.V2.isUnexpectedlyInLegacyMode()) return false
- if (
- seenNotificationsInteractor.isTopUnseenNotification(entry.representativeEntry)
- ) {
- return true
+ return entry.anyEntry { notificationEntry ->
+ seenNotificationsInteractor.isTopOngoingNotification(notificationEntry)
}
- if (entry !is GroupEntry) {
- return false
- }
- return entry.children.any {
- seenNotificationsInteractor.isTopUnseenNotification(it)
+ }
+ }
+
+ val topUnseenSectioner =
+ object : NotifSectioner("TopUnseen", BUCKET_TOP_UNSEEN) {
+ override fun isInSection(entry: ListEntry): Boolean {
+ if (NotificationMinimalismPrototype.V2.isUnexpectedlyInLegacyMode()) return false
+ return entry.anyEntry { notificationEntry ->
+ seenNotificationsInteractor.isTopUnseenNotification(notificationEntry)
}
}
}
+ private fun ListEntry.anyEntry(predicate: (NotificationEntry?) -> Boolean) =
+ when {
+ predicate(representativeEntry) -> true
+ this !is GroupEntry -> false
+ else -> children.any(predicate)
+ }
+
@VisibleForTesting
internal val unseenNotifFilter =
object : NotifFilter("$TAG-unseen") {
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 4506385a2fb9..e41352254bac 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
@@ -116,11 +116,14 @@ constructor(
}
// Manually add Ordered Sections
+ if (NotificationMinimalismPrototype.V2.isEnabled) {
+ mOrderedSections.add(keyguardCoordinator.topOngoingSectioner) // Top Ongoing
+ }
mOrderedSections.add(headsUpCoordinator.sectioner) // HeadsUp
- mOrderedSections.add(colorizedFgsCoordinator.sectioner) // ForegroundService
if (NotificationMinimalismPrototype.V2.isEnabled) {
- mOrderedSections.add(keyguardCoordinator.unseenNotifSectioner) // Unseen (FGS)
+ mOrderedSections.add(keyguardCoordinator.topUnseenSectioner) // Top Unseen
}
+ mOrderedSections.add(colorizedFgsCoordinator.sectioner) // ForegroundService
if (PriorityPeopleSection.isEnabled) {
mOrderedSections.add(conversationCoordinator.priorityPeopleSectioner) // Priority People
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/ActiveNotificationListRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/ActiveNotificationListRepository.kt
index e2c9e02672d2..45d1034f2cfb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/ActiveNotificationListRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/ActiveNotificationListRepository.kt
@@ -42,6 +42,9 @@ class ActiveNotificationListRepository @Inject constructor() {
/** Stats about the list of notifications attached to the shade */
val notifStats = MutableStateFlow(NotifStats.empty)
+ /** The key of the top ongoing notification */
+ val topOngoingNotificationKey = MutableStateFlow<String?>(null)
+
/** The key of the top unseen notification */
val topUnseenNotificationKey = MutableStateFlow<String?>(null)
}
@@ -75,6 +78,7 @@ data class ActiveNotificationsStore(
/** Unique key identifying an [ActiveNotificationEntryModel] in the store. */
sealed class Key {
data class Individual(val key: String) : Key()
+
data class Group(val key: String) : Key()
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/SeenNotificationsInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/SeenNotificationsInteractor.kt
index 42828d99c7e4..85c66bd6f25a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/SeenNotificationsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/SeenNotificationsInteractor.kt
@@ -39,6 +39,18 @@ constructor(
notificationListRepository.hasFilteredOutSeenNotifications.value = value
}
+ /** Set the entry that is identified as the top ongoing notification. */
+ fun setTopOngoingNotification(entry: NotificationEntry?) {
+ if (NotificationMinimalismPrototype.V2.isUnexpectedlyInLegacyMode()) return
+ notificationListRepository.topOngoingNotificationKey.value = entry?.key
+ }
+
+ /** Determine if the given notification is the top ongoing notification. */
+ fun isTopOngoingNotification(entry: NotificationEntry?): Boolean =
+ if (NotificationMinimalismPrototype.V2.isUnexpectedlyInLegacyMode()) false
+ else
+ entry != null && notificationListRepository.topOngoingNotificationKey.value == entry.key
+
/** Set the entry that is identified as the top unseen notification. */
fun setTopUnseenNotification(entry: NotificationEntry?) {
if (NotificationMinimalismPrototype.V2.isUnexpectedlyInLegacyMode()) return
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 fc28a99ef4ef..fabb696d9182 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
@@ -13,7 +13,9 @@ import android.annotation.IntDef
[
BUCKET_UNKNOWN,
BUCKET_MEDIA_CONTROLS,
+ BUCKET_TOP_ONGOING,
BUCKET_HEADS_UP,
+ BUCKET_TOP_UNSEEN,
BUCKET_FOREGROUND_SERVICE,
BUCKET_PRIORITY_PEOPLE,
BUCKET_PEOPLE,
@@ -21,11 +23,28 @@ import android.annotation.IntDef
BUCKET_SILENT
]
)
-annotation class PriorityBucket
+annotation class PriorityBucket {
+ companion object {
+ fun getAllInOrder(): IntArray =
+ intArrayOf(
+ BUCKET_MEDIA_CONTROLS,
+ BUCKET_TOP_ONGOING,
+ BUCKET_HEADS_UP,
+ BUCKET_TOP_UNSEEN,
+ BUCKET_FOREGROUND_SERVICE,
+ BUCKET_PRIORITY_PEOPLE,
+ BUCKET_PEOPLE,
+ BUCKET_ALERTING,
+ BUCKET_SILENT,
+ )
+ }
+}
const val BUCKET_UNKNOWN = 0
const val BUCKET_MEDIA_CONTROLS = 1
+const val BUCKET_TOP_ONGOING = 8
const val BUCKET_HEADS_UP = 2
+const val BUCKET_TOP_UNSEEN = 9
const val BUCKET_FOREGROUND_SERVICE = 3
const val BUCKET_PRIORITY_PEOPLE = 7
const val BUCKET_PEOPLE = 4
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 4b0b1e0029f3..391bc43a784c 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
@@ -73,7 +73,8 @@ constructor(
private var maxNotificationsExcludesMedia = false
/** Whether we allow keyguard to show less important notifications above the shelf. */
- private var limitLockScreenToImportant = false
+ private val limitLockScreenToOneImportant
+ get() = NotificationMinimalismPrototype.V2.isEnabled
/** Minimum space between two notifications, see [calculateGapAndDividerHeight]. */
private var dividerHeight by notNull<Float>()
@@ -89,7 +90,7 @@ constructor(
}
private fun allowedByPolicy(stackHeight: StackHeight): Boolean =
- if (limitLockScreenToImportant && stackHeight.includesLessImportantNotification) {
+ if (stackHeight.shouldForceIntoShelf) {
log { "\tallowedByPolicy = false" }
false
} else {
@@ -333,8 +334,8 @@ constructor(
// changes during the lockscreen <=> full shade transition.
val shelfHeightWithSpaceBefore: Float,
- /** Whether this stack height includes less at least one important notification. */
- val includesLessImportantNotification: Boolean
+ /** Whether the stack should actually be forced into the shelf before this height. */
+ val shouldForceIntoShelf: Boolean
)
private fun computeHeightPerNotificationLimit(
@@ -347,7 +348,7 @@ constructor(
var previous: ExpandableView? = null
val onLockscreen = onLockscreen()
- var includesLessImportantNotification = false
+ val counter = if (limitLockScreenToOneImportant) BucketTypeCounter() else null
// Only shelf. This should never happen, since we allow 1 view minimum (EmptyViewState).
yield(
@@ -355,7 +356,7 @@ constructor(
notifsHeight = 0f,
notifsHeightSavingSpace = 0f,
shelfHeightWithSpaceBefore = shelfHeight,
- includesLessImportantNotification = includesLessImportantNotification,
+ shouldForceIntoShelf = false,
)
)
@@ -381,17 +382,9 @@ constructor(
spaceBeforeShelf + shelfHeight
}
- if (limitLockScreenToImportant && !includesLessImportantNotification) {
- val bucket = (currentNotification as? ExpandableNotificationRow)?.entry?.bucket
- includesLessImportantNotification =
- when (bucket) {
- null,
- BUCKET_MEDIA_CONTROLS,
- BUCKET_HEADS_UP,
- BUCKET_FOREGROUND_SERVICE,
- BUCKET_PRIORITY_PEOPLE -> false
- else -> true
- }
+ if (counter != null) {
+ val entry = (currentNotification as? ExpandableNotificationRow)?.entry
+ counter.incrementForBucket(entry?.bucket)
}
log {
@@ -404,7 +397,7 @@ constructor(
notifsHeight = notifications,
notifsHeightSavingSpace = notifsWithCollapsedHun,
shelfHeightWithSpaceBefore = shelfWithSpaceBefore,
- includesLessImportantNotification = includesLessImportantNotification,
+ shouldForceIntoShelf = counter?.shouldForceIntoShelf() ?: false
)
)
}
@@ -415,8 +408,6 @@ constructor(
infiniteIfNegative(
if (NotificationMinimalismPrototype.V1.isEnabled) {
NotificationMinimalismPrototype.V1.maxNotifs
- } else if (NotificationMinimalismPrototype.V2.isEnabled) {
- 1
} else {
resources.getInteger(R.integer.keyguard_max_notification_count)
}
@@ -424,7 +415,6 @@ constructor(
maxNotificationsExcludesMedia =
NotificationMinimalismPrototype.V1.isEnabled ||
NotificationMinimalismPrototype.V2.isEnabled
- limitLockScreenToImportant = NotificationMinimalismPrototype.V2.isEnabled
dividerHeight =
max(1f, resources.getDimensionPixelSize(R.dimen.notification_divider_height).toFloat())
@@ -552,4 +542,24 @@ constructor(
/** Returns the last index where [predicate] returns true, or -1 if it was always false. */
private fun <T> Sequence<T>.lastIndexWhile(predicate: (T) -> Boolean): Int =
takeWhile(predicate).count() - 1
+
+ /** Counts the number of notifications for each type of bucket */
+ data class BucketTypeCounter(
+ var ongoing: Int = 0,
+ var important: Int = 0,
+ var other: Int = 0,
+ ) {
+ fun incrementForBucket(@PriorityBucket bucket: Int?) {
+ when (bucket) {
+ BUCKET_MEDIA_CONTROLS,
+ null -> Unit // not counted as notifications at all
+ BUCKET_TOP_ONGOING -> ongoing++
+ BUCKET_HEADS_UP -> important++
+ BUCKET_TOP_UNSEEN -> important++
+ else -> other++
+ }
+ }
+
+ fun shouldForceIntoShelf(): Boolean = ongoing > 1 || important > 1 || other > 0
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt
index 9e733be6665c..acb005f6e72f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt
@@ -19,71 +19,86 @@ package com.android.systemui.statusbar.notification
import android.platform.test.annotations.DisableFlags
import android.provider.DeviceConfig
import android.provider.Settings
-
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.dx.mockito.inline.extended.ExtendedMockito
-
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.NOTIFICATIONS_USE_PEOPLE_FILTERING
import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.notification.shared.NotificationMinimalismPrototype
import com.android.systemui.statusbar.notification.shared.PriorityPeopleSection
import com.android.systemui.util.DeviceConfigProxyFake
import com.android.systemui.util.Utils
import com.android.systemui.util.mockito.any
-
import org.junit.After
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.Mockito.`when`
import org.mockito.MockitoSession
+import org.mockito.kotlin.whenever
import org.mockito.quality.Strictness
@RunWith(AndroidJUnit4::class)
@SmallTest
-@DisableFlags(PriorityPeopleSection.FLAG_NAME) // this class has no logic with the flag enabled
+// this class has no testable logic with either of these flags enabled
+@DisableFlags(PriorityPeopleSection.FLAG_NAME, NotificationMinimalismPrototype.V2.FLAG_NAME)
class NotificationSectionsFeatureManagerTest : SysuiTestCase() {
- var manager: NotificationSectionsFeatureManager? = null
- val proxyFake = DeviceConfigProxyFake()
+ lateinit var manager: NotificationSectionsFeatureManager
+ private val proxyFake = DeviceConfigProxyFake()
private lateinit var staticMockSession: MockitoSession
@Before
- public fun setup() {
+ fun setup() {
manager = NotificationSectionsFeatureManager(proxyFake, mContext)
- manager!!.clearCache()
- staticMockSession = ExtendedMockito.mockitoSession()
- .mockStatic<Utils>(Utils::class.java)
- .strictness(Strictness.LENIENT)
- .startMocking()
- `when`(Utils.useQsMediaPlayer(any())).thenReturn(false)
- Settings.Global.putInt(context.getContentResolver(),
- Settings.Global.SHOW_MEDIA_ON_QUICK_SETTINGS, 0)
+ manager.clearCache()
+ staticMockSession =
+ ExtendedMockito.mockitoSession()
+ .mockStatic(Utils::class.java)
+ .strictness(Strictness.LENIENT)
+ .startMocking()
+ whenever(Utils.useQsMediaPlayer(any())).thenReturn(false)
+ Settings.Global.putInt(
+ context.getContentResolver(),
+ Settings.Global.SHOW_MEDIA_ON_QUICK_SETTINGS,
+ 0
+ )
}
@After
- public fun teardown() {
+ fun teardown() {
staticMockSession.finishMocking()
}
@Test
- public fun testPeopleFilteringOff_newInterruptionModelOn() {
+ fun testPeopleFilteringOff_newInterruptionModelOn() {
proxyFake.setProperty(
- DeviceConfig.NAMESPACE_SYSTEMUI, NOTIFICATIONS_USE_PEOPLE_FILTERING, "false", false)
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ NOTIFICATIONS_USE_PEOPLE_FILTERING,
+ "false",
+ false
+ )
- assertFalse("People filtering should be disabled", manager!!.isFilteringEnabled())
- assertTrue("Expecting 2 buckets when people filtering is disabled",
- manager!!.getNumberOfBuckets() == 2)
+ assertFalse("People filtering should be disabled", manager.isFilteringEnabled())
+ assertTrue(
+ "Expecting 2 buckets when people filtering is disabled",
+ manager.getNumberOfBuckets() == 2
+ )
}
@Test
- public fun testPeopleFilteringOn_newInterruptionModelOn() {
+ fun testPeopleFilteringOn_newInterruptionModelOn() {
proxyFake.setProperty(
- DeviceConfig.NAMESPACE_SYSTEMUI, NOTIFICATIONS_USE_PEOPLE_FILTERING, "true", false)
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ NOTIFICATIONS_USE_PEOPLE_FILTERING,
+ "true",
+ false
+ )
- assertTrue("People filtering should be enabled", manager!!.isFilteringEnabled())
- assertTrue("Expecting 5 buckets when people filtering is enabled",
- manager!!.getNumberOfBuckets() == 5)
+ assertTrue("People filtering should be enabled", manager.isFilteringEnabled())
+ assertTrue(
+ "Expecting 5 buckets when people filtering is enabled",
+ manager.getNumberOfBuckets() == 5
+ )
}
}