diff --git a/services/core/java/com/android/server/notification/BadgeExtractor.java b/services/core/java/com/android/server/notification/BadgeExtractor.java index d323d80955251..0681d95ad199c 100644 --- a/services/core/java/com/android/server/notification/BadgeExtractor.java +++ b/services/core/java/com/android/server/notification/BadgeExtractor.java @@ -17,9 +17,9 @@ package com.android.server.notification; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE; +import android.app.Notification; import android.content.Context; import android.util.Slog; -import android.app.Notification; /** * Determines whether a badge should be shown for this notification @@ -66,6 +66,17 @@ public class BadgeExtractor implements NotificationSignalExtractor { if (metadata != null && metadata.isNotificationSuppressed()) { record.setShowBadge(false); } + + if (mConfig.isMediaNotificationFilteringEnabled()) { + final Notification notif = record.getNotification(); + if (notif.hasMediaSession()) { + Class notifStyle = notif.getNotificationStyle(); + if (Notification.DecoratedMediaCustomViewStyle.class.equals(notifStyle) + || Notification.MediaStyle.class.equals(notifStyle)) { + record.setShowBadge(false); + } + } + } return null; } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index b64e99168445b..18635e8c07e30 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -1621,7 +1621,8 @@ public class NotificationManagerService extends SystemService { = Settings.Global.getUriFor(Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE); private final Uri NOTIFICATION_HISTORY_ENABLED = Settings.Secure.getUriFor(Settings.Secure.NOTIFICATION_HISTORY_ENABLED); - + private final Uri NOTIFICATION_SHOW_MEDIA_ON_QUICK_SETTINGS_URI + = Settings.Global.getUriFor(Settings.Global.SHOW_MEDIA_ON_QUICK_SETTINGS); SettingsObserver(Handler handler) { super(handler); @@ -1639,6 +1640,8 @@ public class NotificationManagerService extends SystemService { false, this, UserHandle.USER_ALL); resolver.registerContentObserver(NOTIFICATION_HISTORY_ENABLED, false, this, UserHandle.USER_ALL); + resolver.registerContentObserver(NOTIFICATION_SHOW_MEDIA_ON_QUICK_SETTINGS_URI, + false, this, UserHandle.USER_ALL); update(null); } @@ -1675,6 +1678,9 @@ public class NotificationManagerService extends SystemService { Settings.Secure.NOTIFICATION_HISTORY_ENABLED, 0) == 1); } } + if (uri == null || NOTIFICATION_SHOW_MEDIA_ON_QUICK_SETTINGS_URI.equals(uri)) { + mPreferencesHelper.updateMediaNotificationFilteringEnabled(); + } } } diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java index 95c48c2fbb1f8..dd6a83bc3f605 100644 --- a/services/core/java/com/android/server/notification/PreferencesHelper.java +++ b/services/core/java/com/android/server/notification/PreferencesHelper.java @@ -134,6 +134,7 @@ public class PreferencesHelper implements RankingConfig { static final boolean DEFAULT_GLOBAL_ALLOW_BUBBLE = true; @VisibleForTesting static final int DEFAULT_BUBBLE_PREFERENCE = BUBBLE_PREFERENCE_NONE; + static final boolean DEFAULT_MEDIA_NOTIFICATION_FILTERING = true; /** * Default value for what fields are user locked. See {@link LockableAppFields} for all lockable @@ -165,6 +166,7 @@ public class PreferencesHelper implements RankingConfig { private SparseBooleanArray mBadgingEnabled; private boolean mBubblesEnabledGlobally = DEFAULT_GLOBAL_ALLOW_BUBBLE; + private boolean mIsMediaNotificationFilteringEnabled = DEFAULT_MEDIA_NOTIFICATION_FILTERING; private boolean mAreChannelsBypassingDnd; private boolean mHideSilentStatusBarIcons = DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS; @@ -184,6 +186,7 @@ public class PreferencesHelper implements RankingConfig { updateBadgingEnabled(); updateBubblesEnabled(); + updateMediaNotificationFilteringEnabled(); syncChannelsBypassingDnd(mContext.getUserId()); } @@ -2289,6 +2292,21 @@ public class PreferencesHelper implements RankingConfig { return mBubblesEnabledGlobally; } + /** Requests check of the feature setting for showing media notifications in quick settings. */ + public void updateMediaNotificationFilteringEnabled() { + final boolean newValue = Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.SHOW_MEDIA_ON_QUICK_SETTINGS, 1) > 0; + if (newValue != mIsMediaNotificationFilteringEnabled) { + mIsMediaNotificationFilteringEnabled = newValue; + updateConfig(); + } + } + + /** Returns true if the setting is enabled for showing media notifications in quick settings. */ + public boolean isMediaNotificationFilteringEnabled() { + return mIsMediaNotificationFilteringEnabled; + } + public void updateBadgingEnabled() { if (mBadgingEnabled == null) { mBadgingEnabled = new SparseBooleanArray(); diff --git a/services/core/java/com/android/server/notification/RankingConfig.java b/services/core/java/com/android/server/notification/RankingConfig.java index 7fc79e6a9bf75..b2827bae40bcd 100644 --- a/services/core/java/com/android/server/notification/RankingConfig.java +++ b/services/core/java/com/android/server/notification/RankingConfig.java @@ -31,6 +31,8 @@ public interface RankingConfig { boolean badgingEnabled(UserHandle userHandle); int getBubblePreference(String packageName, int uid); boolean bubblesEnabled(); + /** Returns true when feature is enabled that shows media notifications in quick settings. */ + boolean isMediaNotificationFilteringEnabled(); boolean isGroupBlocked(String packageName, int uid, String groupId); Collection getNotificationChannelGroups(String pkg, diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BadgeExtractorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BadgeExtractorTest.java index c9c31bfcde089..36ac5d5a111d3 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/BadgeExtractorTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/BadgeExtractorTest.java @@ -32,7 +32,7 @@ import android.app.NotificationChannel; import android.app.PendingIntent; import android.content.Intent; import android.graphics.drawable.Icon; - +import android.media.session.MediaSession; import android.os.UserHandle; import android.service.notification.StatusBarNotification; import android.test.suitebuilder.annotation.SmallTest; @@ -114,6 +114,31 @@ public class BadgeExtractorTest extends UiServiceTestCase { return r; } + private NotificationRecord getNotificationRecordWithMedia(boolean excludeSession) { + NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_UNSPECIFIED); + channel.setShowBadge(/* showBadge */ true); + when(mConfig.getNotificationChannel(mPkg, mUid, "a", false)).thenReturn(channel); + + Notification.MediaStyle style = new Notification.MediaStyle(); + if (!excludeSession) { + MediaSession session = new MediaSession(getContext(), "BadgeExtractorTestSession"); + style.setMediaSession(session.getSessionToken()); + } + + final Builder builder = new Builder(getContext()) + .setContentTitle("foo") + .setSmallIcon(android.R.drawable.sym_def_app_icon) + .setPriority(Notification.PRIORITY_HIGH) + .setDefaults(Notification.DEFAULT_SOUND) + .setStyle(style); + + Notification n = builder.build(); + StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, mId, mTag, mUid, + mPid, n, mUser, null, System.currentTimeMillis()); + NotificationRecord r = new NotificationRecord(getContext(), sbn, channel); + return r; + } + // // Tests // @@ -202,6 +227,66 @@ public class BadgeExtractorTest extends UiServiceTestCase { assertFalse(r.canShowBadge()); } + @Test + public void testHideMediaNotifOverridesYes() throws Exception { + BadgeExtractor extractor = new BadgeExtractor(); + extractor.setConfig(mConfig); + when(mConfig.badgingEnabled(mUser)).thenReturn(true); + when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true); + + when(mConfig.isMediaNotificationFilteringEnabled()).thenReturn(true); + NotificationRecord r = getNotificationRecordWithMedia(/* excludeSession */ false); + + extractor.process(r); + + assertFalse(r.canShowBadge()); + } + + @Test + public void testHideMediaNotifDisabledOverridesNo() throws Exception { + BadgeExtractor extractor = new BadgeExtractor(); + extractor.setConfig(mConfig); + when(mConfig.badgingEnabled(mUser)).thenReturn(true); + when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true); + + when(mConfig.isMediaNotificationFilteringEnabled()).thenReturn(false); + NotificationRecord r = getNotificationRecordWithMedia(/* excludeSession */ false); + + extractor.process(r); + + assertTrue(r.canShowBadge()); + } + + @Test + public void testHideMediaNotifNoSessionOverridesNo() throws Exception { + BadgeExtractor extractor = new BadgeExtractor(); + extractor.setConfig(mConfig); + when(mConfig.badgingEnabled(mUser)).thenReturn(true); + when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true); + + when(mConfig.isMediaNotificationFilteringEnabled()).thenReturn(true); + NotificationRecord r = getNotificationRecordWithMedia(/* excludeSession */ true); + + extractor.process(r); + + assertTrue(r.canShowBadge()); + } + + @Test + public void testHideMediaNotifNotMediaStyleOverridesNo() throws Exception { + BadgeExtractor extractor = new BadgeExtractor(); + extractor.setConfig(mConfig); + when(mConfig.badgingEnabled(mUser)).thenReturn(true); + when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true); + + when(mConfig.isMediaNotificationFilteringEnabled()).thenReturn(true); + NotificationRecord r = getNotificationRecord(true, IMPORTANCE_UNSPECIFIED); + + extractor.process(r); + + assertTrue(r.canShowBadge()); + } + @Test public void testDndOverridesYes() { BadgeExtractor extractor = new BadgeExtractor(); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java index 2e49929ec0327..5b0a7fb9d4137 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java @@ -2087,6 +2087,22 @@ public class PreferencesHelperTest extends UiServiceTestCase { assertFalse(mHelper.bubblesEnabled()); } + @Test + public void testShowQSMediaOverrideTrue() { + Global.putInt(getContext().getContentResolver(), + Global.SHOW_MEDIA_ON_QUICK_SETTINGS, 1); + mHelper.updateMediaNotificationFilteringEnabled(); // would be called by settings observer + assertTrue(mHelper.isMediaNotificationFilteringEnabled()); + } + + @Test + public void testShowQSMediaOverrideFalse() { + Global.putInt(getContext().getContentResolver(), + Global.SHOW_MEDIA_ON_QUICK_SETTINGS, 0); + mHelper.updateMediaNotificationFilteringEnabled(); // would be called by settings observer + assertFalse(mHelper.isMediaNotificationFilteringEnabled()); + } + @Test public void testOnLocaleChanged_updatesDefaultChannels() throws Exception { String newLabel = "bananas!";