Loading services/core/java/com/android/server/notification/NotificationManagerService.java +19 −9 Original line number Diff line number Diff line Loading @@ -8019,7 +8019,7 @@ public class NotificationManagerService extends SystemService { int callingUid, int callingPid, String pkg, boolean nullPkgIndicatesUserSwitch, String channelId, FlagChecker flagChecker, boolean includeCurrentProfiles, int userId, boolean sendDelete, int reason, String listenerName, boolean wasPosted) { ArrayList<NotificationRecord> canceledNotifications = null; Set<String> childNotifications = null; for (int i = notificationList.size() - 1; i >= 0; --i) { NotificationRecord r = notificationList.get(i); if (includeCurrentProfiles) { Loading @@ -8042,20 +8042,30 @@ public class NotificationManagerService extends SystemService { if (channelId != null && !channelId.equals(r.getChannel().getId())) { continue; } if (canceledNotifications == null) { canceledNotifications = new ArrayList<>(); if (r.getSbn().isGroup() && r.getNotification().isGroupChild()) { if (childNotifications == null) { childNotifications = new HashSet<>(); } childNotifications.add(r.getKey()); continue; } notificationList.remove(i); mNotificationsByKey.remove(r.getKey()); r.recordDismissalSentiment(NotificationStats.DISMISS_SENTIMENT_NEUTRAL); canceledNotifications.add(r); cancelNotificationLocked(r, sendDelete, reason, wasPosted, listenerName); } if (canceledNotifications != null) { final int M = canceledNotifications.size(); for (int i = 0; i < M; i++) { cancelGroupChildrenLocked(canceledNotifications.get(i), callingUid, callingPid, listenerName, false /* sendDelete */, flagChecker, reason); if (childNotifications != null) { final int M = notificationList.size(); for (int i = M - 1; i >= 0; i--) { NotificationRecord r = notificationList.get(i); if (childNotifications.contains(r.getKey())) { // dismiss conditions were checked in the first loop and so don't need to be // checked again notificationList.remove(i); mNotificationsByKey.remove(r.getKey()); r.recordDismissalSentiment(NotificationStats.DISMISS_SENTIMENT_NEUTRAL); cancelNotificationLocked(r, sendDelete, reason, wasPosted, listenerName); } } updateLightsLocked(); } Loading services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +61 −23 Original line number Diff line number Diff line Loading @@ -74,6 +74,7 @@ import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; Loading Loading @@ -185,6 +186,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.stubbing.Answer; Loading Loading @@ -563,6 +565,37 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { .getUiAutomation().dropShellPermissionIdentity(); } private void simulatePackageSuspendBroadcast(boolean suspend, String pkg, int uid) { // mimics receive broadcast that package is (un)suspended // but does not actually (un)suspend the package final Bundle extras = new Bundle(); extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, new String[]{pkg}); extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, new int[]{uid}); final String action = suspend ? Intent.ACTION_PACKAGES_SUSPENDED : Intent.ACTION_PACKAGES_UNSUSPENDED; final Intent intent = new Intent(action); intent.putExtras(extras); mPackageIntentReceiver.onReceive(getContext(), intent); } private void simulatePackageDistractionBroadcast(int flag, String[] pkgs, int[] uids) { // mimics receive broadcast that package is (un)distracting // but does not actually register that info with packagemanager final Bundle extras = new Bundle(); extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgs); extras.putInt(Intent.EXTRA_DISTRACTION_RESTRICTIONS, flag); extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uids); final Intent intent = new Intent(Intent.ACTION_DISTRACTING_PACKAGES_CHANGED); intent.putExtras(extras); mPackageIntentReceiver.onReceive(getContext(), intent); } private ArrayMap<Boolean, ArrayList<ComponentName>> generateResetComponentValues() { ArrayMap<Boolean, ArrayList<ComponentName>> changed = new ArrayMap<>(); changed.put(true, new ArrayList<>()); Loading Loading @@ -7066,34 +7099,39 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertTrue(mService.isVisibleToListener(sbn, info)); } private void simulatePackageSuspendBroadcast(boolean suspend, String pkg, int uid) { // mimics receive broadcast that package is (un)suspended // but does not actually (un)suspend the package final Bundle extras = new Bundle(); extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, new String[]{pkg}); extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, new int[]{uid}); @Test public void testUserInitiatedCancelAll_groupCancellationOrder_groupPostedFirst() { final NotificationRecord parent = spy(generateNotificationRecord( mTestNotificationChannel, 1, "group", true)); final NotificationRecord child = spy(generateNotificationRecord( mTestNotificationChannel, 2, "group", false)); mService.addNotification(parent); mService.addNotification(child); final String action = suspend ? Intent.ACTION_PACKAGES_SUSPENDED : Intent.ACTION_PACKAGES_UNSUSPENDED; final Intent intent = new Intent(action); intent.putExtras(extras); InOrder inOrder = inOrder(parent, child); mPackageIntentReceiver.onReceive(getContext(), intent); mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), parent.getUserId()); waitForIdle(); inOrder.verify(parent).recordDismissalSentiment(anyInt()); inOrder.verify(child).recordDismissalSentiment(anyInt()); } private void simulatePackageDistractionBroadcast(int flag, String[] pkgs, int[] uids) { // mimics receive broadcast that package is (un)distracting // but does not actually register that info with packagemanager final Bundle extras = new Bundle(); extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgs); extras.putInt(Intent.EXTRA_DISTRACTION_RESTRICTIONS, flag); extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uids); @Test public void testUserInitiatedCancelAll_groupCancellationOrder_groupPostedSecond() { final NotificationRecord parent = spy(generateNotificationRecord( mTestNotificationChannel, 1, "group", true)); final NotificationRecord child = spy(generateNotificationRecord( mTestNotificationChannel, 2, "group", false)); mService.addNotification(child); mService.addNotification(parent); final Intent intent = new Intent(Intent.ACTION_DISTRACTING_PACKAGES_CHANGED); intent.putExtras(extras); InOrder inOrder = inOrder(parent, child); mPackageIntentReceiver.onReceive(getContext(), intent); mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), parent.getUserId()); waitForIdle(); inOrder.verify(parent).recordDismissalSentiment(anyInt()); inOrder.verify(child).recordDismissalSentiment(anyInt()); } } Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +19 −9 Original line number Diff line number Diff line Loading @@ -8019,7 +8019,7 @@ public class NotificationManagerService extends SystemService { int callingUid, int callingPid, String pkg, boolean nullPkgIndicatesUserSwitch, String channelId, FlagChecker flagChecker, boolean includeCurrentProfiles, int userId, boolean sendDelete, int reason, String listenerName, boolean wasPosted) { ArrayList<NotificationRecord> canceledNotifications = null; Set<String> childNotifications = null; for (int i = notificationList.size() - 1; i >= 0; --i) { NotificationRecord r = notificationList.get(i); if (includeCurrentProfiles) { Loading @@ -8042,20 +8042,30 @@ public class NotificationManagerService extends SystemService { if (channelId != null && !channelId.equals(r.getChannel().getId())) { continue; } if (canceledNotifications == null) { canceledNotifications = new ArrayList<>(); if (r.getSbn().isGroup() && r.getNotification().isGroupChild()) { if (childNotifications == null) { childNotifications = new HashSet<>(); } childNotifications.add(r.getKey()); continue; } notificationList.remove(i); mNotificationsByKey.remove(r.getKey()); r.recordDismissalSentiment(NotificationStats.DISMISS_SENTIMENT_NEUTRAL); canceledNotifications.add(r); cancelNotificationLocked(r, sendDelete, reason, wasPosted, listenerName); } if (canceledNotifications != null) { final int M = canceledNotifications.size(); for (int i = 0; i < M; i++) { cancelGroupChildrenLocked(canceledNotifications.get(i), callingUid, callingPid, listenerName, false /* sendDelete */, flagChecker, reason); if (childNotifications != null) { final int M = notificationList.size(); for (int i = M - 1; i >= 0; i--) { NotificationRecord r = notificationList.get(i); if (childNotifications.contains(r.getKey())) { // dismiss conditions were checked in the first loop and so don't need to be // checked again notificationList.remove(i); mNotificationsByKey.remove(r.getKey()); r.recordDismissalSentiment(NotificationStats.DISMISS_SENTIMENT_NEUTRAL); cancelNotificationLocked(r, sendDelete, reason, wasPosted, listenerName); } } updateLightsLocked(); } Loading
services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +61 −23 Original line number Diff line number Diff line Loading @@ -74,6 +74,7 @@ import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; Loading Loading @@ -185,6 +186,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.stubbing.Answer; Loading Loading @@ -563,6 +565,37 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { .getUiAutomation().dropShellPermissionIdentity(); } private void simulatePackageSuspendBroadcast(boolean suspend, String pkg, int uid) { // mimics receive broadcast that package is (un)suspended // but does not actually (un)suspend the package final Bundle extras = new Bundle(); extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, new String[]{pkg}); extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, new int[]{uid}); final String action = suspend ? Intent.ACTION_PACKAGES_SUSPENDED : Intent.ACTION_PACKAGES_UNSUSPENDED; final Intent intent = new Intent(action); intent.putExtras(extras); mPackageIntentReceiver.onReceive(getContext(), intent); } private void simulatePackageDistractionBroadcast(int flag, String[] pkgs, int[] uids) { // mimics receive broadcast that package is (un)distracting // but does not actually register that info with packagemanager final Bundle extras = new Bundle(); extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgs); extras.putInt(Intent.EXTRA_DISTRACTION_RESTRICTIONS, flag); extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uids); final Intent intent = new Intent(Intent.ACTION_DISTRACTING_PACKAGES_CHANGED); intent.putExtras(extras); mPackageIntentReceiver.onReceive(getContext(), intent); } private ArrayMap<Boolean, ArrayList<ComponentName>> generateResetComponentValues() { ArrayMap<Boolean, ArrayList<ComponentName>> changed = new ArrayMap<>(); changed.put(true, new ArrayList<>()); Loading Loading @@ -7066,34 +7099,39 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertTrue(mService.isVisibleToListener(sbn, info)); } private void simulatePackageSuspendBroadcast(boolean suspend, String pkg, int uid) { // mimics receive broadcast that package is (un)suspended // but does not actually (un)suspend the package final Bundle extras = new Bundle(); extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, new String[]{pkg}); extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, new int[]{uid}); @Test public void testUserInitiatedCancelAll_groupCancellationOrder_groupPostedFirst() { final NotificationRecord parent = spy(generateNotificationRecord( mTestNotificationChannel, 1, "group", true)); final NotificationRecord child = spy(generateNotificationRecord( mTestNotificationChannel, 2, "group", false)); mService.addNotification(parent); mService.addNotification(child); final String action = suspend ? Intent.ACTION_PACKAGES_SUSPENDED : Intent.ACTION_PACKAGES_UNSUSPENDED; final Intent intent = new Intent(action); intent.putExtras(extras); InOrder inOrder = inOrder(parent, child); mPackageIntentReceiver.onReceive(getContext(), intent); mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), parent.getUserId()); waitForIdle(); inOrder.verify(parent).recordDismissalSentiment(anyInt()); inOrder.verify(child).recordDismissalSentiment(anyInt()); } private void simulatePackageDistractionBroadcast(int flag, String[] pkgs, int[] uids) { // mimics receive broadcast that package is (un)distracting // but does not actually register that info with packagemanager final Bundle extras = new Bundle(); extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgs); extras.putInt(Intent.EXTRA_DISTRACTION_RESTRICTIONS, flag); extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uids); @Test public void testUserInitiatedCancelAll_groupCancellationOrder_groupPostedSecond() { final NotificationRecord parent = spy(generateNotificationRecord( mTestNotificationChannel, 1, "group", true)); final NotificationRecord child = spy(generateNotificationRecord( mTestNotificationChannel, 2, "group", false)); mService.addNotification(child); mService.addNotification(parent); final Intent intent = new Intent(Intent.ACTION_DISTRACTING_PACKAGES_CHANGED); intent.putExtras(extras); InOrder inOrder = inOrder(parent, child); mPackageIntentReceiver.onReceive(getContext(), intent); mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), parent.getUserId()); waitForIdle(); inOrder.verify(parent).recordDismissalSentiment(anyInt()); inOrder.verify(child).recordDismissalSentiment(anyInt()); } }