diff options
| author | 2021-11-10 23:14:13 +0000 | |
|---|---|---|
| committer | 2021-11-10 23:14:13 +0000 | |
| commit | 43a7ff5f43352e18abd54264e7794267567fa00a (patch) | |
| tree | 3bdafbc3ef6d696715c8deb4fceaf59377e8cecf | |
| parent | 9371fa74efe649b993e9394519b2d3dc5760787f (diff) | |
| parent | 3c7454167ba6a830bb94855b541dfaebd8fe1cda (diff) | |
Merge "Allow media notifications to always be posted"
3 files changed, 153 insertions, 4 deletions
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 5516109253df..6b7500ae4b2f 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -6784,11 +6784,13 @@ public class NotificationManagerService extends SystemService { // blocked apps + boolean isMediaNotification = n.isMediaNotification() + && n.extras.getParcelable(Notification.EXTRA_MEDIA_SESSION) != null; boolean isBlocked = !areNotificationsEnabledForPackageInt(pkg, uid); synchronized (mNotificationLock) { isBlocked |= isRecordBlockedLocked(r); } - if (isBlocked) { + if (isBlocked && !isMediaNotification) { if (DBG) { Slog.e(TAG, "Suppressing notification from package " + r.getSbn().getPackageName() + " by user request."); @@ -7174,7 +7176,13 @@ public class NotificationManagerService extends SystemService { return; } - if (appBanned || isRecordBlockedLocked(r)) { + final StatusBarNotification n = r.getSbn(); + final Notification notification = n.getNotification(); + + boolean isMediaNotification = notification.isMediaNotification() + && notification.extras.getParcelable( + Notification.EXTRA_MEDIA_SESSION) != null; + if (!isMediaNotification && (appBanned || isRecordBlockedLocked(r))) { mUsageStats.registerBlocked(r); if (DBG) { Slog.e(TAG, "Suppressing notification from package " + pkg); @@ -7189,8 +7197,6 @@ public class NotificationManagerService extends SystemService { mUsageStats.registerSuspendedByAdmin(r); } NotificationRecord old = mNotificationsByKey.get(key); - final StatusBarNotification n = r.getSbn(); - final Notification notification = n.getNotification(); // Make sure the SBN has an instance ID for statsd logging. if (old == null || old.getSbn().getInstanceId() == null) { diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 7237b243512c..5a5a4e754390 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -142,6 +142,7 @@ import android.content.res.Resources; import android.graphics.Color; import android.graphics.drawable.Icon; import android.media.AudioManager; +import android.media.session.MediaSession; import android.net.Uri; import android.os.Binder; import android.os.Build; @@ -8465,4 +8466,45 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { fail("call to matchesCallFilter with listener permissions should work"); } } + + @Test + public void testMediaNotificationsBypassBlock() throws Exception { + when(mAmi.getPendingIntentFlags(any(IIntentSender.class))) + .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT); + when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); + + Notification.Builder nb = new Notification.Builder( + mContext, mTestNotificationChannel.getId()) + .setContentTitle("foo") + .setSmallIcon(android.R.drawable.sym_def_app_icon) + .addAction(new Notification.Action.Builder(null, "test", null).build()); + StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, + nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); + NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); + + mBinderService.setNotificationsEnabledForPackage( + r.getSbn().getPackageName(), r.getUid(), false); + + // normal blocked notifications - blocked + assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), + r.getSbn().getId(), r.getSbn().getTag(), r, false)).isFalse(); + + // just using the style - blocked + nb.setStyle(new Notification.MediaStyle()); + sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, + nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); + r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); + + assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), + r.getSbn().getId(), r.getSbn().getTag(), r, false)).isFalse(); + + // style + media session - bypasses block + nb.setStyle(new Notification.MediaStyle().setMediaSession(mock(MediaSession.Token.class))); + sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, + nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); + r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); + + assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), + r.getSbn().getId(), r.getSbn().getTag(), r, false)).isTrue(); + } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java index 423ba94729ff..011d190ea83a 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java @@ -23,6 +23,8 @@ import static android.app.NotificationManager.IMPORTANCE_DEFAULT; import static android.app.NotificationManager.IMPORTANCE_LOW; import static android.app.NotificationManager.IMPORTANCE_NONE; import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED; +import static android.app.PendingIntent.FLAG_MUTABLE; +import static android.app.PendingIntent.FLAG_ONE_SHOT; import static android.content.pm.PackageManager.FEATURE_WATCH; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.os.UserHandle.USER_SYSTEM; @@ -84,6 +86,7 @@ import android.content.pm.ShortcutInfo; import android.content.pm.ShortcutServiceInternal; import android.content.res.Resources; import android.media.AudioManager; +import android.media.session.MediaSession; import android.os.Binder; import android.os.Build; import android.os.IBinder; @@ -711,4 +714,102 @@ public class NotificationPermissionMigrationTest extends UiServiceTestCase { assertThat(r.isImportanceFixed()).isTrue(); } + + @Test + public void testMediaNotificationsBypassBlock() throws Exception { + when(mAmi.getPendingIntentFlags(any(IIntentSender.class))) + .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT); + when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); + + Notification.Builder nb = new Notification.Builder( + mContext, mTestNotificationChannel.getId()) + .setContentTitle("foo") + .setSmallIcon(android.R.drawable.sym_def_app_icon) + .addAction(new Notification.Action.Builder(null, "test", null).build()); + StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, + nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); + NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); + + when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); + + // normal blocked notifications - blocked + assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), + r.getSbn().getId(), r.getSbn().getTag(), r, false)).isFalse(); + + // just using the style - blocked + nb.setStyle(new Notification.MediaStyle()); + sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, + nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); + r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); + + assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), + r.getSbn().getId(), r.getSbn().getTag(), r, false)).isFalse(); + + // style + media session - bypasses block + nb.setStyle(new Notification.MediaStyle().setMediaSession(mock(MediaSession.Token.class))); + sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, + nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); + r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); + + assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), + r.getSbn().getId(), r.getSbn().getTag(), r, false)).isTrue(); + } + + @Test + public void testMediaNotificationsBypassBlock_atPost() throws Exception { + when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); + when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); + + Notification.Builder nb = new Notification.Builder( + mContext, mTestNotificationChannel.getId()) + .setContentTitle("foo") + .setSmallIcon(android.R.drawable.sym_def_app_icon) + .addAction(new Notification.Action.Builder(null, "test", null).build()); + StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, + nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); + NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); + + when(mPermissionHelper.hasPermission(anyInt())).thenReturn(false); + + mService.addEnqueuedNotification(r); + NotificationManagerService.PostNotificationRunnable runnable = + mService.new PostNotificationRunnable(r.getKey()); + runnable.run(); + waitForIdle(); + + verify(mUsageStats).registerBlocked(any()); + verify(mUsageStats, never()).registerPostedByApp(any()); + + // just using the style - blocked + mService.clearNotifications(); + reset(mUsageStats); + nb.setStyle(new Notification.MediaStyle()); + sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, + nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); + r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); + + mService.addEnqueuedNotification(r); + runnable = mService.new PostNotificationRunnable(r.getKey()); + runnable.run(); + waitForIdle(); + + verify(mUsageStats).registerBlocked(any()); + verify(mUsageStats, never()).registerPostedByApp(any()); + + // style + media session - bypasses block + mService.clearNotifications(); + reset(mUsageStats); + nb.setStyle(new Notification.MediaStyle().setMediaSession(mock(MediaSession.Token.class))); + sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, + nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); + r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); + + mService.addEnqueuedNotification(r); + runnable = mService.new PostNotificationRunnable(r.getKey()); + runnable.run(); + waitForIdle(); + + verify(mUsageStats, never()).registerBlocked(any()); + verify(mUsageStats).registerPostedByApp(any()); + } } |