summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> 2024-10-04 14:24:50 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-10-04 14:24:50 +0000
commitf5534e84fb78cbd09f7ae494f0cc667840c183dd (patch)
tree656f728a69d03d1e60f6cbd7ecee913f56f6f72b
parent6481a94c18e4ae9f8442dec2b95f49556e3a2193 (diff)
parentbf59facaa34279ff1122f6e505d1bc6c8144c950 (diff)
Merge "Schedule regrouping if classification adjustment is after notification polite_notifications_attn_update" into main
-rw-r--r--services/core/java/com/android/server/notification/GroupHelper.java59
-rw-r--r--services/core/java/com/android/server/notification/NotificationAdjustmentExtractor.java28
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java43
-rw-r--r--services/core/java/com/android/server/notification/NotificationSignalExtractor.java5
-rw-r--r--services/core/java/com/android/server/notification/RankingHelper.java4
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java55
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java3
7 files changed, 160 insertions, 37 deletions
diff --git a/services/core/java/com/android/server/notification/GroupHelper.java b/services/core/java/com/android/server/notification/GroupHelper.java
index e8d14cbde516..9b9be4cd8f3f 100644
--- a/services/core/java/com/android/server/notification/GroupHelper.java
+++ b/services/core/java/com/android/server/notification/GroupHelper.java
@@ -832,8 +832,9 @@ public class GroupHelper {
FullyQualifiedGroupKey newGroup) { }
/**
- * Called when a notification channel is updated, so that this helper can adjust
- * the aggregate groups by moving children if their section has changed.
+ * Called when a notification channel is updated (channel attributes have changed),
+ * so that this helper can adjust the aggregate groups by moving children
+ * if their section has changed.
* see {@link #onNotificationPostedWithDelay(NotificationRecord, List, Map)}
* @param userId the userId of the channel
* @param pkgName the channel's package
@@ -853,24 +854,48 @@ public class GroupHelper {
}
}
- // The list of notification operations required after the channel update
- final ArrayList<NotificationMoveOp> notificationsToMove = new ArrayList<>();
+ regroupNotifications(userId, pkgName, notificationsToCheck);
+ }
+ }
- // Check any already auto-grouped notifications that may need to be re-grouped
- // after the channel update
- notificationsToMove.addAll(
- getAutogroupedNotificationsMoveOps(userId, pkgName,
- notificationsToCheck));
+ /**
+ * Called when an individuial notification's channel is updated (moved to a new channel),
+ * so that this helper can adjust the aggregate groups by moving children
+ * if their section has changed.
+ * see {@link #onNotificationPostedWithDelay(NotificationRecord, List, Map)}
+ *
+ * @param record the notification which had its channel updated
+ */
+ @FlaggedApi(android.service.notification.Flags.FLAG_NOTIFICATION_FORCE_GROUPING)
+ public void onChannelUpdated(final NotificationRecord record) {
+ synchronized (mAggregatedNotifications) {
+ ArrayMap<String, NotificationRecord> notificationsToCheck = new ArrayMap<>();
+ notificationsToCheck.put(record.getKey(), record);
+ regroupNotifications(record.getUserId(), record.getSbn().getPackageName(),
+ notificationsToCheck);
+ }
+ }
+
+ @GuardedBy("mAggregatedNotifications")
+ private void regroupNotifications(int userId, String pkgName,
+ ArrayMap<String, NotificationRecord> notificationsToCheck) {
+ // The list of notification operations required after the channel update
+ final ArrayList<NotificationMoveOp> notificationsToMove = new ArrayList<>();
- // Check any ungrouped notifications that may need to be auto-grouped
- // after the channel update
- notificationsToMove.addAll(
- getUngroupedNotificationsMoveOps(userId, pkgName, notificationsToCheck));
+ // Check any already auto-grouped notifications that may need to be re-grouped
+ // after the channel update
+ notificationsToMove.addAll(
+ getAutogroupedNotificationsMoveOps(userId, pkgName,
+ notificationsToCheck));
- // Batch move to new section
- if (!notificationsToMove.isEmpty()) {
- moveNotificationsToNewSection(userId, pkgName, notificationsToMove);
- }
+ // Check any ungrouped notifications that may need to be auto-grouped
+ // after the channel update
+ notificationsToMove.addAll(
+ getUngroupedNotificationsMoveOps(userId, pkgName, notificationsToCheck));
+
+ // Batch move to new section
+ if (!notificationsToMove.isEmpty()) {
+ moveNotificationsToNewSection(userId, pkgName, notificationsToMove);
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationAdjustmentExtractor.java b/services/core/java/com/android/server/notification/NotificationAdjustmentExtractor.java
index 97bbc2338f47..2dd4f8392fdf 100644
--- a/services/core/java/com/android/server/notification/NotificationAdjustmentExtractor.java
+++ b/services/core/java/com/android/server/notification/NotificationAdjustmentExtractor.java
@@ -15,6 +15,9 @@
*/
package com.android.server.notification;
+import static android.service.notification.Adjustment.KEY_TYPE;
+import static android.service.notification.Flags.notificationForceGrouping;
+
import android.content.Context;
import android.util.Slog;
@@ -24,6 +27,7 @@ import android.util.Slog;
public class NotificationAdjustmentExtractor implements NotificationSignalExtractor {
private static final String TAG = "AdjustmentExtractor";
private static final boolean DBG = false;
+ private GroupHelper mGroupHelper;
public void initialize(Context ctx, NotificationUsageStats usageStats) {
@@ -35,8 +39,27 @@ public class NotificationAdjustmentExtractor implements NotificationSignalExtrac
if (DBG) Slog.d(TAG, "skipping empty notification");
return null;
}
+
+ final boolean hasAdjustedClassification = record.hasAdjustment(KEY_TYPE);
record.applyAdjustments();
+ if (notificationForceGrouping()
+ && android.service.notification.Flags.notificationClassification()) {
+ // Classification adjustments trigger regrouping
+ if (mGroupHelper != null && hasAdjustedClassification) {
+ return new RankingReconsideration(record.getKey(), 0) {
+ @Override
+ public void work() {
+ }
+
+ @Override
+ public void applyChangesLocked(NotificationRecord record) {
+ mGroupHelper.onChannelUpdated(record);
+ }
+ };
+ }
+ }
+
return null;
}
@@ -49,4 +72,9 @@ public class NotificationAdjustmentExtractor implements NotificationSignalExtrac
public void setZenHelper(ZenModeHelper helper) {
}
+
+ @Override
+ public void setGroupHelper(GroupHelper groupHelper) {
+ mGroupHelper = groupHelper;
+ }
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 56e0a8929772..99e66a222370 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -519,6 +519,7 @@ public class NotificationManagerService extends SystemService {
private static final long DELAY_FORCE_REGROUP_TIME = 3000;
+
private static final String ACTION_NOTIFICATION_TIMEOUT =
NotificationManagerService.class.getSimpleName() + ".TIMEOUT";
private static final int REQUEST_CODE_TIMEOUT = 1;
@@ -2583,7 +2584,7 @@ public class NotificationManagerService extends SystemService {
mShowReviewPermissionsNotification,
Clock.systemUTC());
mRankingHelper = new RankingHelper(getContext(), mRankingHandler, mPreferencesHelper,
- mZenModeHelper, mUsageStats, extractorNames, mPlatformCompat);
+ mZenModeHelper, mUsageStats, extractorNames, mPlatformCompat, groupHelper);
mSnoozeHelper = snoozeHelper;
mGroupHelper = groupHelper;
mHistoryManager = historyManager;
@@ -6871,22 +6872,9 @@ public class NotificationManagerService extends SystemService {
}
if (android.service.notification.Flags.notificationClassification()
&& adjustments.containsKey(KEY_TYPE)) {
- NotificationChannel newChannel = null;
- int type = adjustments.getInt(KEY_TYPE);
- if (TYPE_NEWS == type) {
- newChannel = mPreferencesHelper.getNotificationChannel(
- r.getSbn().getPackageName(), r.getUid(), NEWS_ID, false);
- } else if (TYPE_PROMOTION == type) {
- newChannel = mPreferencesHelper.getNotificationChannel(
- r.getSbn().getPackageName(), r.getUid(), PROMOTIONS_ID, false);
- } else if (TYPE_SOCIAL_MEDIA == type) {
- newChannel = mPreferencesHelper.getNotificationChannel(
- r.getSbn().getPackageName(), r.getUid(), SOCIAL_MEDIA_ID, false);
- } else if (TYPE_CONTENT_RECOMMENDATION == type) {
- newChannel = mPreferencesHelper.getNotificationChannel(
- r.getSbn().getPackageName(), r.getUid(), RECS_ID, false);
- }
- if (newChannel == null) {
+ final NotificationChannel newChannel = getClassificationChannelLocked(r,
+ adjustments);
+ if (newChannel == null || newChannel.getId().equals(r.getChannel().getId())) {
adjustments.remove(KEY_TYPE);
} else {
// swap app provided type with the real thing
@@ -6902,6 +6890,27 @@ public class NotificationManagerService extends SystemService {
}
}
+ @GuardedBy("mNotificationLock")
+ @Nullable
+ private NotificationChannel getClassificationChannelLocked(NotificationRecord r,
+ Bundle adjustments) {
+ int type = adjustments.getInt(KEY_TYPE);
+ if (TYPE_NEWS == type) {
+ return mPreferencesHelper.getNotificationChannel(
+ r.getSbn().getPackageName(), r.getUid(), NEWS_ID, false);
+ } else if (TYPE_PROMOTION == type) {
+ return mPreferencesHelper.getNotificationChannel(
+ r.getSbn().getPackageName(), r.getUid(), PROMOTIONS_ID, false);
+ } else if (TYPE_SOCIAL_MEDIA == type) {
+ return mPreferencesHelper.getNotificationChannel(
+ r.getSbn().getPackageName(), r.getUid(), SOCIAL_MEDIA_ID, false);
+ } else if (TYPE_CONTENT_RECOMMENDATION == type) {
+ return mPreferencesHelper.getNotificationChannel(
+ r.getSbn().getPackageName(), r.getUid(), RECS_ID, false);
+ }
+ return null;
+ }
+
@SuppressWarnings("GuardedBy")
@GuardedBy("mNotificationLock")
void addAutogroupKeyLocked(String key, String groupName, boolean requestSort) {
diff --git a/services/core/java/com/android/server/notification/NotificationSignalExtractor.java b/services/core/java/com/android/server/notification/NotificationSignalExtractor.java
index f0358d1e1d8c..be34beeb1236 100644
--- a/services/core/java/com/android/server/notification/NotificationSignalExtractor.java
+++ b/services/core/java/com/android/server/notification/NotificationSignalExtractor.java
@@ -55,4 +55,9 @@ public interface NotificationSignalExtractor {
void setZenHelper(ZenModeHelper helper);
default void setCompatChangeLogger(IPlatformCompat platformCompat){};
+
+ /**
+ * @param groupHelper Helper for auto-grouping notifications
+ */
+ default void setGroupHelper(GroupHelper groupHelper){};
}
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 03dd9351efc7..f06d6405b3c2 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -23,7 +23,6 @@ import static android.app.NotificationManager.IMPORTANCE_MIN;
import static android.text.TextUtils.formatSimple;
import android.annotation.NonNull;
-import android.app.NotificationManager;
import android.content.Context;
import android.service.notification.RankingHelperProto;
import android.util.ArrayMap;
@@ -61,7 +60,7 @@ public class RankingHelper {
})
public RankingHelper(Context context, RankingHandler rankingHandler, RankingConfig config,
ZenModeHelper zenHelper, NotificationUsageStats usageStats, String[] extractorNames,
- IPlatformCompat platformCompat) {
+ IPlatformCompat platformCompat, GroupHelper groupHelper) {
mContext = context;
mRankingHandler = rankingHandler;
if (sortSectionByTime()) {
@@ -80,6 +79,7 @@ public class RankingHelper {
extractor.initialize(mContext, usageStats);
extractor.setConfig(config);
extractor.setZenHelper(zenHelper);
+ extractor.setGroupHelper(groupHelper);
if (restrictAudioAttributesAlarm() || restrictAudioAttributesMedia()
|| restrictAudioAttributesCall()) {
extractor.setCompatChangeLogger(platformCompat);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java
index 18ca09be235c..bf0586ceb32d 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java
@@ -18,11 +18,21 @@ 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;
+
+import static com.google.common.truth.Truth.assertThat;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.PendingIntent;
@@ -30,12 +40,16 @@ import android.content.Intent;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.os.UserHandle;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.service.notification.Adjustment;
import android.service.notification.SnoozeCriterion;
import android.service.notification.StatusBarNotification;
import com.android.server.UiServiceTestCase;
+import org.junit.Rule;
import org.junit.Test;
import java.util.ArrayList;
@@ -43,6 +57,9 @@ import java.util.Objects;
public class NotificationAdjustmentExtractorTest extends UiServiceTestCase {
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT);
+
@Test
public void testExtractsAdjustment() {
NotificationAdjustmentExtractor extractor = new NotificationAdjustmentExtractor();
@@ -111,6 +128,44 @@ public class NotificationAdjustmentExtractorTest extends UiServiceTestCase {
assertEquals(snoozeCriteria, r.getSnoozeCriteria());
}
+ @Test
+ @EnableFlags({FLAG_NOTIFICATION_CLASSIFICATION, FLAG_NOTIFICATION_FORCE_GROUPING})
+ public void testClassificationAdjustments_triggerRegrouping() {
+ GroupHelper groupHelper = mock(GroupHelper.class);
+ NotificationAdjustmentExtractor extractor = new NotificationAdjustmentExtractor();
+ extractor.setGroupHelper(groupHelper);
+
+ NotificationRecord r = generateRecord();
+
+ Bundle classificationAdj = new Bundle();
+ classificationAdj.putParcelable(Adjustment.KEY_TYPE, 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)).onChannelUpdated(r);
+ }
+
+ @Test
+ @DisableFlags({FLAG_NOTIFICATION_CLASSIFICATION, FLAG_NOTIFICATION_FORCE_GROUPING})
+ public void testClassificationAdjustments_notTriggerRegrouping_flagsDisabled() {
+ GroupHelper groupHelper = mock(GroupHelper.class);
+ NotificationAdjustmentExtractor extractor = new NotificationAdjustmentExtractor();
+ extractor.setGroupHelper(groupHelper);
+
+ NotificationRecord r = generateRecord();
+
+ Bundle classificationAdj = new Bundle();
+ classificationAdj.putParcelable(Adjustment.KEY_TYPE, mock(NotificationChannel.class));
+ Adjustment adjustment = new Adjustment("pkg", r.getKey(), classificationAdj, "", 0);
+ r.addAdjustment(adjustment);
+
+ RankingReconsideration regroupingTask = extractor.process(r);
+ assertThat(regroupingTask).isNull();
+ }
+
private NotificationRecord generateRecord() {
NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_LOW);
final Notification.Builder builder = new Notification.Builder(getContext())
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
index 9a6e81865947..5d4382a6331c 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
@@ -92,6 +92,7 @@ public class RankingHelperTest extends UiServiceTestCase {
@Mock ZenModeHelper mMockZenModeHelper;
@Mock RankingConfig mConfig;
@Mock Vibrator mVibrator;
+ @Mock GroupHelper mGroupHelper;
private NotificationManager.Policy mTestNotificationPolicy;
private Notification mNotiGroupGSortA;
@@ -157,7 +158,7 @@ public class RankingHelperTest extends UiServiceTestCase {
when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
mHelper = new RankingHelper(getContext(), mHandler, mConfig, mMockZenModeHelper,
mUsageStats, new String[] {ImportanceExtractor.class.getName()},
- mock(IPlatformCompat.class));
+ mock(IPlatformCompat.class), mGroupHelper);
mNotiGroupGSortA = new Notification.Builder(mContext, TEST_CHANNEL_ID)
.setContentTitle("A")