diff options
| author | 2024-09-17 20:15:03 +0200 | |
|---|---|---|
| committer | 2024-09-27 18:51:02 +0000 | |
| commit | 216db747d1171734494ef1040c3670f9d28ad3b4 (patch) | |
| tree | b5e4ac2bc20f465a527e5f1765749be31aa93b51 | |
| parent | 28cafbcb2c87c7a40bdbe98ae8dc009815fc3baf (diff) | |
Skip playing notification sound or vibration when cooldown is muted
Do no play the notification sound or vibration at 0 volume, but skip playback.
However log the playback as usual and behave as if playback happened.
Flag: com.android.server.notification.polite_notifications
Test: atest NotificationAttentionHelperTest
Bug: 364349386
Change-Id: I4cba12ff4fd31e9da466aaca6ede8c633688cc2c
3 files changed, 215 insertions, 69 deletions
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags index 5b271a3730fc..7474df2a91ca 100644 --- a/services/core/java/com/android/server/EventLogTags.logtags +++ b/services/core/java/com/android/server/EventLogTags.logtags @@ -87,7 +87,7 @@ option java_package com.android.server # replaces 27510 with a row per notification 27531 notification_visibility (key|3),(visibile|1),(lifespan|1),(freshness|1),(exposure|1),(rank|1) # a notification emited noise, vibration, or light -27532 notification_alert (key|3),(buzz|1),(beep|1),(blink|1),(politeness|1) +27532 notification_alert (key|3),(buzz|1),(beep|1),(blink|1),(politeness|1),(mute_reason|1) # a notification was added to a autogroup 27533 notification_autogrouped (key|3) # notification was removed from an autogroup diff --git a/services/core/java/com/android/server/notification/NotificationAttentionHelper.java b/services/core/java/com/android/server/notification/NotificationAttentionHelper.java index abb21323f7f0..06f419a785f9 100644 --- a/services/core/java/com/android/server/notification/NotificationAttentionHelper.java +++ b/services/core/java/com/android/server/notification/NotificationAttentionHelper.java @@ -118,6 +118,37 @@ public final class NotificationAttentionHelper { Intent.ACTION_MANAGED_PROFILE_AVAILABLE, new Pair<>(Intent.EXTRA_QUIET_MODE, false) ); + // Bits 1, 2, 3, 4 are already taken by: beep|buzz|blink|cooldown + static final int MUTE_REASON_NOT_MUTED = 0; + static final int MUTE_REASON_NOT_AUDIBLE = 1 << 5; + static final int MUTE_REASON_SILENT_UPDATE = 1 << 6; + static final int MUTE_REASON_POST_SILENTLY = 1 << 7; + static final int MUTE_REASON_LISTENER_HINT = 1 << 8; + static final int MUTE_REASON_DND = 1 << 9; + static final int MUTE_REASON_GROUP_ALERT = 1 << 10; + static final int MUTE_REASON_FLAG_SILENT = 1 << 11; + static final int MUTE_REASON_RATE_LIMIT = 1 << 12; + static final int MUTE_REASON_OTHER_INSISTENT_PLAYING = 1 << 13; + static final int MUTE_REASON_SUPPRESSED_BUBBLE = 1 << 14; + static final int MUTE_REASON_COOLDOWN = 1 << 15; + + @IntDef(prefix = { "MUTE_REASON_" }, value = { + MUTE_REASON_NOT_MUTED, + MUTE_REASON_NOT_AUDIBLE, + MUTE_REASON_SILENT_UPDATE, + MUTE_REASON_POST_SILENTLY, + MUTE_REASON_LISTENER_HINT, + MUTE_REASON_DND, + MUTE_REASON_GROUP_ALERT, + MUTE_REASON_FLAG_SILENT, + MUTE_REASON_RATE_LIMIT, + MUTE_REASON_OTHER_INSISTENT_PLAYING, + MUTE_REASON_SUPPRESSED_BUBBLE, + MUTE_REASON_COOLDOWN, + }) + @Retention(RetentionPolicy.SOURCE) + @interface MuteReason {} + private final Context mContext; private final PackageManager mPackageManager; private final TelephonyManager mTelephonyManager; @@ -388,6 +419,7 @@ public final class NotificationAttentionHelper { boolean buzz = false; boolean beep = false; boolean blink = false; + @MuteReason int shouldMuteReason = MUTE_REASON_NOT_MUTED; final String key = record.getKey(); @@ -395,10 +427,6 @@ public final class NotificationAttentionHelper { Log.d(TAG, "buzzBeepBlinkLocked " + record); } - if (isPoliteNotificationFeatureEnabled(record)) { - mStrategy.onNotificationPosted(record); - } - // Should this notification make noise, vibe, or use the LED? final boolean aboveThreshold = mIsAutomotive @@ -443,7 +471,8 @@ public final class NotificationAttentionHelper { boolean vibrateOnly = hasValidVibrate && mNotificationCooldownVibrateUnlocked && mUserPresent; boolean hasAudibleAlert = hasValidSound || hasValidVibrate; - if (hasAudibleAlert && !shouldMuteNotificationLocked(record, signals)) { + shouldMuteReason = shouldMuteNotificationLocked(record, signals, hasAudibleAlert); + if (shouldMuteReason == MUTE_REASON_NOT_MUTED) { if (!sentAccessibilityEvent) { sendAccessibilityEvent(record); sentAccessibilityEvent = true; @@ -541,15 +570,17 @@ public final class NotificationAttentionHelper { } } final int buzzBeepBlinkLoggingCode = - (buzz ? 1 : 0) | (beep ? 2 : 0) | (blink ? 4 : 0) | getPoliteBit(record); + (buzz ? 1 : 0) | (beep ? 2 : 0) | (blink ? 4 : 0) + | getPoliteBit(record) | shouldMuteReason; if (buzzBeepBlinkLoggingCode > 0) { MetricsLogger.action(record.getLogMaker() .setCategory(MetricsEvent.NOTIFICATION_ALERT) .setType(MetricsEvent.TYPE_OPEN) .setSubtype(buzzBeepBlinkLoggingCode)); EventLogTags.writeNotificationAlert(key, buzz ? 1 : 0, beep ? 1 : 0, blink ? 1 : 0, - getPolitenessState(record)); + getPolitenessState(record), shouldMuteReason); } + if (Flags.politeNotifications()) { // Update last alert time if (buzz || beep) { @@ -594,41 +625,46 @@ public final class NotificationAttentionHelper { mNMP.getNotificationByKey(mVibrateNotificationKey)); } - boolean shouldMuteNotificationLocked(final NotificationRecord record, final Signals signals) { + @MuteReason int shouldMuteNotificationLocked(final NotificationRecord record, + final Signals signals, boolean hasAudibleAlert) { + // Suppressed because no audible alert + if (!hasAudibleAlert) { + return MUTE_REASON_NOT_AUDIBLE; + } // Suppressed because it's a silent update final Notification notification = record.getNotification(); if (record.isUpdate && (notification.flags & FLAG_ONLY_ALERT_ONCE) != 0) { - return true; + return MUTE_REASON_SILENT_UPDATE; } // Suppressed because a user manually unsnoozed something (or similar) if (record.shouldPostSilently()) { - return true; + return MUTE_REASON_POST_SILENTLY; } // muted by listener final String disableEffects = disableNotificationEffects(record, signals.listenerHints); if (disableEffects != null) { ZenLog.traceDisableEffects(record, disableEffects); - return true; + return MUTE_REASON_LISTENER_HINT; } // suppressed due to DND if (record.isIntercepted()) { - return true; + return MUTE_REASON_DND; } // Suppressed because another notification in its group handles alerting if (record.getSbn().isGroup()) { if (notification.suppressAlertingDueToGrouping()) { - return true; + return MUTE_REASON_GROUP_ALERT; } } // Suppressed because notification was explicitly flagged as silent if (android.service.notification.Flags.notificationSilentFlag()) { if (notification.isSilent()) { - return true; + return MUTE_REASON_FLAG_SILENT; } } @@ -636,12 +672,12 @@ public final class NotificationAttentionHelper { final String pkg = record.getSbn().getPackageName(); if (mUsageStats.isAlertRateLimited(pkg)) { Slog.e(TAG, "Muting recently noisy " + record.getKey()); - return true; + return MUTE_REASON_RATE_LIMIT; } // A different looping ringtone, such as an incoming call is playing if (isCurrentlyInsistent() && !isInsistentUpdate(record)) { - return true; + return MUTE_REASON_OTHER_INSISTENT_PLAYING; } // Suppressed since it's a non-interruptive update to a bubble-suppressed notification @@ -650,11 +686,23 @@ public final class NotificationAttentionHelper { if (record.isUpdate && !record.isInterruptive() && isBubbleOrOverflowed && record.getNotification().getBubbleMetadata() != null) { if (record.getNotification().getBubbleMetadata().isNotificationSuppressed()) { - return true; + return MUTE_REASON_SUPPRESSED_BUBBLE; } } - return false; + if (isPoliteNotificationFeatureEnabled(record)) { + // Notify the politeness strategy that an alerting notification is posted + if (!isInsistentUpdate(record)) { + mStrategy.onNotificationPosted(record); + } + + // Suppress if politeness is muted and it's not an update for insistent + if (getPolitenessState(record) == PolitenessStrategy.POLITE_STATE_MUTED) { + return MUTE_REASON_COOLDOWN; + } + } + + return MUTE_REASON_NOT_MUTED; } private boolean isLoopingRingtoneNotification(final NotificationRecord playingRecord) { @@ -1201,12 +1249,6 @@ public final class NotificationAttentionHelper { mApplyPerPackage = applyPerPackage; } - boolean shouldIgnoreNotification(final NotificationRecord record) { - // Ignore auto-group summaries => don't count them as app-posted notifications - // for the cooldown budget - return (record.getSbn().isGroup() && GroupHelper.isAggregatedGroup(record)); - } - /** * Get the key that determines the grouping for the cooldown behavior. * @@ -1358,10 +1400,6 @@ public final class NotificationAttentionHelper { @Override public void onNotificationPosted(final NotificationRecord record) { - if (shouldIgnoreNotification(record)) { - return; - } - long timeSinceLastNotif = System.currentTimeMillis() - getLastNotificationUpdateTimeMs(record); @@ -1434,10 +1472,6 @@ public final class NotificationAttentionHelper { @Override void onNotificationPosted(NotificationRecord record) { if (isAvalancheActive()) { - if (shouldIgnoreNotification(record)) { - return; - } - long timeSinceLastNotif = System.currentTimeMillis() - getLastNotificationUpdateTimeMs(record); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java index 62e5b9a3dccc..45cd5719cd86 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java @@ -31,6 +31,12 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.media.AudioAttributes.USAGE_NOTIFICATION; import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE; +import static com.android.server.notification.NotificationAttentionHelper.MUTE_REASON_COOLDOWN; +import static com.android.server.notification.NotificationAttentionHelper.MUTE_REASON_FLAG_SILENT; +import static com.android.server.notification.NotificationAttentionHelper.MUTE_REASON_GROUP_ALERT; +import static com.android.server.notification.NotificationAttentionHelper.MUTE_REASON_NOT_MUTED; +import static com.android.server.notification.NotificationAttentionHelper.MUTE_REASON_OTHER_INSISTENT_PLAYING; + import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; @@ -106,6 +112,7 @@ import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.Notificat import com.android.internal.config.sysui.TestableFlagResolver; import com.android.internal.logging.InstanceIdSequence; import com.android.internal.logging.InstanceIdSequenceFake; +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.util.IntPair; import com.android.server.UiServiceTestCase; import com.android.server.lights.LightsManager; @@ -1276,7 +1283,8 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { verifyNeverBeep(); assertFalse(r.isInterruptive()); assertEquals(-1, r.getLastAudiblyAlertedMs()); - assertTrue(mAttentionHelper.shouldMuteNotificationLocked(r, DEFAULT_SIGNALS)); + assertThat(mAttentionHelper.shouldMuteNotificationLocked(r, DEFAULT_SIGNALS, + true)).isEqualTo(MUTE_REASON_FLAG_SILENT); } @Test @@ -1295,7 +1303,8 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { verifyNeverBeep(); assertFalse(r.isInterruptive()); assertEquals(-1, r.getLastAudiblyAlertedMs()); - assertTrue(mAttentionHelper.shouldMuteNotificationLocked(r, DEFAULT_SIGNALS)); + assertThat(mAttentionHelper.shouldMuteNotificationLocked(r, DEFAULT_SIGNALS, + true)).isEqualTo(MUTE_REASON_GROUP_ALERT); } @Test @@ -1861,7 +1870,9 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { verifyBeepLooped(); NotificationRecord interrupter = getBeepyOtherNotification(); - assertTrue(mAttentionHelper.shouldMuteNotificationLocked(interrupter, DEFAULT_SIGNALS)); + assertThat( + mAttentionHelper.shouldMuteNotificationLocked(interrupter, DEFAULT_SIGNALS, + true)).isEqualTo(MUTE_REASON_OTHER_INSISTENT_PLAYING); mAttentionHelper.buzzBeepBlinkLocked(interrupter, DEFAULT_SIGNALS); verifyBeep(1); @@ -1879,16 +1890,16 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { ringtoneChannel.enableVibration(true); NotificationRecord ringtoneNotification = getCallRecord(1, ringtoneChannel, true); mService.addNotification(ringtoneNotification); - assertFalse(mAttentionHelper.shouldMuteNotificationLocked(ringtoneNotification, - DEFAULT_SIGNALS)); + assertThat(mAttentionHelper.shouldMuteNotificationLocked(ringtoneNotification, + DEFAULT_SIGNALS, true)).isEqualTo(MUTE_REASON_NOT_MUTED); mAttentionHelper.buzzBeepBlinkLocked(ringtoneNotification, DEFAULT_SIGNALS); verifyBeepLooped(); verifyDelayedVibrateLooped(); Mockito.reset(mVibrator); Mockito.reset(mRingtonePlayer); - assertFalse(mAttentionHelper.shouldMuteNotificationLocked(ringtoneNotification, - DEFAULT_SIGNALS)); + assertThat(mAttentionHelper.shouldMuteNotificationLocked(ringtoneNotification, + DEFAULT_SIGNALS, true)).isEqualTo(MUTE_REASON_NOT_MUTED); mAttentionHelper.buzzBeepBlinkLocked(ringtoneNotification, DEFAULT_SIGNALS); // beep wasn't reset @@ -1907,8 +1918,8 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { ringtoneChannel.enableVibration(true); NotificationRecord ringtoneNotification = getCallRecord(1, ringtoneChannel, true); mService.addNotification(ringtoneNotification); - assertFalse(mAttentionHelper.shouldMuteNotificationLocked(ringtoneNotification, - DEFAULT_SIGNALS)); + assertThat(mAttentionHelper.shouldMuteNotificationLocked(ringtoneNotification, + DEFAULT_SIGNALS, true)).isEqualTo(MUTE_REASON_NOT_MUTED); mAttentionHelper.buzzBeepBlinkLocked(ringtoneNotification, DEFAULT_SIGNALS); verifyBeepLooped(); verifyDelayedVibrateLooped(); @@ -1930,8 +1941,8 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { ringtoneChannel.enableVibration(true); NotificationRecord ringtoneNotification = getCallRecord(1, ringtoneChannel, true); mService.addNotification(ringtoneNotification); - assertFalse(mAttentionHelper.shouldMuteNotificationLocked(ringtoneNotification, - DEFAULT_SIGNALS)); + assertThat(mAttentionHelper.shouldMuteNotificationLocked(ringtoneNotification, + DEFAULT_SIGNALS, true)).isEqualTo(MUTE_REASON_NOT_MUTED); mAttentionHelper.buzzBeepBlinkLocked(ringtoneNotification, DEFAULT_SIGNALS); verifyBeepLooped(); verifyNeverVibrate(); @@ -1951,14 +1962,15 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION_RINGTONE).build()); ringtoneChannel.enableVibration(true); NotificationRecord ringtoneNotification = getCallRecord(1, ringtoneChannel, true); - assertFalse(mAttentionHelper.shouldMuteNotificationLocked(ringtoneNotification, - DEFAULT_SIGNALS)); + assertThat(mAttentionHelper.shouldMuteNotificationLocked(ringtoneNotification, + DEFAULT_SIGNALS, true)).isEqualTo(MUTE_REASON_NOT_MUTED); mAttentionHelper.buzzBeepBlinkLocked(ringtoneNotification, DEFAULT_SIGNALS); verifyVibrateLooped(); NotificationRecord interrupter = getBuzzyOtherNotification(); - assertTrue(mAttentionHelper.shouldMuteNotificationLocked(interrupter, DEFAULT_SIGNALS)); + assertThat(mAttentionHelper.shouldMuteNotificationLocked(interrupter, + DEFAULT_SIGNALS, true)).isEqualTo(MUTE_REASON_OTHER_INSISTENT_PLAYING); mAttentionHelper.buzzBeepBlinkLocked(interrupter, DEFAULT_SIGNALS); verifyVibrate(1); @@ -2260,10 +2272,13 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { // 2nd update should beep at 0% volume Mockito.reset(mRingtonePlayer); - mAttentionHelper.buzzBeepBlinkLocked(r, DEFAULT_SIGNALS); - verifyBeepVolume(0.0f); + int buzzBeepBlink = mAttentionHelper.buzzBeepBlinkLocked(r, DEFAULT_SIGNALS); + verifyNeverBeep(); + assertThat(buzzBeepBlink).isEqualTo(MetricsEvent.ALERT_MUTED | MUTE_REASON_COOLDOWN); + assertThat(mAttentionHelper.shouldMuteNotificationLocked(r, DEFAULT_SIGNALS, true)) + .isEqualTo(MUTE_REASON_COOLDOWN); - verify(mAccessibilityService, times(3)).sendAccessibilityEvent(any(), anyInt()); + verify(mAccessibilityService, times(2)).sendAccessibilityEvent(any(), anyInt()); assertEquals(-1, r.getLastAudiblyAlertedMs()); } @@ -2305,8 +2320,9 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { // 2nd update should beep at 0% volume Mockito.reset(mRingtonePlayer); - mAttentionHelper.buzzBeepBlinkLocked(r3, DEFAULT_SIGNALS); - verifyBeepVolume(0.0f); + int buzzBeepBlink = mAttentionHelper.buzzBeepBlinkLocked(r3, DEFAULT_SIGNALS); + verifyNeverBeep(); + assertThat(buzzBeepBlink).isEqualTo(MetricsEvent.ALERT_MUTED | MUTE_REASON_COOLDOWN); verify(mAccessibilityService, times(3)).sendAccessibilityEvent(any(), anyInt()); assertEquals(-1, r3.getLastAudiblyAlertedMs()); @@ -2381,9 +2397,10 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { false, null, Notification.GROUP_ALERT_ALL, false, mUser, "anotherPkg"); // update should beep at 0% volume - mAttentionHelper.buzzBeepBlinkLocked(r2, DEFAULT_SIGNALS); + int buzzBeepBlink = mAttentionHelper.buzzBeepBlinkLocked(r2, DEFAULT_SIGNALS); assertEquals(-1, r2.getLastAudiblyAlertedMs()); - verifyBeepVolume(0.0f); + verifyNeverBeep(); + assertThat(buzzBeepBlink).isEqualTo(MetricsEvent.ALERT_MUTED | MUTE_REASON_COOLDOWN); // Use different package for next notifications NotificationRecord r3 = getNotificationRecord(mId, false /* insistent */, false /* once */, @@ -2392,8 +2409,9 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { // 2nd update should beep at 0% volume Mockito.reset(mRingtonePlayer); - mAttentionHelper.buzzBeepBlinkLocked(r3, DEFAULT_SIGNALS); - verifyBeepVolume(0.0f); + buzzBeepBlink = mAttentionHelper.buzzBeepBlinkLocked(r3, DEFAULT_SIGNALS); + verifyNeverBeep(); + assertThat(buzzBeepBlink).isEqualTo(MetricsEvent.ALERT_MUTED | MUTE_REASON_COOLDOWN); verify(mAccessibilityService, times(3)).sendAccessibilityEvent(any(), anyInt()); assertEquals(-1, r3.getLastAudiblyAlertedMs()); @@ -2493,8 +2511,9 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { // Regular notification: should beep at 0% volume NotificationRecord r = getBeepyNotification(); - mAttentionHelper.buzzBeepBlinkLocked(r, DEFAULT_SIGNALS); - verifyBeepVolume(0.0f); + int buzzBeepBlink = mAttentionHelper.buzzBeepBlinkLocked(r, DEFAULT_SIGNALS); + verifyNeverBeep(); + assertThat(buzzBeepBlink).isEqualTo(MetricsEvent.ALERT_MUTED | MUTE_REASON_COOLDOWN); assertEquals(-1, r.getLastAudiblyAlertedMs()); Mockito.reset(mRingtonePlayer); @@ -2525,8 +2544,9 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { // 2nd update should beep at 0% volume Mockito.reset(mRingtonePlayer); - mAttentionHelper.buzzBeepBlinkLocked(r3, DEFAULT_SIGNALS); - verifyBeepVolume(0.0f); + buzzBeepBlink = mAttentionHelper.buzzBeepBlinkLocked(r3, DEFAULT_SIGNALS); + verifyNeverBeep(); + assertThat(buzzBeepBlink).isEqualTo(MetricsEvent.ALERT_MUTED | MUTE_REASON_COOLDOWN); // Set important conversation mChannel.setImportantConversation(true); @@ -2751,9 +2771,10 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { Mockito.reset(mRingtonePlayer); // next update at 0% volume - mAttentionHelper.buzzBeepBlinkLocked(summary, DEFAULT_SIGNALS); + int buzzBeepBlink = mAttentionHelper.buzzBeepBlinkLocked(summary, DEFAULT_SIGNALS); assertEquals(-1, summary.getLastAudiblyAlertedMs()); - verifyBeepVolume(0.0f); + verifyNeverBeep(); + assertThat(buzzBeepBlink).isEqualTo(MetricsEvent.ALERT_MUTED | MUTE_REASON_COOLDOWN); verify(mAccessibilityService, times(3)).sendAccessibilityEvent(any(), anyInt()); } @@ -2823,9 +2844,10 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { // 2nd update should beep at 0% volume Mockito.reset(mRingtonePlayer); - mAttentionHelper.buzzBeepBlinkLocked(r2, DEFAULT_SIGNALS); + int buzzBeepBlink = mAttentionHelper.buzzBeepBlinkLocked(r2, DEFAULT_SIGNALS); assertEquals(-1, r2.getLastAudiblyAlertedMs()); - verifyBeepVolume(0.0f); + verifyNeverBeep(); + assertThat(buzzBeepBlink).isEqualTo(MetricsEvent.ALERT_MUTED | MUTE_REASON_COOLDOWN); // Use different package for next notifications NotificationRecord r3 = getNotificationRecord(mId, false /* insistent */, false /* once */, @@ -2891,6 +2913,94 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { } @Test + public void testBeepVolume_politeNotif_groupAlertSummary() throws Exception { + mSetFlagsRule.enableFlags(Flags.FLAG_POLITE_NOTIFICATIONS); + mSetFlagsRule.disableFlags(Flags.FLAG_CROSS_APP_POLITE_NOTIFICATIONS); + TestableFlagResolver flagResolver = new TestableFlagResolver(); + flagResolver.setFlagOverride(NotificationFlags.NOTIF_VOLUME1, 50); + flagResolver.setFlagOverride(NotificationFlags.NOTIF_VOLUME2, 0); + // NOTIFICATION_COOLDOWN_ALL setting is enabled + Settings.System.putInt(getContext().getContentResolver(), + Settings.System.NOTIFICATION_COOLDOWN_ALL, 1); + initAttentionHelper(flagResolver); + + // child should beep at 0% volume + NotificationRecord child = getBeepyNotificationRecord("a", GROUP_ALERT_SUMMARY); + mAttentionHelper.buzzBeepBlinkLocked(child, DEFAULT_SIGNALS); + verifyNeverBeep(); + assertFalse(child.isInterruptive()); + assertEquals(-1, child.getLastAudiblyAlertedMs()); + Mockito.reset(mRingtonePlayer); + + // child should beep at 0% volume + child = getBeepyNotificationRecord("a", GROUP_ALERT_SUMMARY); + mAttentionHelper.buzzBeepBlinkLocked(child, DEFAULT_SIGNALS); + verifyNeverBeep(); + assertFalse(child.isInterruptive()); + assertEquals(-1, child.getLastAudiblyAlertedMs()); + Mockito.reset(mRingtonePlayer); + + // summary 100% volume (GROUP_ALERT_SUMMARY) + NotificationRecord summary = getBeepyNotificationRecord("a", GROUP_ALERT_SUMMARY); + summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY; + mAttentionHelper.buzzBeepBlinkLocked(summary, DEFAULT_SIGNALS); + assertNotEquals(-1, summary.getLastAudiblyAlertedMs()); + verifyBeepVolume(1.0f); + Mockito.reset(mRingtonePlayer); + + // next update at 50% volume because only summary was tracked as alerting + mAttentionHelper.buzzBeepBlinkLocked(summary, DEFAULT_SIGNALS); + assertNotEquals(-1, summary.getLastAudiblyAlertedMs()); + verifyBeepVolume(0.5f); + + verify(mAccessibilityService, times(4)).sendAccessibilityEvent(any(), anyInt()); + } + + @Test + public void testBeepVolume_politeNotif_groupAlertChildren() throws Exception { + mSetFlagsRule.enableFlags(Flags.FLAG_POLITE_NOTIFICATIONS); + mSetFlagsRule.disableFlags(Flags.FLAG_CROSS_APP_POLITE_NOTIFICATIONS); + TestableFlagResolver flagResolver = new TestableFlagResolver(); + flagResolver.setFlagOverride(NotificationFlags.NOTIF_VOLUME1, 50); + flagResolver.setFlagOverride(NotificationFlags.NOTIF_VOLUME2, 0); + // NOTIFICATION_COOLDOWN_ALL setting is enabled + Settings.System.putInt(getContext().getContentResolver(), + Settings.System.NOTIFICATION_COOLDOWN_ALL, 1); + initAttentionHelper(flagResolver); + + // summary 0% volume (GROUP_ALERT_CHILDREN) + NotificationRecord summary = getBeepyNotificationRecord("a", GROUP_ALERT_CHILDREN); + summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY; + mAttentionHelper.buzzBeepBlinkLocked(summary, DEFAULT_SIGNALS); + verifyNeverBeep(); + assertFalse(summary.isInterruptive()); + assertEquals(-1, summary.getLastAudiblyAlertedMs()); + Mockito.reset(mRingtonePlayer); + + // child should beep at 100% volume + NotificationRecord child = getBeepyNotificationRecord("a", GROUP_ALERT_CHILDREN); + mAttentionHelper.buzzBeepBlinkLocked(child, DEFAULT_SIGNALS); + assertNotEquals(-1, child.getLastAudiblyAlertedMs()); + verifyBeepVolume(1.0f); + Mockito.reset(mRingtonePlayer); + + // child should beep at 50% volume + child = getBeepyNotificationRecord("a", GROUP_ALERT_CHILDREN); + mAttentionHelper.buzzBeepBlinkLocked(child, DEFAULT_SIGNALS); + assertNotEquals(-1, child.getLastAudiblyAlertedMs()); + verifyBeepVolume(0.5f); + Mockito.reset(mRingtonePlayer); + + // child should beep at 0% volume + mAttentionHelper.buzzBeepBlinkLocked(child, DEFAULT_SIGNALS); + verifyNeverBeep(); + assertTrue(child.isInterruptive()); + assertEquals(-1, child.getLastAudiblyAlertedMs()); + + verify(mAccessibilityService, times(4)).sendAccessibilityEvent(any(), anyInt()); + } + + @Test public void testVibrationIntensity_politeNotif() throws Exception { mSetFlagsRule.enableFlags(Flags.FLAG_POLITE_NOTIFICATIONS); TestableFlagResolver flagResolver = new TestableFlagResolver(); @@ -2914,8 +3024,9 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { Mockito.reset(vibratorHelper); // 2nd update should buzz at 0% intensity - mAttentionHelper.buzzBeepBlinkLocked(r, DEFAULT_SIGNALS); - verify(vibratorHelper, times(1)).scale(any(), eq(0.0f)); + int buzzBeepBlink = mAttentionHelper.buzzBeepBlinkLocked(r, DEFAULT_SIGNALS); + verifyNeverVibrate(); + assertThat(buzzBeepBlink).isEqualTo(MetricsEvent.ALERT_MUTED | MUTE_REASON_COOLDOWN); } @Test @@ -3007,10 +3118,11 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { // 2nd update should beep at 0% volume Mockito.reset(mRingtonePlayer); - mAttentionHelper.buzzBeepBlinkLocked(r, WORK_PROFILE_SIGNALS); - verifyBeepVolume(0.0f); + int buzzBeepBlink = mAttentionHelper.buzzBeepBlinkLocked(r, WORK_PROFILE_SIGNALS); + verifyNeverBeep(); + assertThat(buzzBeepBlink).isEqualTo(MetricsEvent.ALERT_MUTED | MUTE_REASON_COOLDOWN); - verify(mAccessibilityService, times(3)).sendAccessibilityEvent(any(), anyInt()); + verify(mAccessibilityService, times(2)).sendAccessibilityEvent(any(), anyInt()); assertEquals(-1, r.getLastAudiblyAlertedMs()); } |