diff options
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 + ) } } |