Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 57029c61 authored by Julia Tuttle's avatar Julia Tuttle Committed by Android (Google) Code Review
Browse files

Merge changes from topic "interruptions-refactor-1" into udc-dev

* changes:
  Migrate Bubble checks to new Provider
  Migrate HUN/FSI checks to new Provider
  Add logReason to visual interruption decisions
parents fab937d7 b8be82a1
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -288,7 +288,7 @@ public abstract class SystemUIModule {
            INotificationManager notificationManager,
            INotificationManager notificationManager,
            IDreamManager dreamManager,
            IDreamManager dreamManager,
            NotificationVisibilityProvider visibilityProvider,
            NotificationVisibilityProvider visibilityProvider,
            NotificationInterruptStateProvider interruptionStateProvider,
            VisualInterruptionDecisionProvider visualInterruptionDecisionProvider,
            ZenModeController zenModeController,
            ZenModeController zenModeController,
            NotificationLockscreenUserManager notifUserManager,
            NotificationLockscreenUserManager notifUserManager,
            CommonNotifCollection notifCollection,
            CommonNotifCollection notifCollection,
@@ -306,7 +306,7 @@ public abstract class SystemUIModule {
                notificationManager,
                notificationManager,
                dreamManager,
                dreamManager,
                visibilityProvider,
                visibilityProvider,
                interruptionStateProvider,
                visualInterruptionDecisionProvider,
                zenModeController,
                zenModeController,
                notifUserManager,
                notifUserManager,
                notifCollection,
                notifCollection,
+31 −23
Original line number Original line Diff line number Diff line
@@ -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.collection.render.NodeController
import com.android.systemui.statusbar.notification.dagger.IncomingHeader
import com.android.systemui.statusbar.notification.dagger.IncomingHeader
import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder
import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider
import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionProvider
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider.FullScreenIntentDecision
import com.android.systemui.statusbar.notification.logKey
import com.android.systemui.statusbar.notification.logKey
import com.android.systemui.statusbar.notification.stack.BUCKET_HEADS_UP
import com.android.systemui.statusbar.notification.stack.BUCKET_HEADS_UP
import com.android.systemui.statusbar.policy.HeadsUpManager
import com.android.systemui.statusbar.policy.HeadsUpManager
@@ -69,12 +68,12 @@ class HeadsUpCoordinator @Inject constructor(
    private val mSystemClock: SystemClock,
    private val mSystemClock: SystemClock,
    private val mHeadsUpManager: HeadsUpManager,
    private val mHeadsUpManager: HeadsUpManager,
    private val mHeadsUpViewBinder: HeadsUpViewBinder,
    private val mHeadsUpViewBinder: HeadsUpViewBinder,
    private val mNotificationInterruptStateProvider: NotificationInterruptStateProvider,
    private val mVisualInterruptionDecisionProvider: VisualInterruptionDecisionProvider,
    private val mRemoteInputManager: NotificationRemoteInputManager,
    private val mRemoteInputManager: NotificationRemoteInputManager,
    private val mLaunchFullScreenIntentProvider: LaunchFullScreenIntentProvider,
    private val mLaunchFullScreenIntentProvider: LaunchFullScreenIntentProvider,
    private val mFlags: NotifPipelineFlags,
    private val mFlags: NotifPipelineFlags,
    @IncomingHeader private val mIncomingHeaderController: NodeController,
    @IncomingHeader private val mIncomingHeaderController: NodeController,
    @Main private val mExecutor: DelayableExecutor,
    @Main private val mExecutor: DelayableExecutor
) : Coordinator {
) : Coordinator {
    private val mEntriesBindingUntil = ArrayMap<String, Long>()
    private val mEntriesBindingUntil = ArrayMap<String, Long>()
    private val mEntriesUpdateTimes = ArrayMap<String, Long>()
    private val mEntriesUpdateTimes = ArrayMap<String, Long>()
@@ -388,18 +387,21 @@ class HeadsUpCoordinator @Inject constructor(
        override fun onEntryAdded(entry: NotificationEntry) {
        override fun onEntryAdded(entry: NotificationEntry) {
            // First check whether this notification should launch a full screen intent, and
            // First check whether this notification should launch a full screen intent, and
            // launch it if needed.
            // launch it if needed.
            val fsiDecision = mNotificationInterruptStateProvider.getFullScreenIntentDecision(entry)
            val fsiDecision =
            mNotificationInterruptStateProvider.logFullScreenIntentDecision(entry, fsiDecision)
                mVisualInterruptionDecisionProvider.makeUnloggedFullScreenIntentDecision(entry)
            if (fsiDecision.shouldLaunch) {
            mVisualInterruptionDecisionProvider.logFullScreenIntentDecision(fsiDecision)
            if (fsiDecision.shouldInterrupt) {
                mLaunchFullScreenIntentProvider.launchFullScreenIntent(entry)
                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
                // If DND was the only reason this entry was suppressed, note it for potential
                // reconsideration on later ranking updates.
                // reconsideration on later ranking updates.
                addForFSIReconsideration(entry, mSystemClock.currentTimeMillis())
                addForFSIReconsideration(entry, mSystemClock.currentTimeMillis())
            }
            }


            // shouldHeadsUp includes check for whether this notification should be filtered
            // makeAndLogHeadsUpDecision includes check for whether this notification should be
            val shouldHeadsUpEver = mNotificationInterruptStateProvider.shouldHeadsUp(entry)
            // filtered
            val shouldHeadsUpEver =
                mVisualInterruptionDecisionProvider.makeAndLogHeadsUpDecision(entry).shouldInterrupt
            mPostedEntries[entry.key] = PostedEntry(
            mPostedEntries[entry.key] = PostedEntry(
                entry,
                entry,
                wasAdded = true,
                wasAdded = true,
@@ -420,7 +422,8 @@ class HeadsUpCoordinator @Inject constructor(
         * up again.
         * up again.
         */
         */
        override fun onEntryUpdated(entry: NotificationEntry) {
        override fun onEntryUpdated(entry: NotificationEntry) {
            val shouldHeadsUpEver = mNotificationInterruptStateProvider.shouldHeadsUp(entry)
            val shouldHeadsUpEver =
                mVisualInterruptionDecisionProvider.makeAndLogHeadsUpDecision(entry).shouldInterrupt
            val shouldHeadsUpAgain = shouldHunAgain(entry)
            val shouldHeadsUpAgain = shouldHunAgain(entry)
            val isAlerting = mHeadsUpManager.isAlerting(entry.key)
            val isAlerting = mHeadsUpManager.isAlerting(entry.key)
            val isBinding = isEntryBinding(entry)
            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 any of these entries are no longer suppressed, launch the FSI now.
                if (isCandidateForFSIReconsideration(entry)) {
                if (isCandidateForFSIReconsideration(entry)) {
                    val decision =
                    val decision =
                        mNotificationInterruptStateProvider.getFullScreenIntentDecision(entry)
                        mVisualInterruptionDecisionProvider.makeUnloggedFullScreenIntentDecision(
                    if (decision.shouldLaunch) {
                            entry
                        )
                    if (decision.shouldInterrupt) {
                        // Log both the launch of the full screen and also that this was via a
                        // Log both the launch of the full screen and also that this was via a
                        // ranking update, and finally revoke candidacy for FSI reconsideration
                        // ranking update, and finally revoke candidacy for FSI reconsideration
                        mLogger.logEntryUpdatedToFullScreen(entry.key, decision.name)
                        mLogger.logEntryUpdatedToFullScreen(entry.key, decision.logReason)
                        mNotificationInterruptStateProvider.logFullScreenIntentDecision(
                        mVisualInterruptionDecisionProvider.logFullScreenIntentDecision(decision)
                            entry, decision)
                        mLaunchFullScreenIntentProvider.launchFullScreenIntent(entry)
                        mLaunchFullScreenIntentProvider.launchFullScreenIntent(entry)
                        mFSIUpdateCandidates.remove(entry.key)
                        mFSIUpdateCandidates.remove(entry.key)


                        // if we launch the FSI then this is no longer a candidate for HUN
                        // if we launch the FSI then this is no longer a candidate for HUN
                        continue
                        continue
                    } else if (decision == FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND) {
                    } else if (decision.wouldInterruptWithoutDnd) {
                        // decision has not changed; no need to log
                        // decision has not changed; no need to log
                    } else {
                    } else {
                        // some other condition is now blocking FSI; log that and revoke candidacy
                        // some other condition is now blocking FSI; log that and revoke candidacy
                        // for FSI reconsideration
                        // for FSI reconsideration
                        mLogger.logEntryDisqualifiedFromFullScreen(entry.key, decision.name)
                        mLogger.logEntryDisqualifiedFromFullScreen(entry.key, decision.logReason)
                        mNotificationInterruptStateProvider.logFullScreenIntentDecision(
                        mVisualInterruptionDecisionProvider.logFullScreenIntentDecision(decision)
                            entry, decision)
                        mFSIUpdateCandidates.remove(entry.key)
                        mFSIUpdateCandidates.remove(entry.key)
                    }
                    }
                }
                }
@@ -539,13 +542,18 @@ class HeadsUpCoordinator @Inject constructor(
                //   state
                //   state
                // - if it is present in PostedEntries and the previous state of shouldHeadsUp
                // - if it is present in PostedEntries and the previous state of shouldHeadsUp
                //   differs from the updated one
                //   differs from the updated one
                val shouldHeadsUpEver = mNotificationInterruptStateProvider.checkHeadsUp(entry,
                val decision =
                                /* log= */ false)
                    mVisualInterruptionDecisionProvider.makeUnloggedHeadsUpDecision(entry)
                val shouldHeadsUpEver = decision.shouldInterrupt
                val postedShouldHeadsUpEver = mPostedEntries[entry.key]?.shouldHeadsUpEver ?: false
                val postedShouldHeadsUpEver = mPostedEntries[entry.key]?.shouldHeadsUpEver ?: false
                val shouldUpdateEntry = postedShouldHeadsUpEver != shouldHeadsUpEver
                val shouldUpdateEntry = postedShouldHeadsUpEver != shouldHeadsUpEver


                if (shouldUpdateEntry) {
                if (shouldUpdateEntry) {
                    mLogger.logEntryUpdatedByRanking(entry.key, shouldHeadsUpEver)
                    mLogger.logEntryUpdatedByRanking(
                        entry.key,
                        shouldHeadsUpEver,
                        decision.logReason
                    )
                    onEntryUpdated(entry)
                    onEntryUpdated(entry)
                }
                }
            }
            }
+3 −2
Original line number Original line Diff line number Diff line
@@ -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, {
        buffer.log(TAG, LogLevel.DEBUG, {
            str1 = key
            str1 = key
            bool1 = shouldHun
            bool1 = shouldHun
            str2 = reason
        }, {
        }, {
            "updating entry via ranking applied: $str1 updated shouldHeadsUp=$bool1"
            "updating entry via ranking applied: $str1 updated shouldHeadsUp=$bool1 because $str2"
        })
        })
    }
    }


+3 −0
Original line number Original line Diff line number Diff line
@@ -36,6 +36,8 @@ class NotificationInterruptStateProviderWrapper(
        SHOULD_INTERRUPT(shouldInterrupt = true),
        SHOULD_INTERRUPT(shouldInterrupt = true),
        SHOULD_NOT_INTERRUPT(shouldInterrupt = false);
        SHOULD_NOT_INTERRUPT(shouldInterrupt = false);


        override val logReason = "unknown"

        companion object {
        companion object {
            fun of(booleanDecision: Boolean) =
            fun of(booleanDecision: Boolean) =
                if (booleanDecision) SHOULD_INTERRUPT else SHOULD_NOT_INTERRUPT
                if (booleanDecision) SHOULD_INTERRUPT else SHOULD_NOT_INTERRUPT
@@ -49,6 +51,7 @@ class NotificationInterruptStateProviderWrapper(
    ) : FullScreenIntentDecision {
    ) : FullScreenIntentDecision {
        override val shouldInterrupt = originalDecision.shouldLaunch
        override val shouldInterrupt = originalDecision.shouldLaunch
        override val wouldInterruptWithoutDnd = originalDecision == NO_FSI_SUPPRESSED_ONLY_BY_DND
        override val wouldInterruptWithoutDnd = originalDecision == NO_FSI_SUPPRESSED_ONLY_BY_DND
        override val logReason = originalDecision.name
    }
    }


    override fun addSuppressor(suppressor: NotificationInterruptSuppressor) {
    override fun addSuppressor(suppressor: NotificationInterruptSuppressor) {
+3 −0
Original line number Original line Diff line number Diff line
@@ -32,9 +32,12 @@ interface VisualInterruptionDecisionProvider {
     * full-screen intent decisions.
     * full-screen intent decisions.
     *
     *
     * @property[shouldInterrupt] whether a visual interruption should be triggered
     * @property[shouldInterrupt] whether a visual interruption should be triggered
     * @property[logReason] a log-friendly string explaining the reason for the decision; should be
     *   used *only* for logging, not decision-making
     */
     */
    interface Decision {
    interface Decision {
        val shouldInterrupt: Boolean
        val shouldInterrupt: Boolean
        val logReason: String
    }
    }


    /**
    /**
Loading