Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7d6152a0 authored by Jeff DeCew's avatar Jeff DeCew
Browse files

Add BubbleMetadata detection to block FSI

Bug: 274759612
Test: atest NotificationInterruptStateProviderImplTest
Change-Id: I40e1aa6377b8a60d91cb2f4189df1e9a4a4578a2
parent 29664baf
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -60,6 +60,12 @@ public interface NotificationInterruptStateProvider {
         * FSI even while the device was unlocked.
         */
        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.
         */
+22 −0
Original line number Diff line number Diff line
@@ -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;

@@ -82,6 +83,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),

@@ -273,6 +277,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);
        }

        // Notification is coming from a suspended package, block FSI
        if (entry.getRanking().isSuspended()) {
            return getDecisionGivenSuppression(FullScreenIntentDecision.NO_FSI_SUSPENDED,
@@ -351,6 +365,14 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter
                mLogger.logNoFullscreenWarning(entry,
                        decision + ": 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,
                        decision + ": BubbleMetadata may prevent HUN");
                return;
            case NO_FSI_NO_HUN_OR_KEYGUARD:
                android.util.EventLog.writeEvent(0x534e4554, "231322873", uid,
                        "no hun or keyguard");
+37 −0
Original line number Diff line number Diff line
@@ -637,6 +637,39 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
        assertThat(fakeUiEvent.packageName).isEqualTo(entry.getSbn().getPackageName());
    }

    @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,
                "NO_FSI_SUPPRESSIVE_BUBBLE_METADATA: 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);
@@ -646,6 +679,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);
@@ -879,6 +915,7 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
        NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
        Set<FullScreenIntentDecision> warnings = new HashSet<>(Arrays.asList(
                FullScreenIntentDecision.NO_FSI_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR,
                FullScreenIntentDecision.NO_FSI_SUPPRESSIVE_BUBBLE_METADATA,
                FullScreenIntentDecision.NO_FSI_NO_HUN_OR_KEYGUARD
        ));
        for (FullScreenIntentDecision decision : FullScreenIntentDecision.values()) {