summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt54
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt64
3 files changed, 83 insertions, 40 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
index 0529c94ed59a..23b5241b79ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
@@ -38,8 +38,7 @@ import com.android.systemui.statusbar.notification.collection.provider.LaunchFul
import com.android.systemui.statusbar.notification.collection.render.NodeController
import com.android.systemui.statusbar.notification.dagger.IncomingHeader
import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder
-import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider
-import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider.FullScreenIntentDecision
+import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionProvider
import com.android.systemui.statusbar.notification.logKey
import com.android.systemui.statusbar.notification.stack.BUCKET_HEADS_UP
import com.android.systemui.statusbar.policy.HeadsUpManager
@@ -69,12 +68,12 @@ class HeadsUpCoordinator @Inject constructor(
private val mSystemClock: SystemClock,
private val mHeadsUpManager: HeadsUpManager,
private val mHeadsUpViewBinder: HeadsUpViewBinder,
- private val mNotificationInterruptStateProvider: NotificationInterruptStateProvider,
+ private val mVisualInterruptionDecisionProvider: VisualInterruptionDecisionProvider,
private val mRemoteInputManager: NotificationRemoteInputManager,
private val mLaunchFullScreenIntentProvider: LaunchFullScreenIntentProvider,
private val mFlags: NotifPipelineFlags,
@IncomingHeader private val mIncomingHeaderController: NodeController,
- @Main private val mExecutor: DelayableExecutor,
+ @Main private val mExecutor: DelayableExecutor
) : Coordinator {
private val mEntriesBindingUntil = ArrayMap<String, Long>()
private val mEntriesUpdateTimes = ArrayMap<String, Long>()
@@ -388,18 +387,21 @@ class HeadsUpCoordinator @Inject constructor(
override fun onEntryAdded(entry: NotificationEntry) {
// First check whether this notification should launch a full screen intent, and
// launch it if needed.
- val fsiDecision = mNotificationInterruptStateProvider.getFullScreenIntentDecision(entry)
- mNotificationInterruptStateProvider.logFullScreenIntentDecision(entry, fsiDecision)
- if (fsiDecision.shouldLaunch) {
+ val fsiDecision =
+ mVisualInterruptionDecisionProvider.makeUnloggedFullScreenIntentDecision(entry)
+ mVisualInterruptionDecisionProvider.logFullScreenIntentDecision(fsiDecision)
+ if (fsiDecision.shouldInterrupt) {
mLaunchFullScreenIntentProvider.launchFullScreenIntent(entry)
- } else if (fsiDecision == FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND) {
+ } else if (fsiDecision.wouldInterruptWithoutDnd) {
// If DND was the only reason this entry was suppressed, note it for potential
// reconsideration on later ranking updates.
addForFSIReconsideration(entry, mSystemClock.currentTimeMillis())
}
- // shouldHeadsUp includes check for whether this notification should be filtered
- val shouldHeadsUpEver = mNotificationInterruptStateProvider.shouldHeadsUp(entry)
+ // makeAndLogHeadsUpDecision includes check for whether this notification should be
+ // filtered
+ val shouldHeadsUpEver =
+ mVisualInterruptionDecisionProvider.makeAndLogHeadsUpDecision(entry).shouldInterrupt
mPostedEntries[entry.key] = PostedEntry(
entry,
wasAdded = true,
@@ -420,7 +422,8 @@ class HeadsUpCoordinator @Inject constructor(
* up again.
*/
override fun onEntryUpdated(entry: NotificationEntry) {
- val shouldHeadsUpEver = mNotificationInterruptStateProvider.shouldHeadsUp(entry)
+ val shouldHeadsUpEver =
+ mVisualInterruptionDecisionProvider.makeAndLogHeadsUpDecision(entry).shouldInterrupt
val shouldHeadsUpAgain = shouldHunAgain(entry)
val isAlerting = mHeadsUpManager.isAlerting(entry.key)
val isBinding = isEntryBinding(entry)
@@ -510,26 +513,26 @@ class HeadsUpCoordinator @Inject constructor(
// If any of these entries are no longer suppressed, launch the FSI now.
if (isCandidateForFSIReconsideration(entry)) {
val decision =
- mNotificationInterruptStateProvider.getFullScreenIntentDecision(entry)
- if (decision.shouldLaunch) {
+ mVisualInterruptionDecisionProvider.makeUnloggedFullScreenIntentDecision(
+ entry
+ )
+ if (decision.shouldInterrupt) {
// Log both the launch of the full screen and also that this was via a
// ranking update, and finally revoke candidacy for FSI reconsideration
- mLogger.logEntryUpdatedToFullScreen(entry.key, decision.name)
- mNotificationInterruptStateProvider.logFullScreenIntentDecision(
- entry, decision)
+ mLogger.logEntryUpdatedToFullScreen(entry.key, decision.logReason)
+ mVisualInterruptionDecisionProvider.logFullScreenIntentDecision(decision)
mLaunchFullScreenIntentProvider.launchFullScreenIntent(entry)
mFSIUpdateCandidates.remove(entry.key)
// if we launch the FSI then this is no longer a candidate for HUN
continue
- } else if (decision == FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND) {
+ } else if (decision.wouldInterruptWithoutDnd) {
// decision has not changed; no need to log
} else {
// some other condition is now blocking FSI; log that and revoke candidacy
// for FSI reconsideration
- mLogger.logEntryDisqualifiedFromFullScreen(entry.key, decision.name)
- mNotificationInterruptStateProvider.logFullScreenIntentDecision(
- entry, decision)
+ mLogger.logEntryDisqualifiedFromFullScreen(entry.key, decision.logReason)
+ mVisualInterruptionDecisionProvider.logFullScreenIntentDecision(decision)
mFSIUpdateCandidates.remove(entry.key)
}
}
@@ -539,13 +542,18 @@ class HeadsUpCoordinator @Inject constructor(
// state
// - if it is present in PostedEntries and the previous state of shouldHeadsUp
// differs from the updated one
- val shouldHeadsUpEver = mNotificationInterruptStateProvider.checkHeadsUp(entry,
- /* log= */ false)
+ val decision =
+ mVisualInterruptionDecisionProvider.makeUnloggedHeadsUpDecision(entry)
+ val shouldHeadsUpEver = decision.shouldInterrupt
val postedShouldHeadsUpEver = mPostedEntries[entry.key]?.shouldHeadsUpEver ?: false
val shouldUpdateEntry = postedShouldHeadsUpEver != shouldHeadsUpEver
if (shouldUpdateEntry) {
- mLogger.logEntryUpdatedByRanking(entry.key, shouldHeadsUpEver)
+ mLogger.logEntryUpdatedByRanking(
+ entry.key,
+ shouldHeadsUpEver,
+ decision.logReason
+ )
onEntryUpdated(entry)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt
index e9365594fad7..32c3c6665b6f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt
@@ -61,12 +61,13 @@ class HeadsUpCoordinatorLogger constructor(
})
}
- fun logEntryUpdatedByRanking(key: String, shouldHun: Boolean) {
+ fun logEntryUpdatedByRanking(key: String, shouldHun: Boolean, reason: String) {
buffer.log(TAG, LogLevel.DEBUG, {
str1 = key
bool1 = shouldHun
+ str2 = reason
}, {
- "updating entry via ranking applied: $str1 updated shouldHeadsUp=$bool1"
+ "updating entry via ranking applied: $str1 updated shouldHeadsUp=$bool1 because $str2"
})
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
index 67128ff5624a..283efe263f04 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
@@ -38,8 +38,10 @@ import com.android.systemui.statusbar.notification.collection.notifcollection.No
import com.android.systemui.statusbar.notification.collection.provider.LaunchFullScreenIntentProvider
import com.android.systemui.statusbar.notification.collection.render.NodeController
import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder
-import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider.FullScreenIntentDecision
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderWrapper.DecisionImpl
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderWrapper.FullScreenIntentDecisionImpl
+import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionProvider
import com.android.systemui.statusbar.notification.row.NotifBindPipeline.BindCallback
import com.android.systemui.statusbar.phone.NotificationGroupTestHelper
import com.android.systemui.statusbar.policy.HeadsUpManager
@@ -52,6 +54,7 @@ import com.android.systemui.util.mockito.withArgCaptor
import com.android.systemui.util.time.FakeSystemClock
import java.util.ArrayList
import java.util.function.Consumer
+import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
@@ -86,7 +89,7 @@ class HeadsUpCoordinatorTest : SysuiTestCase() {
private val logger = HeadsUpCoordinatorLogger(logcatLogBuffer(), verbose = true)
private val headsUpManager: HeadsUpManager = mock()
private val headsUpViewBinder: HeadsUpViewBinder = mock()
- private val notificationInterruptStateProvider: NotificationInterruptStateProvider = mock()
+ private val visualInterruptionDecisionProvider: VisualInterruptionDecisionProvider = mock()
private val remoteInputManager: NotificationRemoteInputManager = mock()
private val endLifetimeExtension: OnEndLifetimeExtensionCallback = mock()
private val headerController: NodeController = mock()
@@ -114,7 +117,7 @@ class HeadsUpCoordinatorTest : SysuiTestCase() {
systemClock,
headsUpManager,
headsUpViewBinder,
- notificationInterruptStateProvider,
+ visualInterruptionDecisionProvider,
remoteInputManager,
launchFullScreenIntentProvider,
flags,
@@ -168,8 +171,11 @@ class HeadsUpCoordinatorTest : SysuiTestCase() {
groupChild2 = helper.createChildNotification(GROUP_ALERT_ALL, 2, "child", 250)
groupChild3 = helper.createChildNotification(GROUP_ALERT_ALL, 3, "child", 150)
+ // Set the default HUN decision
+ setDefaultShouldHeadsUp(false)
+
// Set the default FSI decision
- setShouldFullScreen(any(), FullScreenIntentDecision.NO_FULL_SCREEN_INTENT)
+ setDefaultShouldFullScreen(FullScreenIntentDecision.NO_FULL_SCREEN_INTENT)
}
@Test
@@ -1006,31 +1012,59 @@ class HeadsUpCoordinatorTest : SysuiTestCase() {
verify(launchFullScreenIntentProvider, never()).launchFullScreenIntent(entry)
}
+ private fun setDefaultShouldHeadsUp(should: Boolean) {
+ whenever(visualInterruptionDecisionProvider.makeAndLogHeadsUpDecision(any()))
+ .thenReturn(DecisionImpl.of(should))
+ whenever(visualInterruptionDecisionProvider.makeUnloggedHeadsUpDecision(any()))
+ .thenReturn(DecisionImpl.of(should))
+ }
+
private fun setShouldHeadsUp(entry: NotificationEntry, should: Boolean = true) {
- whenever(notificationInterruptStateProvider.shouldHeadsUp(entry)).thenReturn(should)
- whenever(notificationInterruptStateProvider.checkHeadsUp(eq(entry), any()))
- .thenReturn(should)
+ whenever(visualInterruptionDecisionProvider.makeAndLogHeadsUpDecision(entry))
+ .thenReturn(DecisionImpl.of(should))
+ whenever(visualInterruptionDecisionProvider.makeUnloggedHeadsUpDecision(entry))
+ .thenReturn(DecisionImpl.of(should))
}
- private fun setShouldFullScreen(entry: NotificationEntry, decision: FullScreenIntentDecision) {
- whenever(notificationInterruptStateProvider.getFullScreenIntentDecision(entry))
- .thenReturn(decision)
+ private fun setDefaultShouldFullScreen(
+ originalDecision: FullScreenIntentDecision
+ ) {
+ val provider = visualInterruptionDecisionProvider
+ whenever(provider.makeUnloggedFullScreenIntentDecision(any())).thenAnswer {
+ val entry: NotificationEntry = it.getArgument(0)
+ FullScreenIntentDecisionImpl(entry, originalDecision)
+ }
+ }
+
+ private fun setShouldFullScreen(
+ entry: NotificationEntry,
+ originalDecision: FullScreenIntentDecision
+ ) {
+ whenever(
+ visualInterruptionDecisionProvider.makeUnloggedFullScreenIntentDecision(entry)
+ ).thenAnswer {
+ FullScreenIntentDecisionImpl(entry, originalDecision)
+ }
}
private fun verifyLoggedFullScreenIntentDecision(
entry: NotificationEntry,
- decision: FullScreenIntentDecision
+ originalDecision: FullScreenIntentDecision
) {
- verify(notificationInterruptStateProvider).logFullScreenIntentDecision(entry, decision)
+ val decision = withArgCaptor {
+ verify(visualInterruptionDecisionProvider).logFullScreenIntentDecision(capture())
+ }
+ check(decision is FullScreenIntentDecisionImpl)
+ assertEquals(entry, decision.originalEntry)
+ assertEquals(originalDecision, decision.originalDecision)
}
private fun verifyNoFullScreenIntentDecisionLogged() {
- verify(notificationInterruptStateProvider, never())
- .logFullScreenIntentDecision(any(), any())
+ verify(visualInterruptionDecisionProvider, never()).logFullScreenIntentDecision(any())
}
private fun clearInterruptionProviderInvocations() {
- clearInvocations(notificationInterruptStateProvider)
+ clearInvocations(visualInterruptionDecisionProvider)
}
private fun finishBind(entry: NotificationEntry) {