1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.systemui.statusbar.notification.interruption
17 
18 import com.android.app.tracing.traceSection
19 import com.android.internal.annotations.VisibleForTesting
20 import com.android.systemui.dagger.SysUISingleton
21 import com.android.systemui.flags.RefactorFlagUtils
22 import com.android.systemui.statusbar.notification.collection.NotificationEntry
23 import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider.FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND
24 import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionProvider.Decision
25 import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionProvider.FullScreenIntentDecision
26 
27 /**
28  * Wraps a [NotificationInterruptStateProvider] to convert it to the new
29  * [VisualInterruptionDecisionProvider] interface.
30  */
31 @SysUISingleton
32 class NotificationInterruptStateProviderWrapper(
33     private val wrapped: NotificationInterruptStateProvider
34 ) : VisualInterruptionDecisionProvider {
35     init {
36         VisualInterruptionRefactor.assertInLegacyMode()
37     }
38 
39     @VisibleForTesting
40     enum class DecisionImpl(override val shouldInterrupt: Boolean) : Decision {
41         SHOULD_INTERRUPT(shouldInterrupt = true),
42         SHOULD_NOT_INTERRUPT(shouldInterrupt = false);
43 
44         override val logReason = "unknown"
45 
46         companion object {
ofnull47             fun of(booleanDecision: Boolean) =
48                 if (booleanDecision) SHOULD_INTERRUPT else SHOULD_NOT_INTERRUPT
49         }
50     }
51 
52     @VisibleForTesting
53     class FullScreenIntentDecisionImpl(
54         val originalEntry: NotificationEntry,
55         val originalDecision: NotificationInterruptStateProvider.FullScreenIntentDecision
56     ) : FullScreenIntentDecision {
57         override val shouldInterrupt = originalDecision.shouldLaunch
58         override val wouldInterruptWithoutDnd = originalDecision == NO_FSI_SUPPRESSED_ONLY_BY_DND
59         override val logReason = originalDecision.name
60     }
61 
addLegacySuppressornull62     override fun addLegacySuppressor(suppressor: NotificationInterruptSuppressor) {
63         wrapped.addSuppressor(suppressor)
64     }
65 
removeLegacySuppressornull66     override fun removeLegacySuppressor(suppressor: NotificationInterruptSuppressor) {
67         wrapped.removeSuppressor(suppressor)
68     }
69 
addConditionnull70     override fun addCondition(condition: VisualInterruptionCondition) = notValidInLegacyMode()
71 
72     override fun removeCondition(condition: VisualInterruptionCondition) = notValidInLegacyMode()
73 
74     override fun addFilter(filter: VisualInterruptionFilter) = notValidInLegacyMode()
75 
76     override fun removeFilter(filter: VisualInterruptionFilter) = notValidInLegacyMode()
77 
78     private fun notValidInLegacyMode() {
79         RefactorFlagUtils.assertOnEngBuild(
80             "This method is only implemented in VisualInterruptionDecisionProviderImpl, " +
81                 "and so should only be called when FLAG_VISUAL_INTERRUPTIONS_REFACTOR is enabled."
82         )
83     }
84 
makeUnloggedHeadsUpDecisionnull85     override fun makeUnloggedHeadsUpDecision(entry: NotificationEntry): Decision =
86         traceSection("NotificationInterruptStateProviderWrapper#makeUnloggedHeadsUpDecision") {
87             wrapped.checkHeadsUp(entry, /* log= */ false).let { DecisionImpl.of(it) }
88         }
89 
makeAndLogHeadsUpDecisionnull90     override fun makeAndLogHeadsUpDecision(entry: NotificationEntry): Decision =
91         traceSection("NotificationInterruptStateProviderWrapper#makeAndLogHeadsUpDecision") {
92             wrapped.checkHeadsUp(entry, /* log= */ true).let { DecisionImpl.of(it) }
93         }
94 
makeUnloggedFullScreenIntentDecisionnull95     override fun makeUnloggedFullScreenIntentDecision(entry: NotificationEntry) =
96         traceSection(
97             "NotificationInterruptStateProviderWrapper#makeUnloggedFullScreenIntentDecision"
98         ) {
99             wrapped.getFullScreenIntentDecision(entry).let {
100                 FullScreenIntentDecisionImpl(entry, it)
101             }
102         }
103 
logFullScreenIntentDecisionnull104     override fun logFullScreenIntentDecision(decision: FullScreenIntentDecision) =
105         traceSection("NotificationInterruptStateProviderWrapper#logFullScreenIntentDecision") {
106             (decision as FullScreenIntentDecisionImpl).let {
107                 wrapped.logFullScreenIntentDecision(it.originalEntry, it.originalDecision)
108             }
109         }
110 
makeAndLogBubbleDecisionnull111     override fun makeAndLogBubbleDecision(entry: NotificationEntry): Decision =
112         traceSection("NotificationInterruptStateProviderWrapper#makeAndLogBubbleDecision") {
113             wrapped.shouldBubbleUp(entry).let { DecisionImpl.of(it) }
114         }
115 }
116