1 /*
2  * Copyright (C) 2021 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.collection.coordinator
17 
18 import android.platform.test.annotations.DisableFlags
19 import android.platform.test.annotations.EnableFlags
20 import android.testing.TestableLooper.RunWithLooper
21 import androidx.test.ext.junit.runners.AndroidJUnit4
22 import androidx.test.filters.SmallTest
23 import com.android.server.notification.Flags.FLAG_SCREENSHARE_NOTIFICATION_HIDING
24 import com.android.systemui.Flags.FLAG_SCREENSHARE_NOTIFICATION_HIDING_BUG_FIX
25 import com.android.systemui.SysuiTestCase
26 import com.android.systemui.statusbar.notification.collection.NotifPipeline
27 import com.android.systemui.statusbar.notification.collection.NotificationEntry
28 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
29 import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection
30 import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderListListener
31 import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManagerImpl
32 import com.android.systemui.statusbar.notification.collection.render.NotifStackController
33 import com.android.systemui.statusbar.notification.collection.render.NotifStats
34 import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor
35 import com.android.systemui.statusbar.notification.domain.interactor.RenderNotificationListInteractor
36 import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor
37 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
38 import com.android.systemui.statusbar.notification.stack.BUCKET_ALERTING
39 import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT
40 import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionController
41 import org.junit.Before
42 import org.junit.Test
43 import org.junit.runner.RunWith
44 import org.mockito.kotlin.argumentCaptor
45 import org.mockito.kotlin.eq
46 import org.mockito.kotlin.mock
47 import org.mockito.kotlin.verify
48 import org.mockito.kotlin.verifyNoMoreInteractions
49 import org.mockito.kotlin.whenever
50 
51 @SmallTest
52 @RunWith(AndroidJUnit4::class)
53 @RunWithLooper
54 class StackCoordinatorTest : SysuiTestCase() {
55     private lateinit var entry: NotificationEntry
56     private lateinit var coordinator: StackCoordinator
57     private lateinit var afterRenderListListener: OnAfterRenderListListener
58 
59     private val pipeline: NotifPipeline = mock()
60     private val groupExpansionManagerImpl: GroupExpansionManagerImpl = mock()
61     private val renderListInteractor: RenderNotificationListInteractor = mock()
62     private val activeNotificationsInteractor: ActiveNotificationsInteractor = mock()
63     private val sensitiveNotificationProtectionController:
64         SensitiveNotificationProtectionController =
65         mock()
66     private val stackController: NotifStackController = mock()
67     private val section: NotifSection = mock()
68     private val row: ExpandableNotificationRow = mock()
69 
70     @Before
setUpnull71     fun setUp() {
72         whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(false)
73 
74         entry = NotificationEntryBuilder().setSection(section).build()
75         entry.row = row
76         entry.setSensitive(false, false)
77         coordinator =
78             StackCoordinator(
79                 groupExpansionManagerImpl,
80                 renderListInteractor,
81                 activeNotificationsInteractor,
82                 sensitiveNotificationProtectionController,
83             )
84         coordinator.attach(pipeline)
85         val captor = argumentCaptor<OnAfterRenderListListener>()
86         verify(pipeline).addOnAfterRenderListListener(captor.capture())
87         afterRenderListListener = captor.lastValue
88     }
89 
90     @Test
testSetRenderedListOnInteractornull91     fun testSetRenderedListOnInteractor() {
92         afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
93         verify(renderListInteractor).setRenderedList(eq(listOf(entry)))
94     }
95 
96     @Test
97     @EnableFlags(FooterViewRefactor.FLAG_NAME)
testSetRenderedListOnInteractor_footerFlagOnnull98     fun testSetRenderedListOnInteractor_footerFlagOn() {
99         afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
100         verify(renderListInteractor).setRenderedList(eq(listOf(entry)))
101     }
102 
103     @Test
104     @DisableFlags(FooterViewRefactor.FLAG_NAME)
testSetNotificationStats_clearableAlertingnull105     fun testSetNotificationStats_clearableAlerting() {
106         whenever(section.bucket).thenReturn(BUCKET_ALERTING)
107         afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
108         verify(stackController)
109             .setNotifStats(
110                 NotifStats(
111                     1,
112                     hasNonClearableAlertingNotifs = false,
113                     hasClearableAlertingNotifs = true,
114                     hasNonClearableSilentNotifs = false,
115                     hasClearableSilentNotifs = false,
116                 )
117             )
118         verifyNoMoreInteractions(activeNotificationsInteractor)
119     }
120 
121     @Test
122     @DisableFlags(FooterViewRefactor.FLAG_NAME)
123     @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING, FLAG_SCREENSHARE_NOTIFICATION_HIDING_BUG_FIX)
testSetNotificationStats_isSensitiveStateActive_nonClearableAlertingnull124     fun testSetNotificationStats_isSensitiveStateActive_nonClearableAlerting() {
125         whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true)
126         whenever(section.bucket).thenReturn(BUCKET_ALERTING)
127         afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
128         verify(stackController)
129             .setNotifStats(
130                 NotifStats(
131                     1,
132                     hasNonClearableAlertingNotifs = true,
133                     hasClearableAlertingNotifs = false,
134                     hasNonClearableSilentNotifs = false,
135                     hasClearableSilentNotifs = false,
136                 )
137             )
138         verifyNoMoreInteractions(activeNotificationsInteractor)
139     }
140 
141     @Test
142     @DisableFlags(FooterViewRefactor.FLAG_NAME)
testSetNotificationStats_clearableSilentnull143     fun testSetNotificationStats_clearableSilent() {
144         whenever(section.bucket).thenReturn(BUCKET_SILENT)
145         afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
146         verify(stackController)
147             .setNotifStats(
148                 NotifStats(
149                     1,
150                     hasNonClearableAlertingNotifs = false,
151                     hasClearableAlertingNotifs = false,
152                     hasNonClearableSilentNotifs = false,
153                     hasClearableSilentNotifs = true,
154                 )
155             )
156         verifyNoMoreInteractions(activeNotificationsInteractor)
157     }
158 
159     @Test
160     @DisableFlags(FooterViewRefactor.FLAG_NAME)
161     @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING, FLAG_SCREENSHARE_NOTIFICATION_HIDING_BUG_FIX)
testSetNotificationStats_isSensitiveStateActive_nonClearableSilentnull162     fun testSetNotificationStats_isSensitiveStateActive_nonClearableSilent() {
163         whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true)
164         whenever(section.bucket).thenReturn(BUCKET_SILENT)
165         afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
166         verify(stackController)
167             .setNotifStats(
168                 NotifStats(
169                     1,
170                     hasNonClearableAlertingNotifs = false,
171                     hasClearableAlertingNotifs = false,
172                     hasNonClearableSilentNotifs = true,
173                     hasClearableSilentNotifs = false,
174                 )
175             )
176         verifyNoMoreInteractions(activeNotificationsInteractor)
177     }
178 
179     @Test
180     @EnableFlags(FooterViewRefactor.FLAG_NAME)
testSetNotificationStats_footerFlagOn_clearableAlertingnull181     fun testSetNotificationStats_footerFlagOn_clearableAlerting() {
182         whenever(section.bucket).thenReturn(BUCKET_ALERTING)
183         afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
184         verify(activeNotificationsInteractor)
185             .setNotifStats(
186                 NotifStats(
187                     1,
188                     hasNonClearableAlertingNotifs = false,
189                     hasClearableAlertingNotifs = true,
190                     hasNonClearableSilentNotifs = false,
191                     hasClearableSilentNotifs = false,
192                 )
193             )
194         verifyNoMoreInteractions(stackController)
195     }
196 
197     @Test
198     @EnableFlags(
199         FooterViewRefactor.FLAG_NAME,
200         FLAG_SCREENSHARE_NOTIFICATION_HIDING,
201         FLAG_SCREENSHARE_NOTIFICATION_HIDING_BUG_FIX,
202     )
testSetNotificationStats_footerFlagOn_isSensitiveStateActive_nonClearableAlertingnull203     fun testSetNotificationStats_footerFlagOn_isSensitiveStateActive_nonClearableAlerting() {
204         whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true)
205         whenever(section.bucket).thenReturn(BUCKET_ALERTING)
206         afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
207         verify(activeNotificationsInteractor)
208             .setNotifStats(
209                 NotifStats(
210                     1,
211                     hasNonClearableAlertingNotifs = true,
212                     hasClearableAlertingNotifs = false,
213                     hasNonClearableSilentNotifs = false,
214                     hasClearableSilentNotifs = false,
215                 )
216             )
217         verifyNoMoreInteractions(stackController)
218     }
219 
220     @Test
221     @EnableFlags(FooterViewRefactor.FLAG_NAME)
testSetNotificationStats_footerFlagOn_clearableSilentnull222     fun testSetNotificationStats_footerFlagOn_clearableSilent() {
223         whenever(section.bucket).thenReturn(BUCKET_SILENT)
224         afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
225         verify(activeNotificationsInteractor)
226             .setNotifStats(
227                 NotifStats(
228                     1,
229                     hasNonClearableAlertingNotifs = false,
230                     hasClearableAlertingNotifs = false,
231                     hasNonClearableSilentNotifs = false,
232                     hasClearableSilentNotifs = true,
233                 )
234             )
235         verifyNoMoreInteractions(stackController)
236     }
237 
238     @Test
239     @EnableFlags(
240         FooterViewRefactor.FLAG_NAME,
241         FLAG_SCREENSHARE_NOTIFICATION_HIDING,
242         FLAG_SCREENSHARE_NOTIFICATION_HIDING_BUG_FIX,
243     )
testSetNotificationStats_footerFlagOn_isSensitiveStateActive_nonClearableSilentnull244     fun testSetNotificationStats_footerFlagOn_isSensitiveStateActive_nonClearableSilent() {
245         whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true)
246         whenever(section.bucket).thenReturn(BUCKET_SILENT)
247         afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
248         verify(activeNotificationsInteractor)
249             .setNotifStats(
250                 NotifStats(
251                     1,
252                     hasNonClearableAlertingNotifs = false,
253                     hasClearableAlertingNotifs = false,
254                     hasNonClearableSilentNotifs = true,
255                     hasClearableSilentNotifs = false,
256                 )
257             )
258         verifyNoMoreInteractions(stackController)
259     }
260 
261     @Test
262     @EnableFlags(FooterViewRefactor.FLAG_NAME)
testSetNotificationStats_footerFlagOn_nonClearableRedactednull263     fun testSetNotificationStats_footerFlagOn_nonClearableRedacted() {
264         entry.setSensitive(true, true)
265         whenever(section.bucket).thenReturn(BUCKET_ALERTING)
266         afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
267         verify(activeNotificationsInteractor)
268             .setNotifStats(
269                 NotifStats(
270                     1,
271                     hasNonClearableAlertingNotifs = true,
272                     hasClearableAlertingNotifs = false,
273                     hasNonClearableSilentNotifs = false,
274                     hasClearableSilentNotifs = false,
275                 )
276             )
277         verifyNoMoreInteractions(stackController)
278     }
279 }
280