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

Commit a7064b97 authored by Valentin Iftime's avatar Valentin Iftime
Browse files

Notification API hardening: add FLAG_SILENT

 Replace Notification.GROUP_KEY_SILENT with FLAG_SILENT.
 Prevents silent notifications to be forced grouped by GroupHelper.

Flag: android.service.notification.notification_silent_flag

Test: atest NotificationTest NotificationManagerServiceTest
Test: atest NotificationInterruptStateProviderImplTest
Test: atest VisualInterruptionDecisionProviderImplTest

Bug: 336488844
Change-Id: Icd0ae4d647223e481a1857f98b2732ccb52eddca
parent 02b4a975
Loading
Loading
Loading
Loading
+51 −3
Original line number Diff line number Diff line
@@ -762,6 +762,16 @@ public class Notification implements Parcelable
    @FlaggedApi(Flags.FLAG_LIFETIME_EXTENSION_REFACTOR)
    public static final int FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY = 0x00010000;
    /**
     * Bit to be bitwise-ored into the {@link #flags} field that should be
     * set by the system if this notification is silent.
     *
     * This flag is for internal use only; applications cannot set this flag directly.
     * @hide
     */
    @FlaggedApi(android.service.notification.Flags.FLAG_NOTIFICATION_SILENT_FLAG)
    public static final int FLAG_SILENT = 1 << 17;  //0x00020000
    private static final List<Class<? extends Style>> PLATFORM_STYLE_CLASSES = Arrays.asList(
            BigTextStyle.class, BigPictureStyle.class, InboxStyle.class, MediaStyle.class,
            DecoratedCustomViewStyle.class, DecoratedMediaCustomViewStyle.class,
@@ -784,7 +794,8 @@ public class Notification implements Parcelable
            FLAG_BUBBLE,
            FLAG_NO_DISMISS,
            FLAG_FSI_REQUESTED_BUT_DENIED,
            FLAG_USER_INITIATED_JOB
            FLAG_USER_INITIATED_JOB,
            FLAG_SILENT
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface NotificationFlags{};
@@ -1692,6 +1703,7 @@ public class Notification implements Parcelable
     *
     * @hide
     */
    @Deprecated
    public static final String GROUP_KEY_SILENT = "silent";
    private int mGroupAlertBehavior = GROUP_ALERT_ALL;
@@ -3984,6 +3996,13 @@ public class Notification implements Parcelable
            }
        }
        if (android.service.notification.Flags.notificationSilentFlag()) {
            if ((flags & FLAG_SILENT) != 0) {
                flagStrings.add("SILENT");
                flags &= ~FLAG_SILENT;
            }
        }
        if (flagStrings.isEmpty()) {
            return "0";
        }
@@ -4319,6 +4338,31 @@ public class Notification implements Parcelable
        return contextualActions;
    }
    /**
     * Sets the FLAG_SILENT flag to mark the notification as silent and clears the group key.
     * @hide
     */
    public void fixSilentGroup() {
        if (android.service.notification.Flags.notificationSilentFlag()) {
            if (GROUP_KEY_SILENT.equals(mGroupKey)) {
                mGroupKey = null;
                flags |= FLAG_SILENT;
            }
        }
    }
    /**
     * @return whether this notification is silent. See {@link Builder#setSilent()}
     * @hide
     */
    public boolean isSilent() {
        if (android.service.notification.Flags.notificationSilentFlag()) {
            return (flags & Notification.FLAG_SILENT) != 0;
        } else {
            return GROUP_KEY_SILENT.equals(getGroup()) && suppressAlertingDueToGrouping();
        }
    }
    /**
     * Builder class for {@link Notification} objects.
     *
@@ -4770,9 +4814,13 @@ public class Notification implements Parcelable
            mN.defaults &= ~DEFAULT_VIBRATE;
            setDefaults(mN.defaults);
            if (android.service.notification.Flags.notificationSilentFlag()) {
                mN.flags |= FLAG_SILENT;
            } else {
                if (TextUtils.isEmpty(mN.mGroupKey)) {
                    setGroup(GROUP_KEY_SILENT);
                }
            }
            return this;
        }
+17 −1
Original line number Diff line number Diff line
@@ -84,6 +84,8 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
import android.platform.test.flag.junit.SetFlagsRule;
import android.text.Spannable;
@@ -545,12 +547,26 @@ public class NotificationTest {
    }

    @Test
    @DisableFlags(android.service.notification.Flags.FLAG_NOTIFICATION_SILENT_FLAG)
    public void testBuilder_setSilent_emptyGroupKey_groupKeySilent() {
        Notification emptyGroupKeyNotif = new Notification.Builder(mContext, "channelId")
                .setGroup("")
                .setSilent(true)
                .build();
        assertEquals(GROUP_KEY_SILENT, emptyGroupKeyNotif.getGroup());
        assertThat(emptyGroupKeyNotif.getGroup()).isEqualTo(GROUP_KEY_SILENT);
        assertThat(emptyGroupKeyNotif.isSilent()).isTrue();
    }

    @Test
    @EnableFlags(android.service.notification.Flags.FLAG_NOTIFICATION_SILENT_FLAG)
    public void testBuilder_setSilent_flagSilent() {
        final String groupKey = "groupKey";
        Notification emptyGroupKeyNotif = new Notification.Builder(mContext, "channelId")
            .setGroup(groupKey)
            .setSilent(true)
            .build();
        assertThat(emptyGroupKeyNotif.getGroup()).isEqualTo(groupKey);
        assertThat(emptyGroupKeyNotif.isSilent()).isTrue();
    }

    @Test
+10 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import android.os.SystemProperties
import android.provider.Settings
import android.provider.Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED
import android.provider.Settings.Global.HEADS_UP_OFF
import android.service.notification.Flags
import com.android.internal.logging.UiEvent
import com.android.internal.logging.UiEventLogger
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage
@@ -221,6 +222,15 @@ class HunGroupAlertBehaviorSuppressor() :
        entry.sbn.let { it.isGroup && it.notification.suppressAlertingDueToGrouping() }
}

class HunSilentNotificationSuppressor() :
    VisualInterruptionFilter(
        types = setOf(PEEK, PULSE),
        reason = "notification isSilent"
    ) {
    override fun shouldSuppress(entry: NotificationEntry) =
        entry.sbn.let { Flags.notificationSilentFlag() && it.notification.isSilent }
}

class HunJustLaunchedFsiSuppressor() :
    VisualInterruptionFilter(types = setOf(PEEK, PULSE), reason = "just launched FSI") {
    override fun shouldSuppress(entry: NotificationEntry) = entry.hasJustLaunchedFullScreenIntent()
+8 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import com.android.systemui.statusbar.notification.interruption.FullScreenIntent
import com.android.systemui.statusbar.notification.interruption.FullScreenIntentDecisionProvider.DecisionImpl.NO_FSI_SUPPRESSED_ONLY_BY_DND
import com.android.systemui.statusbar.notification.interruption.FullScreenIntentDecisionProvider.DecisionImpl.NO_FSI_SUPPRESSIVE_BUBBLE_METADATA
import com.android.systemui.statusbar.notification.interruption.FullScreenIntentDecisionProvider.DecisionImpl.NO_FSI_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR
import com.android.systemui.statusbar.notification.interruption.FullScreenIntentDecisionProvider.DecisionImpl.NO_FSI_SUPPRESSIVE_SILENT_NOTIFICATION
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.NotificationInterruptEvent.FSI_SUPPRESSED_NO_HUN_OR_KEYGUARD
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.NotificationInterruptEvent.FSI_SUPPRESSED_SUPPRESSIVE_BUBBLE_METADATA
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.NotificationInterruptEvent.FSI_SUPPRESSED_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR
@@ -94,6 +95,7 @@ class FullScreenIntentDecisionProvider(
            uiEventId = FSI_SUPPRESSED_SUPPRESSIVE_BUBBLE_METADATA,
            eventLogData = EventLogData("274759612", "bubbleMetadata")
        ),
        NO_FSI_SUPPRESSIVE_SILENT_NOTIFICATION(false, "suppressive setSilent notification"),
        NO_FSI_PACKAGE_SUSPENDED(false, "package suspended"),
        FSI_DEVICE_NOT_INTERACTIVE(true, "device is not interactive"),
        FSI_DEVICE_DREAMING(true, "device is dreaming"),
@@ -154,6 +156,12 @@ class FullScreenIntentDecisionProvider(
            return NO_FSI_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR
        }

        if (android.service.notification.Flags.notificationSilentFlag()) {
            if (sbn.notification.isSilent) {
                return NO_FSI_SUPPRESSIVE_SILENT_NOTIFICATION
            }
        }

        val bubbleMetadata = notification.bubbleMetadata
        if (bubbleMetadata != null && bubbleMetadata.isNotificationSuppressed) {
            return NO_FSI_SUPPRESSIVE_BUBBLE_METADATA
+8 −0
Original line number Diff line number Diff line
@@ -193,6 +193,14 @@ class NotificationInterruptLogger @Inject constructor(
        })
    }

    fun logNoAlertingSilentNotification(entry: NotificationEntry) {
        buffer.log(TAG, DEBUG, {
            str1 = entry.logKey
        }, {
            "No alerting: suppressed due to silent notification: $str1"
        })
    }

    fun logNoAlertingSuppressedBy(
        entry: NotificationEntry,
        suppressor: NotificationInterruptSuppressor,
Loading