Merge changes Ib678f277,Ieaae2f9c into main

* changes:
  Fix notification visibility when screensharing
  Refactor NotificationEntry utility methods
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index 2a4753d..9916ef6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -749,7 +749,7 @@
                 || isNotifUserRedacted;
 
         boolean notificationRequestsRedaction =
-                ent.getSbn().getNotification().visibility == Notification.VISIBILITY_PRIVATE;
+                ent.isNotificationVisibilityPrivate();
         boolean userForcesRedaction = packageHasVisibilityOverride(ent.getSbn().getKey());
 
         if (keyguardPrivateNotifications()) {
@@ -767,9 +767,7 @@
         }
         NotificationEntry entry = mCommonNotifCollectionLazy.get().getEntry(key);
         if (mFeatureFlags.isEnabled(Flags.NOTIF_LS_BACKGROUND_THREAD)) {
-            return entry != null && entry.getRanking().getChannel() != null
-                    && entry.getRanking().getChannel().getLockscreenVisibility()
-                    == Notification.VISIBILITY_PRIVATE;
+            return entry != null && entry.isChannelVisibilityPrivate();
         } else {
             return entry != null
                     && entry.getRanking().getLockscreenVisibilityOverride()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 8678f0a..e111525 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -998,6 +998,23 @@
         return style == null ? "nostyle" : style.getSimpleName();
     }
 
+    /**
+     * Return {@code true} if notification's visibility is {@link Notification.VISIBILITY_PRIVATE}
+     */
+    public boolean isNotificationVisibilityPrivate() {
+        return getSbn().getNotification().visibility == Notification.VISIBILITY_PRIVATE;
+    }
+
+    /**
+     * Return {@code true} if notification's channel lockscreen visibility is
+     * {@link Notification.VISIBILITY_PRIVATE}
+     */
+    public boolean isChannelVisibilityPrivate() {
+        return getRanking().getChannel() != null
+                && getRanking().getChannel().getLockscreenVisibility()
+                == Notification.VISIBILITY_PRIVATE;
+    }
+
     /** Information about a suggestion that is being edited. */
     public static class EditedSuggestionInfo {
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java
index 2b0a92c..6956a7d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java
@@ -221,10 +221,15 @@
         // Exempt foreground service notifications from protection in effort to keep screen share
         // stop actions easily accessible
         StatusBarNotification sbn = entry.getSbn();
-        if (sbn.getNotification().isFgsOrUij()) {
-            return !sbn.getPackageName().equals(projection.getPackageName());
+        if (sbn.getNotification().isFgsOrUij()
+                && sbn.getPackageName().equals(projection.getPackageName())) {
+            return false;
         }
 
-        return true;
+        // Only protect/redact notifications if the developer has not explicitly set notification
+        // visibility as public and users has not adjusted default channel visibility to private
+        boolean notificationRequestsRedaction = entry.isNotificationVisibilityPrivate();
+        boolean userForcesRedaction = entry.isChannelVisibilityPrivate();
+        return notificationRequestsRedaction || userForcesRedaction;
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
index ccc9dc0..8a48fe1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
@@ -50,8 +50,8 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.RankingBuilder;
 import com.android.systemui.statusbar.SbnBuilder;
 import com.android.systemui.util.time.FakeSystemClock;
@@ -280,6 +280,66 @@
     }
 
     @Test
+    public void testIsNotificationVisibilityPrivate_true() {
+        assertTrue(mEntry.isNotificationVisibilityPrivate());
+    }
+
+    @Test
+    public void testIsNotificationVisibilityPrivate_visibilityPublic_false() {
+        Notification.Builder notification = new Notification.Builder(mContext, "")
+                .setVisibility(Notification.VISIBILITY_PUBLIC)
+                .setSmallIcon(R.drawable.ic_person)
+                .setContentTitle("Title")
+                .setContentText("Text");
+
+        NotificationEntry entry = new NotificationEntryBuilder()
+                .setPkg(TEST_PACKAGE_NAME)
+                .setOpPkg(TEST_PACKAGE_NAME)
+                .setUid(TEST_UID)
+                .setChannel(mChannel)
+                .setId(mId++)
+                .setNotification(notification.build())
+                .setUser(new UserHandle(ActivityManager.getCurrentUser()))
+                .build();
+
+        assertFalse(entry.isNotificationVisibilityPrivate());
+    }
+
+    @Test
+    public void testIsChannelVisibilityPrivate_true() {
+        assertTrue(mEntry.isChannelVisibilityPrivate());
+    }
+
+    @Test
+    public void testIsChannelVisibilityPrivate_visibilityPublic_false() {
+        NotificationChannel channel =
+                new NotificationChannel("id", "name", NotificationChannel.USER_LOCKED_IMPORTANCE);
+        channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
+        StatusBarNotification sbn = new SbnBuilder().build();
+        Ranking ranking = new RankingBuilder()
+                .setChannel(channel)
+                .setKey(sbn.getKey())
+                .build();
+        NotificationEntry entry =
+                new NotificationEntry(sbn, ranking, mClock.uptimeMillis());
+
+        assertFalse(entry.isChannelVisibilityPrivate());
+    }
+
+    @Test
+    public void testIsChannelVisibilityPrivate_entryHasNoChannel_false() {
+        StatusBarNotification sbn = new SbnBuilder().build();
+        Ranking ranking = new RankingBuilder()
+                .setChannel(null)
+                .setKey(sbn.getKey())
+                .build();
+        NotificationEntry entry =
+                new NotificationEntry(sbn, ranking, mClock.uptimeMillis());
+
+        assertFalse(entry.isChannelVisibilityPrivate());
+    }
+
+    @Test
     public void notificationDataEntry_testIsLastMessageFromReply() {
         Person.Builder person = new Person.Builder()
                 .setName("name")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt
index 1dac642..a2af38f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt
@@ -19,17 +19,24 @@
 import android.app.ActivityOptions
 import android.app.IActivityManager
 import android.app.Notification
+import android.app.Notification.FLAG_FOREGROUND_SERVICE
+import android.app.Notification.VISIBILITY_PRIVATE
+import android.app.Notification.VISIBILITY_PUBLIC
+import android.app.NotificationChannel
+import android.app.NotificationManager.IMPORTANCE_HIGH
+import android.app.NotificationManager.VISIBILITY_NO_OVERRIDE
 import android.media.projection.MediaProjectionInfo
 import android.media.projection.MediaProjectionManager
 import android.platform.test.annotations.EnableFlags
 import android.provider.Settings.Global.DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS
-import android.service.notification.StatusBarNotification
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper.RunWithLooper
 import androidx.test.filters.SmallTest
 import com.android.server.notification.Flags
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.RankingBuilder
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.concurrency.mockExecutorHandler
 import com.android.systemui.util.mockito.whenever
@@ -316,6 +323,25 @@
 
         assertFalse(controller.shouldProtectNotification(notificationEntry))
     }
+    @Test
+    fun shouldProtectNotification_projectionActive_publicNotification_false() {
+        mediaProjectionCallback.onStart(mediaProjectionInfo)
+
+        // App marked notification visibility as public
+        val notificationEntry = setupPublicNotificationEntry(TEST_PROJECTION_PACKAGE_NAME)
+
+        assertFalse(controller.shouldProtectNotification(notificationEntry))
+    }
+
+    @Test
+    fun shouldProtectNotification_projectionActive_publicNotificationUserChannelOverride_true() {
+        mediaProjectionCallback.onStart(mediaProjectionInfo)
+
+        val notificationEntry =
+            setupPublicNotificationEntryWithUserOverriddenChannel(TEST_PROJECTION_PACKAGE_NAME)
+
+        assertTrue(controller.shouldProtectNotification(notificationEntry))
+    }
 
     private fun setDisabledViaDeveloperOption() {
         globalSettings.putInt(DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS, 1)
@@ -336,21 +362,50 @@
 
     private fun setupNotificationEntry(
         packageName: String,
-        isFgs: Boolean = false
+        isFgs: Boolean = false,
+        overrideVisibility: Boolean = false,
+        overrideChannelVisibility: Boolean = false,
     ): NotificationEntry {
-        val notificationEntry = mock(NotificationEntry::class.java)
-        val sbn = mock(StatusBarNotification::class.java)
-        val notification = mock(Notification::class.java)
-        whenever(notificationEntry.sbn).thenReturn(sbn)
-        whenever(sbn.packageName).thenReturn(packageName)
-        whenever(sbn.notification).thenReturn(notification)
-        whenever(notification.isFgsOrUij).thenReturn(isFgs)
-
+        val notification = Notification()
+        if (isFgs) {
+            notification.flags = notification.flags or FLAG_FOREGROUND_SERVICE
+        }
+        if (overrideVisibility) {
+            // Developer has marked notification as public
+            notification.visibility = VISIBILITY_PUBLIC
+        }
+        val notificationEntry =
+            NotificationEntryBuilder().setNotification(notification).setPkg(packageName).build()
+        val channel = NotificationChannel("1", "1", IMPORTANCE_HIGH)
+        if (overrideChannelVisibility) {
+            // User doesn't allow private notifications at the channel level
+            channel.lockscreenVisibility = VISIBILITY_PRIVATE
+        }
+        notificationEntry.setRanking(
+            RankingBuilder(notificationEntry.ranking)
+                .setChannel(channel)
+                .setVisibilityOverride(VISIBILITY_NO_OVERRIDE)
+                .build()
+        )
         return notificationEntry
     }
 
     private fun setupFgsNotificationEntry(packageName: String): NotificationEntry {
-        return setupNotificationEntry(packageName, /* isFgs= */ true)
+        return setupNotificationEntry(packageName, isFgs = true)
+    }
+
+    private fun setupPublicNotificationEntry(packageName: String): NotificationEntry {
+        return setupNotificationEntry(packageName, overrideVisibility = true)
+    }
+
+    private fun setupPublicNotificationEntryWithUserOverriddenChannel(
+        packageName: String
+    ): NotificationEntry {
+        return setupNotificationEntry(
+            packageName,
+            overrideVisibility = true,
+            overrideChannelVisibility = true
+        )
     }
 
     companion object {