Loading services/core/java/com/android/server/notification/NotificationManagerService.java +10 −4 Original line number Diff line number Diff line Loading @@ -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."); Loading Loading @@ -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); Loading @@ -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) { Loading services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +42 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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(); } } services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java +101 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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()); } } Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +10 −4 Original line number Diff line number Diff line Loading @@ -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."); Loading Loading @@ -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); Loading @@ -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) { Loading
services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +42 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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(); } }
services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java +101 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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()); } }