Loading services/core/java/com/android/server/notification/NotificationManagerService.java +12 −11 Original line number Diff line number Diff line Loading @@ -573,7 +573,8 @@ public class NotificationManagerService extends SystemService { } } private final NotificationDelegate mNotificationDelegate = new NotificationDelegate() { @VisibleForTesting final NotificationDelegate mNotificationDelegate = new NotificationDelegate() { @Override public void onSetDisabled(int status) { Loading Loading @@ -3830,7 +3831,8 @@ public class NotificationManagerService extends SystemService { // notification was a summary and the new one isn't, or when the old // notification was a summary and its group key changed. if (oldIsSummary && (!isSummary || !oldGroup.equals(group))) { cancelGroupChildrenLocked(old, callingUid, callingPid, null, false /* sendDelete */); cancelGroupChildrenLocked(old, callingUid, callingPid, null, false /* sendDelete */, null); } } Loading Loading @@ -4581,7 +4583,7 @@ public class NotificationManagerService extends SystemService { boolean wasPosted = removeFromNotificationListsLocked(r); cancelNotificationLocked(r, sendDelete, reason, wasPosted); cancelGroupChildrenLocked(r, callingUid, callingPid, listenerName, sendDelete); sendDelete, null); updateLightsLocked(); } else { // No notification was found, assume that it is snoozed and cancel it. Loading Loading @@ -4652,7 +4654,6 @@ public class NotificationManagerService extends SystemService { } return true; }; cancelAllNotificationsByListLocked(mNotificationList, callingUid, callingPid, pkg, true /*nullPkgIndicatesUserSwitch*/, channelId, flagChecker, false /*includeCurrentProfiles*/, userId, false /*sendDelete*/, reason, Loading Loading @@ -4700,7 +4701,6 @@ public class NotificationManagerService extends SystemService { if (channelId != null && !channelId.equals(r.getChannel().getId())) { continue; } if (canceledNotifications == null) { canceledNotifications = new ArrayList<>(); } Loading @@ -4712,7 +4712,7 @@ public class NotificationManagerService extends SystemService { final int M = canceledNotifications.size(); for (int i = 0; i < M; i++) { cancelGroupChildrenLocked(canceledNotifications.get(i), callingUid, callingPid, listenerName, false /* sendDelete */); listenerName, false /* sendDelete */, flagChecker); } updateLightsLocked(); } Loading Loading @@ -4779,7 +4779,7 @@ public class NotificationManagerService extends SystemService { // Warning: The caller is responsible for invoking updateLightsLocked(). @GuardedBy("mNotificationLock") private void cancelGroupChildrenLocked(NotificationRecord r, int callingUid, int callingPid, String listenerName, boolean sendDelete) { String listenerName, boolean sendDelete, FlagChecker flagChecker) { Notification n = r.getNotification(); if (!n.isGroupSummary()) { return; Loading @@ -4793,15 +4793,15 @@ public class NotificationManagerService extends SystemService { } cancelGroupChildrenByListLocked(mNotificationList, r, callingUid, callingPid, listenerName, sendDelete, true); sendDelete, true, flagChecker); cancelGroupChildrenByListLocked(mEnqueuedNotifications, r, callingUid, callingPid, listenerName, sendDelete, false); listenerName, sendDelete, false, flagChecker); } @GuardedBy("mNotificationLock") private void cancelGroupChildrenByListLocked(ArrayList<NotificationRecord> notificationList, NotificationRecord parentNotification, int callingUid, int callingPid, String listenerName, boolean sendDelete, boolean wasPosted) { String listenerName, boolean sendDelete, boolean wasPosted, FlagChecker flagChecker) { final String pkg = parentNotification.sbn.getPackageName(); final int userId = parentNotification.getUserId(); final int reason = REASON_GROUP_SUMMARY_CANCELED; Loading @@ -4810,7 +4810,8 @@ public class NotificationManagerService extends SystemService { final StatusBarNotification childSbn = childR.sbn; if ((childSbn.isGroup() && !childSbn.getNotification().isGroupSummary()) && childR.getGroupKey().equals(parentNotification.getGroupKey()) && (childR.getFlags() & Notification.FLAG_FOREGROUND_SERVICE) == 0) { && (childR.getFlags() & Notification.FLAG_FOREGROUND_SERVICE) == 0 && (flagChecker == null || flagChecker.apply(childR.getFlags()))) { EventLogTags.writeNotificationCancel(callingUid, callingPid, pkg, childSbn.getId(), childSbn.getTag(), userId, 0, 0, reason, listenerName); notificationList.remove(i); Loading services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java +89 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.notification; import static android.app.NotificationManager.IMPORTANCE_LOW; import static android.app.NotificationManager.IMPORTANCE_NONE; import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; Loading Loading @@ -482,6 +483,93 @@ public class NotificationManagerServiceTest extends NotificationTestCase { assertEquals(1, notifs.length); } @Test public void testAppInitiatedCancelAllNotifications_CancelsNoClearFlag() throws Exception { final StatusBarNotification sbn = generateNotificationRecord(null).sbn; sbn.getNotification().flags |= Notification.FLAG_NO_CLEAR; mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", sbn.getId(), sbn.getNotification(), sbn.getUserId()); mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); waitForIdle(); StatusBarNotification[] notifs = mBinderService.getActiveNotifications(sbn.getPackageName()); assertEquals(0, notifs.length); } @Test public void testCancelAllNotifications_CancelsNoClearFlag() throws Exception { final NotificationRecord notif = generateNotificationRecord( mTestNotificationChannel, 1, "group", true); notif.getNotification().flags |= Notification.FLAG_NO_CLEAR; mNotificationManagerService.addNotification(notif); mNotificationManagerService.cancelAllNotificationsInt(uid, 0, PKG, null, 0, 0, true, notif.getUserId(), 0, null); waitForIdle(); StatusBarNotification[] notifs = mBinderService.getActiveNotifications(notif.sbn.getPackageName()); assertEquals(0, notifs.length); } @Test public void testUserInitiatedCancelAllOnClearAll_NoClearFlag() throws Exception { final NotificationRecord notif = generateNotificationRecord( mTestNotificationChannel, 1, "group", true); notif.getNotification().flags |= Notification.FLAG_NO_CLEAR; mNotificationManagerService.addNotification(notif); mNotificationManagerService.mNotificationDelegate.onClearAll(uid, Binder.getCallingPid(), notif.getUserId()); waitForIdle(); StatusBarNotification[] notifs = mBinderService.getActiveNotifications(notif.sbn.getPackageName()); assertEquals(1, notifs.length); } @Test public void testCancelAllCancelNotificationsFromListener_NoClearFlag() throws Exception { final NotificationRecord parent = generateNotificationRecord( mTestNotificationChannel, 1, "group", true); final NotificationRecord child = generateNotificationRecord( mTestNotificationChannel, 2, "group", false); final NotificationRecord child2 = generateNotificationRecord( mTestNotificationChannel, 3, "group", false); child2.getNotification().flags |= Notification.FLAG_NO_CLEAR; final NotificationRecord newGroup = generateNotificationRecord( mTestNotificationChannel, 4, "group2", false); mNotificationManagerService.addNotification(parent); mNotificationManagerService.addNotification(child); mNotificationManagerService.addNotification(child2); mNotificationManagerService.addNotification(newGroup); mNotificationManagerService.getBinderService().cancelNotificationsFromListener(null, null); waitForIdle(); StatusBarNotification[] notifs = mBinderService.getActiveNotifications(parent.sbn.getPackageName()); assertEquals(1, notifs.length); } @Test public void testUserInitiatedCancelAllWithGroup_NoClearFlag() throws Exception { final NotificationRecord parent = generateNotificationRecord( mTestNotificationChannel, 1, "group", true); final NotificationRecord child = generateNotificationRecord( mTestNotificationChannel, 2, "group", false); final NotificationRecord child2 = generateNotificationRecord( mTestNotificationChannel, 3, "group", false); child2.getNotification().flags |= Notification.FLAG_NO_CLEAR; final NotificationRecord newGroup = generateNotificationRecord( mTestNotificationChannel, 4, "group2", false); mNotificationManagerService.addNotification(parent); mNotificationManagerService.addNotification(child); mNotificationManagerService.addNotification(child2); mNotificationManagerService.addNotification(newGroup); mNotificationManagerService.mNotificationDelegate.onClearAll(uid, Binder.getCallingPid(), parent.getUserId()); waitForIdle(); StatusBarNotification[] notifs = mBinderService.getActiveNotifications(parent.sbn.getPackageName()); assertEquals(1, notifs.length); } @Test public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception { final StatusBarNotification sbn = generateNotificationRecord(null).sbn; Loading Loading @@ -1130,4 +1218,5 @@ public class NotificationManagerServiceTest extends NotificationTestCase { verify(mGroupHelper, never()).onNotificationPosted(any()); } } Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +12 −11 Original line number Diff line number Diff line Loading @@ -573,7 +573,8 @@ public class NotificationManagerService extends SystemService { } } private final NotificationDelegate mNotificationDelegate = new NotificationDelegate() { @VisibleForTesting final NotificationDelegate mNotificationDelegate = new NotificationDelegate() { @Override public void onSetDisabled(int status) { Loading Loading @@ -3830,7 +3831,8 @@ public class NotificationManagerService extends SystemService { // notification was a summary and the new one isn't, or when the old // notification was a summary and its group key changed. if (oldIsSummary && (!isSummary || !oldGroup.equals(group))) { cancelGroupChildrenLocked(old, callingUid, callingPid, null, false /* sendDelete */); cancelGroupChildrenLocked(old, callingUid, callingPid, null, false /* sendDelete */, null); } } Loading Loading @@ -4581,7 +4583,7 @@ public class NotificationManagerService extends SystemService { boolean wasPosted = removeFromNotificationListsLocked(r); cancelNotificationLocked(r, sendDelete, reason, wasPosted); cancelGroupChildrenLocked(r, callingUid, callingPid, listenerName, sendDelete); sendDelete, null); updateLightsLocked(); } else { // No notification was found, assume that it is snoozed and cancel it. Loading Loading @@ -4652,7 +4654,6 @@ public class NotificationManagerService extends SystemService { } return true; }; cancelAllNotificationsByListLocked(mNotificationList, callingUid, callingPid, pkg, true /*nullPkgIndicatesUserSwitch*/, channelId, flagChecker, false /*includeCurrentProfiles*/, userId, false /*sendDelete*/, reason, Loading Loading @@ -4700,7 +4701,6 @@ public class NotificationManagerService extends SystemService { if (channelId != null && !channelId.equals(r.getChannel().getId())) { continue; } if (canceledNotifications == null) { canceledNotifications = new ArrayList<>(); } Loading @@ -4712,7 +4712,7 @@ public class NotificationManagerService extends SystemService { final int M = canceledNotifications.size(); for (int i = 0; i < M; i++) { cancelGroupChildrenLocked(canceledNotifications.get(i), callingUid, callingPid, listenerName, false /* sendDelete */); listenerName, false /* sendDelete */, flagChecker); } updateLightsLocked(); } Loading Loading @@ -4779,7 +4779,7 @@ public class NotificationManagerService extends SystemService { // Warning: The caller is responsible for invoking updateLightsLocked(). @GuardedBy("mNotificationLock") private void cancelGroupChildrenLocked(NotificationRecord r, int callingUid, int callingPid, String listenerName, boolean sendDelete) { String listenerName, boolean sendDelete, FlagChecker flagChecker) { Notification n = r.getNotification(); if (!n.isGroupSummary()) { return; Loading @@ -4793,15 +4793,15 @@ public class NotificationManagerService extends SystemService { } cancelGroupChildrenByListLocked(mNotificationList, r, callingUid, callingPid, listenerName, sendDelete, true); sendDelete, true, flagChecker); cancelGroupChildrenByListLocked(mEnqueuedNotifications, r, callingUid, callingPid, listenerName, sendDelete, false); listenerName, sendDelete, false, flagChecker); } @GuardedBy("mNotificationLock") private void cancelGroupChildrenByListLocked(ArrayList<NotificationRecord> notificationList, NotificationRecord parentNotification, int callingUid, int callingPid, String listenerName, boolean sendDelete, boolean wasPosted) { String listenerName, boolean sendDelete, boolean wasPosted, FlagChecker flagChecker) { final String pkg = parentNotification.sbn.getPackageName(); final int userId = parentNotification.getUserId(); final int reason = REASON_GROUP_SUMMARY_CANCELED; Loading @@ -4810,7 +4810,8 @@ public class NotificationManagerService extends SystemService { final StatusBarNotification childSbn = childR.sbn; if ((childSbn.isGroup() && !childSbn.getNotification().isGroupSummary()) && childR.getGroupKey().equals(parentNotification.getGroupKey()) && (childR.getFlags() & Notification.FLAG_FOREGROUND_SERVICE) == 0) { && (childR.getFlags() & Notification.FLAG_FOREGROUND_SERVICE) == 0 && (flagChecker == null || flagChecker.apply(childR.getFlags()))) { EventLogTags.writeNotificationCancel(callingUid, callingPid, pkg, childSbn.getId(), childSbn.getTag(), userId, 0, 0, reason, listenerName); notificationList.remove(i); Loading
services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java +89 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.notification; import static android.app.NotificationManager.IMPORTANCE_LOW; import static android.app.NotificationManager.IMPORTANCE_NONE; import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; Loading Loading @@ -482,6 +483,93 @@ public class NotificationManagerServiceTest extends NotificationTestCase { assertEquals(1, notifs.length); } @Test public void testAppInitiatedCancelAllNotifications_CancelsNoClearFlag() throws Exception { final StatusBarNotification sbn = generateNotificationRecord(null).sbn; sbn.getNotification().flags |= Notification.FLAG_NO_CLEAR; mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", sbn.getId(), sbn.getNotification(), sbn.getUserId()); mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); waitForIdle(); StatusBarNotification[] notifs = mBinderService.getActiveNotifications(sbn.getPackageName()); assertEquals(0, notifs.length); } @Test public void testCancelAllNotifications_CancelsNoClearFlag() throws Exception { final NotificationRecord notif = generateNotificationRecord( mTestNotificationChannel, 1, "group", true); notif.getNotification().flags |= Notification.FLAG_NO_CLEAR; mNotificationManagerService.addNotification(notif); mNotificationManagerService.cancelAllNotificationsInt(uid, 0, PKG, null, 0, 0, true, notif.getUserId(), 0, null); waitForIdle(); StatusBarNotification[] notifs = mBinderService.getActiveNotifications(notif.sbn.getPackageName()); assertEquals(0, notifs.length); } @Test public void testUserInitiatedCancelAllOnClearAll_NoClearFlag() throws Exception { final NotificationRecord notif = generateNotificationRecord( mTestNotificationChannel, 1, "group", true); notif.getNotification().flags |= Notification.FLAG_NO_CLEAR; mNotificationManagerService.addNotification(notif); mNotificationManagerService.mNotificationDelegate.onClearAll(uid, Binder.getCallingPid(), notif.getUserId()); waitForIdle(); StatusBarNotification[] notifs = mBinderService.getActiveNotifications(notif.sbn.getPackageName()); assertEquals(1, notifs.length); } @Test public void testCancelAllCancelNotificationsFromListener_NoClearFlag() throws Exception { final NotificationRecord parent = generateNotificationRecord( mTestNotificationChannel, 1, "group", true); final NotificationRecord child = generateNotificationRecord( mTestNotificationChannel, 2, "group", false); final NotificationRecord child2 = generateNotificationRecord( mTestNotificationChannel, 3, "group", false); child2.getNotification().flags |= Notification.FLAG_NO_CLEAR; final NotificationRecord newGroup = generateNotificationRecord( mTestNotificationChannel, 4, "group2", false); mNotificationManagerService.addNotification(parent); mNotificationManagerService.addNotification(child); mNotificationManagerService.addNotification(child2); mNotificationManagerService.addNotification(newGroup); mNotificationManagerService.getBinderService().cancelNotificationsFromListener(null, null); waitForIdle(); StatusBarNotification[] notifs = mBinderService.getActiveNotifications(parent.sbn.getPackageName()); assertEquals(1, notifs.length); } @Test public void testUserInitiatedCancelAllWithGroup_NoClearFlag() throws Exception { final NotificationRecord parent = generateNotificationRecord( mTestNotificationChannel, 1, "group", true); final NotificationRecord child = generateNotificationRecord( mTestNotificationChannel, 2, "group", false); final NotificationRecord child2 = generateNotificationRecord( mTestNotificationChannel, 3, "group", false); child2.getNotification().flags |= Notification.FLAG_NO_CLEAR; final NotificationRecord newGroup = generateNotificationRecord( mTestNotificationChannel, 4, "group2", false); mNotificationManagerService.addNotification(parent); mNotificationManagerService.addNotification(child); mNotificationManagerService.addNotification(child2); mNotificationManagerService.addNotification(newGroup); mNotificationManagerService.mNotificationDelegate.onClearAll(uid, Binder.getCallingPid(), parent.getUserId()); waitForIdle(); StatusBarNotification[] notifs = mBinderService.getActiveNotifications(parent.sbn.getPackageName()); assertEquals(1, notifs.length); } @Test public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception { final StatusBarNotification sbn = generateNotificationRecord(null).sbn; Loading Loading @@ -1130,4 +1218,5 @@ public class NotificationManagerServiceTest extends NotificationTestCase { verify(mGroupHelper, never()).onNotificationPosted(any()); } }