diff options
3 files changed, 60 insertions, 0 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java index bc881ce36341..455c7612617f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java @@ -59,6 +59,12 @@ public interface NotificationInterruptStateProvider { */ NO_FSI_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR(false), /** + * Notification should not FSI due to having suppressive BubbleMetadata. This blocks a + * potentially malicious use of flags that previously allowed apps to escalate a HUN to an + * FSI even while the device was unlocked. + */ + NO_FSI_SUPPRESSIVE_BUBBLE_METADATA(false), + /** * Device screen is off, so the FSI should launch. */ FSI_DEVICE_NOT_INTERACTIVE(true), diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java index c40939f26148..f7dce8224db2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.notification.interruption; import static com.android.systemui.statusbar.StatusBarState.SHADE; import static com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.NotificationInterruptEvent.FSI_SUPPRESSED_NO_HUN_OR_KEYGUARD; +import static com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.NotificationInterruptEvent.FSI_SUPPRESSED_SUPPRESSIVE_BUBBLE_METADATA; import static com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.NotificationInterruptEvent.FSI_SUPPRESSED_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR; import static com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.NotificationInterruptEvent.HUN_SNOOZE_BYPASSED_POTENTIALLY_SUPPRESSED_FSI; @@ -80,6 +81,9 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter @UiEvent(doc = "FSI suppressed for suppressive GroupAlertBehavior") FSI_SUPPRESSED_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR(1235), + @UiEvent(doc = "FSI suppressed for suppressive BubbleMetadata") + FSI_SUPPRESSED_SUPPRESSIVE_BUBBLE_METADATA(1353), + @UiEvent(doc = "FSI suppressed for requiring neither HUN nor keyguard") FSI_SUPPRESSED_NO_HUN_OR_KEYGUARD(1236), @@ -270,6 +274,16 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter suppressedByDND); } + // If the notification has suppressive BubbleMetadata, block FSI and warn. + Notification.BubbleMetadata bubbleMetadata = sbn.getNotification().getBubbleMetadata(); + if (bubbleMetadata != null && bubbleMetadata.isNotificationSuppressed()) { + // b/274759612: Detect and report an event when a notification has both an FSI and a + // suppressive BubbleMetadata, and now correctly block the FSI from firing. + return getDecisionGivenSuppression( + FullScreenIntentDecision.NO_FSI_SUPPRESSIVE_BUBBLE_METADATA, + suppressedByDND); + } + // If the screen is off, then launch the FullScreenIntent if (!mPowerManager.isInteractive()) { return getDecisionGivenSuppression(FullScreenIntentDecision.FSI_DEVICE_NOT_INTERACTIVE, @@ -350,6 +364,11 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter packageName); mLogger.logNoFullscreenWarning(entry, "GroupAlertBehavior will prevent HUN"); return; + case NO_FSI_SUPPRESSIVE_BUBBLE_METADATA: + android.util.EventLog.writeEvent(0x534e4554, "274759612", uid, "bubbleMetadata"); + mUiEventLogger.log(FSI_SUPPRESSED_SUPPRESSIVE_BUBBLE_METADATA, uid, packageName); + mLogger.logNoFullscreenWarning(entry, "BubbleMetadata may prevent HUN"); + return; case FSI_DEVICE_NOT_INTERACTIVE: mLogger.logFullscreen(entry, "Device is not interactive"); return; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java index dcbe9843e3db..2644a04cf096 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java @@ -630,6 +630,38 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase { } @Test + public void testShouldNotFullScreen_isSuppressedByBubbleMetadata_withStrictFlag() { + when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(true); + testShouldNotFullScreen_isSuppressedByBubbleMetadata(); + } + + @Test + public void testShouldNotFullScreen_isSuppressedByBubbleMetadata() { + NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false); + Notification.BubbleMetadata bubbleMetadata = new Notification.BubbleMetadata.Builder("foo") + .setSuppressNotification(true).build(); + entry.getSbn().getNotification().setBubbleMetadata(bubbleMetadata); + when(mPowerManager.isInteractive()).thenReturn(false); + when(mStatusBarStateController.isDreaming()).thenReturn(true); + when(mStatusBarStateController.getState()).thenReturn(KEYGUARD); + + assertThat(mNotifInterruptionStateProvider.getFullScreenIntentDecision(entry)) + .isEqualTo(FullScreenIntentDecision.NO_FSI_SUPPRESSIVE_BUBBLE_METADATA); + assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry)) + .isFalse(); + verify(mLogger, never()).logNoFullscreen(any(), any()); + verify(mLogger).logNoFullscreenWarning(entry, "BubbleMetadata may prevent HUN"); + verify(mLogger, never()).logFullscreen(any(), any()); + + assertThat(mUiEventLoggerFake.numLogs()).isEqualTo(1); + UiEventLoggerFake.FakeUiEvent fakeUiEvent = mUiEventLoggerFake.get(0); + assertThat(fakeUiEvent.eventId).isEqualTo( + NotificationInterruptEvent.FSI_SUPPRESSED_SUPPRESSIVE_BUBBLE_METADATA.getId()); + assertThat(fakeUiEvent.uid).isEqualTo(entry.getSbn().getUid()); + assertThat(fakeUiEvent.packageName).isEqualTo(entry.getSbn().getPackageName()); + } + + @Test public void testShouldFullScreen_notInteractive_withStrictFlag() throws Exception { when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(true); testShouldFullScreen_notInteractive(); @@ -638,6 +670,9 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase { @Test public void testShouldFullScreen_notInteractive() throws RemoteException { NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false); + Notification.BubbleMetadata bubbleMetadata = new Notification.BubbleMetadata.Builder("foo") + .setSuppressNotification(false).build(); + entry.getSbn().getNotification().setBubbleMetadata(bubbleMetadata); when(mPowerManager.isInteractive()).thenReturn(false); when(mStatusBarStateController.isDreaming()).thenReturn(false); when(mStatusBarStateController.getState()).thenReturn(SHADE); |