Disable clear notifications when screenshare

When screensharing, notifications that are not dismissable should also
not be clearable

Bug: 324285161
Test: atest StackCoordinatorTest
Flag: ACONFIG com.android.server.notification.screenshare_notification_hiding TRUNKFOOD
Flag: ACONFIG com.android.systemui.screenshare_notification_hiding_bug_fix DISABLED
Change-Id: I44badef472f46b166f94e9a8e1b07f36dbbbfc3c
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index c845ab3..af89f63 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -692,6 +692,16 @@
 }
 
 flag {
+  name: "screenshare_notification_hiding_bug_fix"
+  namespace: "systemui"
+  description: "Various bug fixes for notification redaction while screensharing"
+  bug: "312784809"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
+
+flag {
     name: "qs_ui_refactor"
     namespace: "systemui"
     description: "Enables the new QS UI pipeline that follows recommended architecture and uses"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
index c8ca63d..1511abd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
@@ -17,6 +17,8 @@
 package com.android.systemui.statusbar.notification.collection.coordinator
 
 import com.android.app.tracing.traceSection
+import com.android.server.notification.Flags.screenshareNotificationHiding
+import com.android.systemui.Flags.screenshareNotificationHidingBugFix
 import com.android.systemui.statusbar.notification.collection.ListEntry
 import com.android.systemui.statusbar.notification.collection.NotifPipeline
 import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
@@ -29,6 +31,7 @@
 import com.android.systemui.statusbar.notification.shared.NotificationIconContainerRefactor
 import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT
 import com.android.systemui.statusbar.phone.NotificationIconAreaController
+import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionController
 import javax.inject.Inject
 
 /**
@@ -43,6 +46,8 @@
     private val notificationIconAreaController: NotificationIconAreaController,
     private val renderListInteractor: RenderNotificationListInteractor,
     private val activeNotificationsInteractor: ActiveNotificationsInteractor,
+    private val sensitiveNotificationProtectionController:
+        SensitiveNotificationProtectionController,
 ) : Coordinator {
 
     override fun attach(pipeline: NotifPipeline) {
@@ -71,13 +76,16 @@
         var hasClearableAlertingNotifs = false
         var hasNonClearableSilentNotifs = false
         var hasClearableSilentNotifs = false
+        val isSensitiveContentProtectionActive = screenshareNotificationHiding() &&
+            screenshareNotificationHidingBugFix() &&
+            sensitiveNotificationProtectionController.isSensitiveStateActive
         entries.forEach {
             val section = checkNotNull(it.section) { "Null section for ${it.key}" }
             val entry = checkNotNull(it.representativeEntry) { "Null notif entry for ${it.key}" }
             val isSilent = section.bucket == BUCKET_SILENT
             // NOTE: NotificationEntry.isClearable will internally check group children to ensure
             //  the group itself definitively clearable.
-            val isClearable = entry.isClearable
+            val isClearable = !isSensitiveContentProtectionActive && entry.isClearable
             when {
                 isSilent && isClearable -> hasClearableSilentNotifs = true
                 isSilent && !isClearable -> hasNonClearableSilentNotifs = true
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt
index b4dadaf..ea4f692 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt
@@ -20,6 +20,8 @@
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper.RunWithLooper
 import androidx.test.filters.SmallTest
+import com.android.server.notification.Flags.FLAG_SCREENSHARE_NOTIFICATION_HIDING
+import com.android.systemui.Flags.FLAG_SCREENSHARE_NOTIFICATION_HIDING_BUG_FIX
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.statusbar.notification.collection.NotifPipeline
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
@@ -36,6 +38,7 @@
 import com.android.systemui.statusbar.notification.stack.BUCKET_ALERTING
 import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT
 import com.android.systemui.statusbar.phone.NotificationIconAreaController
+import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionController
 import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.mockito.withArgCaptor
 import org.junit.Before
@@ -43,6 +46,7 @@
 import org.junit.runner.RunWith
 import org.mockito.Mock
 import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyZeroInteractions
 import org.mockito.MockitoAnnotations.initMocks
 import org.mockito.Mockito.`when` as whenever
 
@@ -60,12 +64,18 @@
     @Mock private lateinit var notificationIconAreaController: NotificationIconAreaController
     @Mock private lateinit var renderListInteractor: RenderNotificationListInteractor
     @Mock private lateinit var activeNotificationsInteractor: ActiveNotificationsInteractor
+    @Mock private lateinit var sensitiveNotificationProtectionController:
+        SensitiveNotificationProtectionController
     @Mock private lateinit var stackController: NotifStackController
     @Mock private lateinit var section: NotifSection
 
     @Before
     fun setUp() {
         initMocks(this)
+
+        whenever(sensitiveNotificationProtectionController.isSensitiveStateActive)
+            .thenReturn(false)
+
         entry = NotificationEntryBuilder().setSection(section).build()
         coordinator =
             StackCoordinator(
@@ -73,6 +83,7 @@
                 notificationIconAreaController,
                 renderListInteractor,
                 activeNotificationsInteractor,
+                sensitiveNotificationProtectionController,
             )
         coordinator.attach(pipeline)
         afterRenderListListener = withArgCaptor {
@@ -107,6 +118,18 @@
         whenever(section.bucket).thenReturn(BUCKET_ALERTING)
         afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
         verify(stackController).setNotifStats(NotifStats(1, false, true, false, false))
+        verifyZeroInteractions(activeNotificationsInteractor)
+    }
+
+    @Test
+    @DisableFlags(FooterViewRefactor.FLAG_NAME)
+    @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING, FLAG_SCREENSHARE_NOTIFICATION_HIDING_BUG_FIX)
+    fun testSetNotificationStats_isSensitiveStateActive_nonClearableAlerting() {
+        whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true)
+        whenever(section.bucket).thenReturn(BUCKET_ALERTING)
+        afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
+        verify(stackController).setNotifStats(NotifStats(1, true, false, false, false))
+        verifyZeroInteractions(activeNotificationsInteractor)
     }
 
     @Test
@@ -115,5 +138,67 @@
         whenever(section.bucket).thenReturn(BUCKET_SILENT)
         afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
         verify(stackController).setNotifStats(NotifStats(1, false, false, false, true))
+        verifyZeroInteractions(activeNotificationsInteractor)
+    }
+
+    @Test
+    @DisableFlags(FooterViewRefactor.FLAG_NAME)
+    @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING, FLAG_SCREENSHARE_NOTIFICATION_HIDING_BUG_FIX)
+    fun testSetNotificationStats_isSensitiveStateActive_nonClearableSilent() {
+        whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true)
+        whenever(section.bucket).thenReturn(BUCKET_SILENT)
+        afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
+        verify(stackController).setNotifStats(NotifStats(1, false, false, true, false))
+        verifyZeroInteractions(activeNotificationsInteractor)
+    }
+
+    @Test
+    @EnableFlags(FooterViewRefactor.FLAG_NAME)
+    fun testSetNotificationStats_footerFlagOn_clearableAlerting() {
+        whenever(section.bucket).thenReturn(BUCKET_ALERTING)
+        afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
+        verify(activeNotificationsInteractor)
+            .setNotifStats(NotifStats(1, false, true, false, false))
+        verifyZeroInteractions(stackController)
+    }
+
+    @Test
+    @EnableFlags(
+        FooterViewRefactor.FLAG_NAME,
+        FLAG_SCREENSHARE_NOTIFICATION_HIDING,
+        FLAG_SCREENSHARE_NOTIFICATION_HIDING_BUG_FIX
+    )
+    fun testSetNotificationStats_footerFlagOn_isSensitiveStateActive_nonClearableAlerting() {
+        whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true)
+        whenever(section.bucket).thenReturn(BUCKET_ALERTING)
+        afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
+        verify(activeNotificationsInteractor)
+            .setNotifStats(NotifStats(1, true, false, false, false))
+        verifyZeroInteractions(stackController)
+    }
+
+    @Test
+    @EnableFlags(FooterViewRefactor.FLAG_NAME)
+    fun testSetNotificationStats_footerFlagOn_clearableSilent() {
+        whenever(section.bucket).thenReturn(BUCKET_SILENT)
+        afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
+        verify(activeNotificationsInteractor)
+            .setNotifStats(NotifStats(1, false, false, false, true))
+        verifyZeroInteractions(stackController)
+    }
+
+    @Test
+    @EnableFlags(
+        FooterViewRefactor.FLAG_NAME,
+        FLAG_SCREENSHARE_NOTIFICATION_HIDING,
+        FLAG_SCREENSHARE_NOTIFICATION_HIDING_BUG_FIX
+    )
+    fun testSetNotificationStats_footerFlagOn_isSensitiveStateActive_nonClearableSilent() {
+        whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true)
+        whenever(section.bucket).thenReturn(BUCKET_SILENT)
+        afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
+        verify(activeNotificationsInteractor)
+            .setNotifStats(NotifStats(1, false, false, true, false))
+        verifyZeroInteractions(stackController)
     }
 }