Loading core/java/android/service/notification/Adjustment.java +9 −1 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.StringDef; import android.annotation.SystemApi; import android.annotation.TestApi; import android.app.Notification; import android.os.Build; import android.os.Bundle; Loading Loading @@ -67,6 +66,7 @@ public final class Adjustment implements Parcelable { KEY_RANKING_SCORE, KEY_NOT_CONVERSATION, KEY_TYPE, KEY_UNCLASSIFY, KEY_SUMMARIZATION }) @Retention(RetentionPolicy.SOURCE) Loading Loading @@ -224,6 +224,14 @@ public final class Adjustment implements Parcelable { @FlaggedApi(Flags.FLAG_NOTIFICATION_CLASSIFICATION) public static final int TYPE_CONTENT_RECOMMENDATION = 4; /** * Data type: NotificationChannel; the presence of this key indicates that the notification * classification should be removed and the channel reverted to its original channel (provided). * @hide */ @FlaggedApi(Flags.FLAG_NOTIFICATION_CLASSIFICATION) public static final String KEY_UNCLASSIFY = "key_unclassify"; /** * Data type: CharSequence, a summarization of the text of the notification, or, if provided for * a group summary, a summarization of the text of all of the notificatrions in the group. Loading services/core/java/com/android/server/notification/NotificationAdjustmentExtractor.java +13 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.notification; import static android.service.notification.Adjustment.KEY_TYPE; import static android.service.notification.Adjustment.KEY_UNCLASSIFY; import static android.service.notification.Flags.notificationForceGrouping; import android.content.Context; Loading @@ -41,12 +42,13 @@ public class NotificationAdjustmentExtractor implements NotificationSignalExtrac } final boolean hasAdjustedClassification = record.hasAdjustment(KEY_TYPE); final boolean removedClassification = record.hasAdjustment(KEY_UNCLASSIFY); record.applyAdjustments(); if (notificationForceGrouping() && android.service.notification.Flags.notificationClassification()) { // Classification adjustments trigger regrouping if (mGroupHelper != null && hasAdjustedClassification) { if (mGroupHelper != null && (hasAdjustedClassification || removedClassification)) { return new RankingReconsideration(record.getKey(), 0) { @Override public void work() { Loading @@ -54,8 +56,17 @@ public class NotificationAdjustmentExtractor implements NotificationSignalExtrac @Override public void applyChangesLocked(NotificationRecord record) { if (hasAdjustedClassification) { mGroupHelper.onChannelUpdated(record); } if (removedClassification) { mGroupHelper.onNotificationUnbundled(record, record.hadGroupSummaryWhenUnclassified()); // clear this bit now that we're done reading it record.setHadGroupSummaryWhenUnclassified(false); } } }; } } Loading services/core/java/com/android/server/notification/NotificationManagerService.java +8 −2 Original line number Diff line number Diff line Loading @@ -109,6 +109,7 @@ import static android.os.UserHandle.USER_NULL; import static android.os.UserHandle.USER_SYSTEM; import static android.service.notification.Adjustment.KEY_SUMMARIZATION; import static android.service.notification.Adjustment.KEY_TYPE; import static android.service.notification.Adjustment.KEY_UNCLASSIFY; import static android.service.notification.Adjustment.TYPE_CONTENT_RECOMMENDATION; import static android.service.notification.Adjustment.TYPE_NEWS; import static android.service.notification.Adjustment.TYPE_PROMOTION; Loading Loading @@ -1950,9 +1951,14 @@ public class NotificationManagerService extends SystemService { String currChannelId = r.getChannel().getId(); boolean isClassified = NotificationChannel.SYSTEM_RESERVED_IDS.contains(currChannelId); if (originalChannel != null && !origChannelId.equals(currChannelId) && isClassified) { r.updateNotificationChannel(originalChannel); mGroupHelper.onNotificationUnbundled(r, final Bundle signals = new Bundle(); signals.putParcelable(KEY_UNCLASSIFY, originalChannel); Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals, "unclassify", r.getSbn().getUserId()); r.addAdjustment(adjustment); r.setHadGroupSummaryWhenUnclassified( GroupHelper.isOriginalGroupSummaryPresent(r, mSummaryByGroupKey)); mRankingHandler.requestSort(); } } Loading services/core/java/com/android/server/notification/NotificationRecord.java +26 −7 Original line number Diff line number Diff line Loading @@ -232,6 +232,10 @@ public final class NotificationRecord { private String mSummarization = null; // If this notification was unclassified, whether the notification's original group summary // was present at the time of unclassification. private boolean mHadGroupSummaryWhenUnclassified = false; public NotificationRecord(Context context, StatusBarNotification sbn, NotificationChannel channel) { this.sbn = sbn; Loading Loading @@ -807,14 +811,21 @@ public final class NotificationRecord { Adjustment.KEY_SENSITIVE_CONTENT, Boolean.toString(mSensitiveContent)); } if (android.service.notification.Flags.notificationClassification() && signals.containsKey(Adjustment.KEY_TYPE)) { if (android.service.notification.Flags.notificationClassification()) { if (signals.containsKey(Adjustment.KEY_TYPE)) { updateNotificationChannel(signals.getParcelable(Adjustment.KEY_TYPE, NotificationChannel.class)); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_TYPE, mChannel.getId()); } if (signals.containsKey(Adjustment.KEY_UNCLASSIFY)) { updateNotificationChannel(signals.getParcelable(Adjustment.KEY_UNCLASSIFY, NotificationChannel.class)); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_UNCLASSIFY, mChannel.getId()); } } if ((android.app.Flags.nmSummarizationUi() || android.app.Flags.nmSummarization()) && signals.containsKey(KEY_SUMMARIZATION)) { CharSequence summary = signals.getCharSequence(KEY_SUMMARIZATION, Loading Loading @@ -1675,6 +1686,14 @@ public final class NotificationRecord { mBundleType = bundleType; } public boolean hadGroupSummaryWhenUnclassified() { return mHadGroupSummaryWhenUnclassified; } public void setHadGroupSummaryWhenUnclassified(boolean exists) { mHadGroupSummaryWhenUnclassified = exists; } /** * Whether this notification is a conversation notification. */ Loading services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java +29 −1 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package com.android.server.notification; import static android.app.NotificationManager.IMPORTANCE_LOW; import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT; import static android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION; import static android.service.notification.Flags.FLAG_NOTIFICATION_FORCE_GROUPING; Loading Loading @@ -148,6 +147,35 @@ public class NotificationAdjustmentExtractorTest extends UiServiceTestCase { verify(groupHelper, times(1)).onChannelUpdated(r); } @Test @EnableFlags({FLAG_NOTIFICATION_CLASSIFICATION, FLAG_NOTIFICATION_FORCE_GROUPING}) public void testClassificationAdjustments_unclassifyTriggersUnbundling() { GroupHelper groupHelper = mock(GroupHelper.class); NotificationAdjustmentExtractor extractor = new NotificationAdjustmentExtractor(); extractor.setGroupHelper(groupHelper); NotificationRecord r = generateRecord(); r.setHadGroupSummaryWhenUnclassified(true); Bundle classificationAdj = new Bundle(); classificationAdj.putParcelable(Adjustment.KEY_UNCLASSIFY, mock(NotificationChannel.class)); Adjustment adjustment = new Adjustment("pkg", r.getKey(), classificationAdj, "", 0); r.addAdjustment(adjustment); RankingReconsideration regroupingTask = extractor.process(r); assertThat(regroupingTask).isNotNull(); regroupingTask.applyChangesLocked(r); verify(groupHelper, times(1)).onNotificationUnbundled(r, true); // make sure that the group summary boolean is passed through correctly r.setHadGroupSummaryWhenUnclassified(false); r.addAdjustment(adjustment); RankingReconsideration regroupingTask2 = extractor.process(r); assertThat(regroupingTask2).isNotNull(); regroupingTask2.applyChangesLocked(r); verify(groupHelper, times(1)).onNotificationUnbundled(r, false); } @Test @DisableFlags({FLAG_NOTIFICATION_CLASSIFICATION, FLAG_NOTIFICATION_FORCE_GROUPING}) public void testClassificationAdjustments_notTriggerRegrouping_flagsDisabled() { Loading Loading
core/java/android/service/notification/Adjustment.java +9 −1 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.StringDef; import android.annotation.SystemApi; import android.annotation.TestApi; import android.app.Notification; import android.os.Build; import android.os.Bundle; Loading Loading @@ -67,6 +66,7 @@ public final class Adjustment implements Parcelable { KEY_RANKING_SCORE, KEY_NOT_CONVERSATION, KEY_TYPE, KEY_UNCLASSIFY, KEY_SUMMARIZATION }) @Retention(RetentionPolicy.SOURCE) Loading Loading @@ -224,6 +224,14 @@ public final class Adjustment implements Parcelable { @FlaggedApi(Flags.FLAG_NOTIFICATION_CLASSIFICATION) public static final int TYPE_CONTENT_RECOMMENDATION = 4; /** * Data type: NotificationChannel; the presence of this key indicates that the notification * classification should be removed and the channel reverted to its original channel (provided). * @hide */ @FlaggedApi(Flags.FLAG_NOTIFICATION_CLASSIFICATION) public static final String KEY_UNCLASSIFY = "key_unclassify"; /** * Data type: CharSequence, a summarization of the text of the notification, or, if provided for * a group summary, a summarization of the text of all of the notificatrions in the group. Loading
services/core/java/com/android/server/notification/NotificationAdjustmentExtractor.java +13 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.notification; import static android.service.notification.Adjustment.KEY_TYPE; import static android.service.notification.Adjustment.KEY_UNCLASSIFY; import static android.service.notification.Flags.notificationForceGrouping; import android.content.Context; Loading @@ -41,12 +42,13 @@ public class NotificationAdjustmentExtractor implements NotificationSignalExtrac } final boolean hasAdjustedClassification = record.hasAdjustment(KEY_TYPE); final boolean removedClassification = record.hasAdjustment(KEY_UNCLASSIFY); record.applyAdjustments(); if (notificationForceGrouping() && android.service.notification.Flags.notificationClassification()) { // Classification adjustments trigger regrouping if (mGroupHelper != null && hasAdjustedClassification) { if (mGroupHelper != null && (hasAdjustedClassification || removedClassification)) { return new RankingReconsideration(record.getKey(), 0) { @Override public void work() { Loading @@ -54,8 +56,17 @@ public class NotificationAdjustmentExtractor implements NotificationSignalExtrac @Override public void applyChangesLocked(NotificationRecord record) { if (hasAdjustedClassification) { mGroupHelper.onChannelUpdated(record); } if (removedClassification) { mGroupHelper.onNotificationUnbundled(record, record.hadGroupSummaryWhenUnclassified()); // clear this bit now that we're done reading it record.setHadGroupSummaryWhenUnclassified(false); } } }; } } Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +8 −2 Original line number Diff line number Diff line Loading @@ -109,6 +109,7 @@ import static android.os.UserHandle.USER_NULL; import static android.os.UserHandle.USER_SYSTEM; import static android.service.notification.Adjustment.KEY_SUMMARIZATION; import static android.service.notification.Adjustment.KEY_TYPE; import static android.service.notification.Adjustment.KEY_UNCLASSIFY; import static android.service.notification.Adjustment.TYPE_CONTENT_RECOMMENDATION; import static android.service.notification.Adjustment.TYPE_NEWS; import static android.service.notification.Adjustment.TYPE_PROMOTION; Loading Loading @@ -1950,9 +1951,14 @@ public class NotificationManagerService extends SystemService { String currChannelId = r.getChannel().getId(); boolean isClassified = NotificationChannel.SYSTEM_RESERVED_IDS.contains(currChannelId); if (originalChannel != null && !origChannelId.equals(currChannelId) && isClassified) { r.updateNotificationChannel(originalChannel); mGroupHelper.onNotificationUnbundled(r, final Bundle signals = new Bundle(); signals.putParcelable(KEY_UNCLASSIFY, originalChannel); Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals, "unclassify", r.getSbn().getUserId()); r.addAdjustment(adjustment); r.setHadGroupSummaryWhenUnclassified( GroupHelper.isOriginalGroupSummaryPresent(r, mSummaryByGroupKey)); mRankingHandler.requestSort(); } } Loading
services/core/java/com/android/server/notification/NotificationRecord.java +26 −7 Original line number Diff line number Diff line Loading @@ -232,6 +232,10 @@ public final class NotificationRecord { private String mSummarization = null; // If this notification was unclassified, whether the notification's original group summary // was present at the time of unclassification. private boolean mHadGroupSummaryWhenUnclassified = false; public NotificationRecord(Context context, StatusBarNotification sbn, NotificationChannel channel) { this.sbn = sbn; Loading Loading @@ -807,14 +811,21 @@ public final class NotificationRecord { Adjustment.KEY_SENSITIVE_CONTENT, Boolean.toString(mSensitiveContent)); } if (android.service.notification.Flags.notificationClassification() && signals.containsKey(Adjustment.KEY_TYPE)) { if (android.service.notification.Flags.notificationClassification()) { if (signals.containsKey(Adjustment.KEY_TYPE)) { updateNotificationChannel(signals.getParcelable(Adjustment.KEY_TYPE, NotificationChannel.class)); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_TYPE, mChannel.getId()); } if (signals.containsKey(Adjustment.KEY_UNCLASSIFY)) { updateNotificationChannel(signals.getParcelable(Adjustment.KEY_UNCLASSIFY, NotificationChannel.class)); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_UNCLASSIFY, mChannel.getId()); } } if ((android.app.Flags.nmSummarizationUi() || android.app.Flags.nmSummarization()) && signals.containsKey(KEY_SUMMARIZATION)) { CharSequence summary = signals.getCharSequence(KEY_SUMMARIZATION, Loading Loading @@ -1675,6 +1686,14 @@ public final class NotificationRecord { mBundleType = bundleType; } public boolean hadGroupSummaryWhenUnclassified() { return mHadGroupSummaryWhenUnclassified; } public void setHadGroupSummaryWhenUnclassified(boolean exists) { mHadGroupSummaryWhenUnclassified = exists; } /** * Whether this notification is a conversation notification. */ Loading
services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java +29 −1 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package com.android.server.notification; import static android.app.NotificationManager.IMPORTANCE_LOW; import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT; import static android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION; import static android.service.notification.Flags.FLAG_NOTIFICATION_FORCE_GROUPING; Loading Loading @@ -148,6 +147,35 @@ public class NotificationAdjustmentExtractorTest extends UiServiceTestCase { verify(groupHelper, times(1)).onChannelUpdated(r); } @Test @EnableFlags({FLAG_NOTIFICATION_CLASSIFICATION, FLAG_NOTIFICATION_FORCE_GROUPING}) public void testClassificationAdjustments_unclassifyTriggersUnbundling() { GroupHelper groupHelper = mock(GroupHelper.class); NotificationAdjustmentExtractor extractor = new NotificationAdjustmentExtractor(); extractor.setGroupHelper(groupHelper); NotificationRecord r = generateRecord(); r.setHadGroupSummaryWhenUnclassified(true); Bundle classificationAdj = new Bundle(); classificationAdj.putParcelable(Adjustment.KEY_UNCLASSIFY, mock(NotificationChannel.class)); Adjustment adjustment = new Adjustment("pkg", r.getKey(), classificationAdj, "", 0); r.addAdjustment(adjustment); RankingReconsideration regroupingTask = extractor.process(r); assertThat(regroupingTask).isNotNull(); regroupingTask.applyChangesLocked(r); verify(groupHelper, times(1)).onNotificationUnbundled(r, true); // make sure that the group summary boolean is passed through correctly r.setHadGroupSummaryWhenUnclassified(false); r.addAdjustment(adjustment); RankingReconsideration regroupingTask2 = extractor.process(r); assertThat(regroupingTask2).isNotNull(); regroupingTask2.applyChangesLocked(r); verify(groupHelper, times(1)).onNotificationUnbundled(r, false); } @Test @DisableFlags({FLAG_NOTIFICATION_CLASSIFICATION, FLAG_NOTIFICATION_FORCE_GROUPING}) public void testClassificationAdjustments_notTriggerRegrouping_flagsDisabled() { Loading