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

Commit aa96cf34 authored by Julia Reynolds's avatar Julia Reynolds
Browse files

Exclude system notifications from visual suppression

But silence them by saying them cannot bypass DND.

Test: atest SystemUITests
Bug: 77656914
Change-Id: I044696cfdcef0e4a14be21173949612480722236
parent bae834c0
Loading
Loading
Loading
Loading
+1 −20
Original line number Diff line number Diff line
@@ -59,7 +59,6 @@ public class SystemNotificationChannels {
                VIRTUAL_KEYBOARD,
                context.getString(R.string.notification_channel_virtual_keyboard),
                NotificationManager.IMPORTANCE_LOW);
        keyboard.setBypassDnd(true);
        keyboard.setBlockableSystem(true);
        channelsList.add(keyboard);

@@ -76,7 +75,6 @@ public class SystemNotificationChannels {
                SECURITY,
                context.getString(R.string.notification_channel_security),
                NotificationManager.IMPORTANCE_LOW);
        security.setBypassDnd(true);
        channelsList.add(security);

        final NotificationChannel car = new NotificationChannel(
@@ -84,7 +82,6 @@ public class SystemNotificationChannels {
                context.getString(R.string.notification_channel_car_mode),
                NotificationManager.IMPORTANCE_LOW);
        car.setBlockableSystem(true);
        car.setBypassDnd(true);
        channelsList.add(car);

        channelsList.add(newAccountChannel(context));
@@ -93,7 +90,6 @@ public class SystemNotificationChannels {
                DEVELOPER,
                context.getString(R.string.notification_channel_developer),
                NotificationManager.IMPORTANCE_LOW);
        developer.setBypassDnd(true);
        developer.setBlockableSystem(true);
        channelsList.add(developer);

@@ -101,21 +97,18 @@ public class SystemNotificationChannels {
                UPDATES,
                context.getString(R.string.notification_channel_updates),
                NotificationManager.IMPORTANCE_LOW);
        updates.setBypassDnd(true);
        channelsList.add(updates);

        final NotificationChannel network = new NotificationChannel(
                NETWORK_STATUS,
                context.getString(R.string.notification_channel_network_status),
                NotificationManager.IMPORTANCE_LOW);
        network.setBypassDnd(true);
        channelsList.add(network);

        final NotificationChannel networkAlertsChannel = new NotificationChannel(
                NETWORK_ALERTS,
                context.getString(R.string.notification_channel_network_alerts),
                NotificationManager.IMPORTANCE_HIGH);
        networkAlertsChannel.setBypassDnd(true);
        networkAlertsChannel.setBlockableSystem(true);
        channelsList.add(networkAlertsChannel);

@@ -124,42 +117,36 @@ public class SystemNotificationChannels {
                context.getString(R.string.notification_channel_network_available),
                NotificationManager.IMPORTANCE_LOW);
        networkAvailable.setBlockableSystem(true);
        networkAvailable.setBypassDnd(true);
        channelsList.add(networkAvailable);

        final NotificationChannel vpn = new NotificationChannel(
                VPN,
                context.getString(R.string.notification_channel_vpn),
                NotificationManager.IMPORTANCE_LOW);
        vpn.setBypassDnd(true);
        channelsList.add(vpn);

        final NotificationChannel deviceAdmin = new NotificationChannel(
                DEVICE_ADMIN,
                context.getString(R.string.notification_channel_device_admin),
                NotificationManager.IMPORTANCE_LOW);
        deviceAdmin.setBypassDnd(true);
        channelsList.add(deviceAdmin);

        final NotificationChannel alertsChannel = new NotificationChannel(
                ALERTS,
                context.getString(R.string.notification_channel_alerts),
                NotificationManager.IMPORTANCE_DEFAULT);
        alertsChannel.setBypassDnd(true);
        channelsList.add(alertsChannel);

        final NotificationChannel retail = new NotificationChannel(
                RETAIL_MODE,
                context.getString(R.string.notification_channel_retail_mode),
                NotificationManager.IMPORTANCE_LOW);
        retail.setBypassDnd(true);
        channelsList.add(retail);

        final NotificationChannel usb = new NotificationChannel(
                USB,
                context.getString(R.string.notification_channel_usb),
                NotificationManager.IMPORTANCE_MIN);
        usb.setBypassDnd(true);
        channelsList.add(usb);

        NotificationChannel foregroundChannel = new NotificationChannel(
@@ -167,7 +154,6 @@ public class SystemNotificationChannels {
                context.getString(R.string.notification_channel_foreground_service),
                NotificationManager.IMPORTANCE_LOW);
        foregroundChannel.setBlockableSystem(true);
        foregroundChannel.setBypassDnd(true);
        channelsList.add(foregroundChannel);

        NotificationChannel heavyWeightChannel = new NotificationChannel(
@@ -179,19 +165,16 @@ public class SystemNotificationChannels {
                .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                .setUsage(AudioAttributes.USAGE_NOTIFICATION_EVENT)
                .build());
        heavyWeightChannel.setBypassDnd(true);
        channelsList.add(heavyWeightChannel);

        NotificationChannel systemChanges = new NotificationChannel(SYSTEM_CHANGES,
                context.getString(R.string.notification_channel_system_changes),
                NotificationManager.IMPORTANCE_LOW);
        systemChanges.setBypassDnd(true);
        channelsList.add(systemChanges);

        NotificationChannel dndChanges = new NotificationChannel(DO_NOT_DISTURB,
                context.getString(R.string.notification_channel_do_not_disturb),
                NotificationManager.IMPORTANCE_LOW);
        dndChanges.setBypassDnd(true);
        channelsList.add(dndChanges);

        nm.createNotificationChannels(channelsList);
@@ -208,12 +191,10 @@ public class SystemNotificationChannels {
    }

    private static NotificationChannel newAccountChannel(Context context) {
        final NotificationChannel acct = new NotificationChannel(
        return new NotificationChannel(
                ACCOUNT,
                context.getString(R.string.notification_channel_account),
                NotificationManager.IMPORTANCE_LOW);
        acct.setBypassDnd(true);
        return acct;
    }

    private SystemNotificationChannels() {}
+8 −11
Original line number Diff line number Diff line
@@ -179,11 +179,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
    private NotificationGuts mGuts;
    private NotificationData.Entry mEntry;
    private StatusBarNotification mStatusBarNotification;
    /**
     * Whether or not this row represents a system notification. Note that if this is {@code null},
     * that means we were either unable to retrieve the info or have yet to retrieve the info.
     */
    private Boolean mIsSystemNotification;
    private String mAppName;
    private boolean mIsHeadsUp;
    private boolean mLastChronometerRunning = true;
@@ -426,7 +421,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
     * once per notification as the packageInfo can't technically change for a notification row.
     */
    private void cacheIsSystemNotification() {
        if (mIsSystemNotification == null) {
        if (mEntry != null && mEntry.mIsSystemNotification == null) {
            if (mSystemNotificationAsyncTask.getStatus() == AsyncTask.Status.PENDING) {
                // Run async task once, only if it hasn't already been executed. Note this is
                // executed in serial - no need to parallelize this small task.
@@ -445,16 +440,16 @@ public class ExpandableNotificationRow extends ActivatableNotificationView

        // If the SystemNotifAsyncTask hasn't finished running or retrieved a value, we'll try once
        // again, but in-place on the main thread this time. This should rarely ever get called.
        if (mIsSystemNotification == null) {
        if (mEntry != null && mEntry.mIsSystemNotification == null) {
            if (DEBUG) {
                Log.d(TAG, "Retrieving isSystemNotification on main thread");
            }
            mSystemNotificationAsyncTask.cancel(true /* mayInterruptIfRunning */);
            mIsSystemNotification = isSystemNotification(mContext, mStatusBarNotification);
            mEntry.mIsSystemNotification = isSystemNotification(mContext, mStatusBarNotification);
        }

        if (!isNonblockable && mIsSystemNotification != null) {
            if (mIsSystemNotification) {
        if (!isNonblockable && mEntry != null && mEntry.mIsSystemNotification != null) {
            if (mEntry.mIsSystemNotification) {
                if (mEntry.channel != null
                        && !mEntry.channel.isBlockableSystem()) {
                    isNonblockable = true;
@@ -2875,7 +2870,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView

        @Override
        protected void onPostExecute(Boolean result) {
            mIsSystemNotification = result;
            if (mEntry != null) {
                mEntry.mIsSystemNotification = result;
            }
        }
    }
}
+31 −22
Original line number Diff line number Diff line
@@ -103,6 +103,12 @@ public class NotificationData {
        public ArraySet<Integer> mActiveAppOps = new ArraySet<>(3);
        public CharSequence headsUpStatusBarText;
        public CharSequence headsUpStatusBarTextPublic;
        /**
         * Whether or not this row represents a system notification. Note that if this is
         * {@code null}, that means we were either unable to retrieve the info or have yet to
         * retrieve the info.
         */
        public Boolean mIsSystemNotification;

        public Entry(StatusBarNotification n) {
            this.key = n.getKey();
@@ -435,31 +441,31 @@ public class NotificationData {
        return Ranking.VISIBILITY_NO_OVERRIDE;
    }

    public boolean shouldSuppressFullScreenIntent(StatusBarNotification sbn) {
        return shouldSuppressVisualEffect(sbn, SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
    public boolean shouldSuppressFullScreenIntent(Entry entry) {
        return shouldSuppressVisualEffect(entry, SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
    }

    public boolean shouldSuppressPeek(StatusBarNotification sbn) {
        return shouldSuppressVisualEffect(sbn, SUPPRESSED_EFFECT_PEEK);
    public boolean shouldSuppressPeek(Entry entry) {
        return shouldSuppressVisualEffect(entry, SUPPRESSED_EFFECT_PEEK);
    }

    public boolean shouldSuppressStatusBar(StatusBarNotification sbn) {
        return shouldSuppressVisualEffect(sbn, SUPPRESSED_EFFECT_STATUS_BAR);
    public boolean shouldSuppressStatusBar(Entry entry) {
        return shouldSuppressVisualEffect(entry, SUPPRESSED_EFFECT_STATUS_BAR);
    }

    public boolean shouldSuppressAmbient(StatusBarNotification sbn) {
        return shouldSuppressVisualEffect(sbn, SUPPRESSED_EFFECT_AMBIENT);
    public boolean shouldSuppressAmbient(Entry entry) {
        return shouldSuppressVisualEffect(entry, SUPPRESSED_EFFECT_AMBIENT);
    }

    public boolean shouldSuppressNotificationList(StatusBarNotification sbn) {
        return shouldSuppressVisualEffect(sbn, SUPPRESSED_EFFECT_NOTIFICATION_LIST);
    public boolean shouldSuppressNotificationList(Entry entry) {
        return shouldSuppressVisualEffect(entry, SUPPRESSED_EFFECT_NOTIFICATION_LIST);
    }

    private boolean shouldSuppressVisualEffect(StatusBarNotification sbn, int effect) {
        if (isExemptFromDndVisualSuppression(sbn)) {
    private boolean shouldSuppressVisualEffect(Entry entry, int effect) {
        if (isExemptFromDndVisualSuppression(entry)) {
            return false;
        }
        String key = sbn.getKey();
        String key = entry.key;
        if (mRankingMap != null) {
            getRanking(key, mTmpRanking);
            return (mTmpRanking.getSuppressedVisualEffects() & effect) != 0;
@@ -467,11 +473,15 @@ public class NotificationData {
        return false;
    }

    protected boolean isExemptFromDndVisualSuppression(StatusBarNotification sbn) {
        if ((sbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
    protected boolean isExemptFromDndVisualSuppression(Entry entry) {
        if ((entry.notification.getNotification().flags
                & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
            return true;
        }
        if (entry.notification.getNotification().isMediaNotification()) {
            return true;
        }
        if (sbn.getNotification().isMediaNotification()) {
        if (entry.mIsSystemNotification != null && entry.mIsSystemNotification) {
            return true;
        }
        return false;
@@ -564,9 +574,8 @@ public class NotificationData {
            final int N = mEntries.size();
            for (int i = 0; i < N; i++) {
                Entry entry = mEntries.valueAt(i);
                StatusBarNotification sbn = entry.notification;

                if (shouldFilterOut(sbn)) {
                if (shouldFilterOut(entry)) {
                    continue;
                }

@@ -578,10 +587,10 @@ public class NotificationData {
    }

    /**
     * @param sbn
     * @return true if this notification should NOT be shown right now
     */
    public boolean shouldFilterOut(StatusBarNotification sbn) {
    public boolean shouldFilterOut(Entry entry) {
        final StatusBarNotification sbn = entry.notification;
        if (!(mEnvironment.isDeviceProvisioned() ||
                showNotificationEvenIfUnprovisioned(sbn))) {
            return true;
@@ -598,11 +607,11 @@ public class NotificationData {
            return true;
        }

        if (mEnvironment.isDozing() && shouldSuppressAmbient(sbn)) {
        if (mEnvironment.isDozing() && shouldSuppressAmbient(entry)) {
            return true;
        }

        if (!mEnvironment.isDozing() && shouldSuppressNotificationList(sbn)) {
        if (!mEnvironment.isDozing() && shouldSuppressNotificationList(entry)) {
            return true;
        }

+6 −6
Original line number Diff line number Diff line
@@ -300,12 +300,12 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
        updateNotifications();
    }

    private boolean shouldSuppressFullScreenIntent(StatusBarNotification sbn) {
    private boolean shouldSuppressFullScreenIntent(NotificationData.Entry entry) {
        if (mPresenter.isDeviceInVrMode()) {
            return true;
        }

        return mNotificationData.shouldSuppressFullScreenIntent(sbn);
        return mNotificationData.shouldSuppressFullScreenIntent(entry);
    }

    private void inflateViews(NotificationData.Entry entry, ViewGroup parent) {
@@ -692,7 +692,7 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
        NotificationData.Entry shadeEntry = createNotificationViews(notification);
        boolean isHeadsUped = shouldPeek(shadeEntry);
        if (!isHeadsUped && notification.getNotification().fullScreenIntent != null) {
            if (shouldSuppressFullScreenIntent(notification)) {
            if (shouldSuppressFullScreenIntent(shadeEntry)) {
                if (DEBUG) {
                    Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + key);
                }
@@ -848,7 +848,7 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
            return false;
        }

        if (mNotificationData.shouldFilterOut(sbn)) {
        if (mNotificationData.shouldFilterOut(entry)) {
            if (DEBUG) Log.d(TAG, "No peeking: filtered notification: " + sbn.getKey());
            return false;
        }
@@ -862,13 +862,13 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
            return false;
        }

        if (!mPresenter.isDozing() && mNotificationData.shouldSuppressPeek(sbn)) {
        if (!mPresenter.isDozing() && mNotificationData.shouldSuppressPeek(entry)) {
            if (DEBUG) Log.d(TAG, "No peeking: suppressed by DND: " + sbn.getKey());
            return false;
        }

        // Peeking triggers an ambient display pulse, so disable peek is ambient is active
        if (mPresenter.isDozing() && mNotificationData.shouldSuppressAmbient(sbn)) {
        if (mPresenter.isDozing() && mNotificationData.shouldSuppressAmbient(entry)) {
            if (DEBUG) Log.d(TAG, "No peeking: suppressed by DND: " + sbn.getKey());
            return false;
        }
+1 −2
Original line number Diff line number Diff line
@@ -156,8 +156,7 @@ public class NotificationIconAreaController implements DarkReceiver {
        }

        // showAmbient == show in shade but not shelf
        if (!showAmbient && mEntryManager.getNotificationData().shouldSuppressStatusBar(
                entry.notification)) {
        if (!showAmbient && mEntryManager.getNotificationData().shouldSuppressStatusBar(entry)) {
            return false;
        }

Loading