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