Loading services/core/java/com/android/server/notification/GroupHelper.java +51 −21 Original line number Diff line number Diff line Loading @@ -92,10 +92,16 @@ public class GroupHelper { static final int REGROUP_REASON_CHANNEL_UPDATE = 0; // Regrouping needed because of notification bundling static final int REGROUP_REASON_BUNDLE = 1; // Regrouping needed because of notification unbundling static final int REGROUP_REASON_UNBUNDLE = 2; // Regrouping needed because of notification unbundling + the original group summary exists static final int REGROUP_REASON_UNBUNDLE_ORIGINAL_GROUP = 3; @IntDef(prefix = { "REGROUP_REASON_" }, value = { REGROUP_REASON_CHANNEL_UPDATE, REGROUP_REASON_BUNDLE, REGROUP_REASON_UNBUNDLE, REGROUP_REASON_UNBUNDLE_ORIGINAL_GROUP, }) @Retention(RetentionPolicy.SOURCE) @interface RegroupingReason {} Loading @@ -103,7 +109,6 @@ public class GroupHelper { private final Callback mCallback; private final int mAutoGroupAtCount; private final int mAutogroupSparseGroupsAtCount; private final int mAutoGroupRegroupingAtCount; private final Context mContext; private final PackageManager mPackageManager; private boolean mIsTestHarnessExempted; Loading Loading @@ -190,11 +195,6 @@ public class GroupHelper { mContext = context; mPackageManager = packageManager; mAutogroupSparseGroupsAtCount = autoGroupSparseGroupsAtCount; if (notificationRegroupOnClassification()) { mAutoGroupRegroupingAtCount = 1; } else { mAutoGroupRegroupingAtCount = mAutoGroupAtCount; } NOTIFICATION_SHADE_SECTIONS = getNotificationShadeSections(); } Loading Loading @@ -797,7 +797,8 @@ public class GroupHelper { Slog.v(TAG, "isGroupChildInDifferentBundleThanSummary: " + record); } moveNotificationsToNewSection(record.getUserId(), pkgName, List.of(new NotificationMoveOp(record, null, fullAggregateGroupKey))); List.of(new NotificationMoveOp(record, null, fullAggregateGroupKey)), REGROUP_REASON_BUNDLE); return; } } Loading Loading @@ -945,6 +946,27 @@ public class GroupHelper { } } /** * Called when a notification that was classified (bundled) is restored to its original channel. * The notification will be restored to its original group, if any/if summary still exists. * Otherwise it will be moved to the appropriate section as an ungrouped notification. * * @param record the notification which had its channel updated * @param originalSummaryExists the original group summary exists */ @FlaggedApi(android.service.notification.Flags.FLAG_NOTIFICATION_FORCE_GROUPING) public void onNotificationUnbundled(final NotificationRecord record, final boolean originalSummaryExists) { synchronized (mAggregatedNotifications) { ArrayMap<String, NotificationRecord> notificationsToCheck = new ArrayMap<>(); notificationsToCheck.put(record.getKey(), record); regroupNotifications(record.getUserId(), record.getSbn().getPackageName(), notificationsToCheck, originalSummaryExists ? REGROUP_REASON_UNBUNDLE_ORIGINAL_GROUP : REGROUP_REASON_UNBUNDLE); } } @GuardedBy("mAggregatedNotifications") private void regroupNotifications(int userId, String pkgName, ArrayMap<String, NotificationRecord> notificationsToCheck, Loading Loading @@ -973,7 +995,7 @@ public class GroupHelper { // Batch move to new section if (!notificationsToMove.isEmpty()) { moveNotificationsToNewSection(userId, pkgName, notificationsToMove); moveNotificationsToNewSection(userId, pkgName, notificationsToMove, regroupingReason); } } Loading Loading @@ -1093,7 +1115,7 @@ public class GroupHelper { @GuardedBy("mAggregatedNotifications") private void moveNotificationsToNewSection(final int userId, final String pkgName, final List<NotificationMoveOp> notificationsToMove) { final List<NotificationMoveOp> notificationsToMove, int regroupingReason) { record GroupUpdateOp(FullyQualifiedGroupKey groupKey, NotificationRecord record, boolean hasSummary) { } // Bundled operations to apply to groups affected by the channel update Loading @@ -1111,7 +1133,8 @@ public class GroupHelper { if (DEBUG) { Log.i(TAG, "moveNotificationToNewSection: " + record + " " + newFullAggregateGroupKey + " from: " + oldFullAggregateGroupKey); + " from: " + oldFullAggregateGroupKey + " regroupingReason: " + regroupingReason); } // Update/remove aggregate summary for old group Loading Loading @@ -1140,6 +1163,12 @@ public class GroupHelper { // Add moved notifications to the ungrouped list for new group and do grouping // after all notifications have been handled if (newFullAggregateGroupKey != null) { if (notificationRegroupOnClassification() && regroupingReason == REGROUP_REASON_UNBUNDLE_ORIGINAL_GROUP) { // Just reset override group key, original summary exists // => will be grouped back to its original group record.setOverrideGroupKey(null); } else { final ArrayMap<String, NotificationAttributes> newAggregatedNotificationsAttrs = mAggregatedNotifications.getOrDefault(newFullAggregateGroupKey, new ArrayMap<>()); Loading @@ -1165,6 +1194,7 @@ public class GroupHelper { } } } } // Update groups (sections) for (FullyQualifiedGroupKey groupKey : groupsToUpdate.keySet()) { Loading @@ -1176,7 +1206,7 @@ public class GroupHelper { NotificationRecord triggeringNotification = groupsToUpdate.get(groupKey).record; boolean hasSummary = groupsToUpdate.get(groupKey).hasSummary; //Group needs to be created/updated if (ungrouped.size() >= mAutoGroupRegroupingAtCount if (ungrouped.size() >= mAutoGroupAtCount || (hasSummary && !aggregatedNotificationsAttrs.isEmpty())) { NotificationSectioner sectioner = getSection(triggeringNotification); if (sectioner == null) { Loading services/core/java/com/android/server/notification/NotificationManagerService.java +6 −3 Original line number Diff line number Diff line Loading @@ -7180,6 +7180,8 @@ public class NotificationManagerService extends SystemService { Slog.i(TAG, "Removing app summary (all children bundled): " + groupSummary); } if (convertSummaryToNotificationLocked(groupSummary.getKey())) { groupSummary.isCanceled = true; canceledSummary = groupSummary; mSummaryByGroupKey.remove(oldGroupKey); cancelNotification(Binder.getCallingUid(), Binder.getCallingPid(), Loading @@ -7190,6 +7192,7 @@ public class NotificationManagerService extends SystemService { } } } } return canceledSummary; } Loading services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java +220 −24 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
services/core/java/com/android/server/notification/GroupHelper.java +51 −21 Original line number Diff line number Diff line Loading @@ -92,10 +92,16 @@ public class GroupHelper { static final int REGROUP_REASON_CHANNEL_UPDATE = 0; // Regrouping needed because of notification bundling static final int REGROUP_REASON_BUNDLE = 1; // Regrouping needed because of notification unbundling static final int REGROUP_REASON_UNBUNDLE = 2; // Regrouping needed because of notification unbundling + the original group summary exists static final int REGROUP_REASON_UNBUNDLE_ORIGINAL_GROUP = 3; @IntDef(prefix = { "REGROUP_REASON_" }, value = { REGROUP_REASON_CHANNEL_UPDATE, REGROUP_REASON_BUNDLE, REGROUP_REASON_UNBUNDLE, REGROUP_REASON_UNBUNDLE_ORIGINAL_GROUP, }) @Retention(RetentionPolicy.SOURCE) @interface RegroupingReason {} Loading @@ -103,7 +109,6 @@ public class GroupHelper { private final Callback mCallback; private final int mAutoGroupAtCount; private final int mAutogroupSparseGroupsAtCount; private final int mAutoGroupRegroupingAtCount; private final Context mContext; private final PackageManager mPackageManager; private boolean mIsTestHarnessExempted; Loading Loading @@ -190,11 +195,6 @@ public class GroupHelper { mContext = context; mPackageManager = packageManager; mAutogroupSparseGroupsAtCount = autoGroupSparseGroupsAtCount; if (notificationRegroupOnClassification()) { mAutoGroupRegroupingAtCount = 1; } else { mAutoGroupRegroupingAtCount = mAutoGroupAtCount; } NOTIFICATION_SHADE_SECTIONS = getNotificationShadeSections(); } Loading Loading @@ -797,7 +797,8 @@ public class GroupHelper { Slog.v(TAG, "isGroupChildInDifferentBundleThanSummary: " + record); } moveNotificationsToNewSection(record.getUserId(), pkgName, List.of(new NotificationMoveOp(record, null, fullAggregateGroupKey))); List.of(new NotificationMoveOp(record, null, fullAggregateGroupKey)), REGROUP_REASON_BUNDLE); return; } } Loading Loading @@ -945,6 +946,27 @@ public class GroupHelper { } } /** * Called when a notification that was classified (bundled) is restored to its original channel. * The notification will be restored to its original group, if any/if summary still exists. * Otherwise it will be moved to the appropriate section as an ungrouped notification. * * @param record the notification which had its channel updated * @param originalSummaryExists the original group summary exists */ @FlaggedApi(android.service.notification.Flags.FLAG_NOTIFICATION_FORCE_GROUPING) public void onNotificationUnbundled(final NotificationRecord record, final boolean originalSummaryExists) { synchronized (mAggregatedNotifications) { ArrayMap<String, NotificationRecord> notificationsToCheck = new ArrayMap<>(); notificationsToCheck.put(record.getKey(), record); regroupNotifications(record.getUserId(), record.getSbn().getPackageName(), notificationsToCheck, originalSummaryExists ? REGROUP_REASON_UNBUNDLE_ORIGINAL_GROUP : REGROUP_REASON_UNBUNDLE); } } @GuardedBy("mAggregatedNotifications") private void regroupNotifications(int userId, String pkgName, ArrayMap<String, NotificationRecord> notificationsToCheck, Loading Loading @@ -973,7 +995,7 @@ public class GroupHelper { // Batch move to new section if (!notificationsToMove.isEmpty()) { moveNotificationsToNewSection(userId, pkgName, notificationsToMove); moveNotificationsToNewSection(userId, pkgName, notificationsToMove, regroupingReason); } } Loading Loading @@ -1093,7 +1115,7 @@ public class GroupHelper { @GuardedBy("mAggregatedNotifications") private void moveNotificationsToNewSection(final int userId, final String pkgName, final List<NotificationMoveOp> notificationsToMove) { final List<NotificationMoveOp> notificationsToMove, int regroupingReason) { record GroupUpdateOp(FullyQualifiedGroupKey groupKey, NotificationRecord record, boolean hasSummary) { } // Bundled operations to apply to groups affected by the channel update Loading @@ -1111,7 +1133,8 @@ public class GroupHelper { if (DEBUG) { Log.i(TAG, "moveNotificationToNewSection: " + record + " " + newFullAggregateGroupKey + " from: " + oldFullAggregateGroupKey); + " from: " + oldFullAggregateGroupKey + " regroupingReason: " + regroupingReason); } // Update/remove aggregate summary for old group Loading Loading @@ -1140,6 +1163,12 @@ public class GroupHelper { // Add moved notifications to the ungrouped list for new group and do grouping // after all notifications have been handled if (newFullAggregateGroupKey != null) { if (notificationRegroupOnClassification() && regroupingReason == REGROUP_REASON_UNBUNDLE_ORIGINAL_GROUP) { // Just reset override group key, original summary exists // => will be grouped back to its original group record.setOverrideGroupKey(null); } else { final ArrayMap<String, NotificationAttributes> newAggregatedNotificationsAttrs = mAggregatedNotifications.getOrDefault(newFullAggregateGroupKey, new ArrayMap<>()); Loading @@ -1165,6 +1194,7 @@ public class GroupHelper { } } } } // Update groups (sections) for (FullyQualifiedGroupKey groupKey : groupsToUpdate.keySet()) { Loading @@ -1176,7 +1206,7 @@ public class GroupHelper { NotificationRecord triggeringNotification = groupsToUpdate.get(groupKey).record; boolean hasSummary = groupsToUpdate.get(groupKey).hasSummary; //Group needs to be created/updated if (ungrouped.size() >= mAutoGroupRegroupingAtCount if (ungrouped.size() >= mAutoGroupAtCount || (hasSummary && !aggregatedNotificationsAttrs.isEmpty())) { NotificationSectioner sectioner = getSection(triggeringNotification); if (sectioner == null) { Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +6 −3 Original line number Diff line number Diff line Loading @@ -7180,6 +7180,8 @@ public class NotificationManagerService extends SystemService { Slog.i(TAG, "Removing app summary (all children bundled): " + groupSummary); } if (convertSummaryToNotificationLocked(groupSummary.getKey())) { groupSummary.isCanceled = true; canceledSummary = groupSummary; mSummaryByGroupKey.remove(oldGroupKey); cancelNotification(Binder.getCallingUid(), Binder.getCallingPid(), Loading @@ -7190,6 +7192,7 @@ public class NotificationManagerService extends SystemService { } } } } return canceledSummary; } Loading
services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java +220 −24 File changed.Preview size limit exceeded, changes collapsed. Show changes