summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jean-Michel Trivi <jmtrivi@google.com> 2023-12-15 08:43:35 -0800
committer Jean-Michel Trivi <jmtrivi@google.com> 2024-01-09 08:32:48 -0800
commita97cd6811af2b88e8b7e97457cc29923e9466adf (patch)
tree151bce0ac11b7bc4e4bf7ce4d05f984e58fa9ba6
parent3f6fad2a6ac8dd234a613e4810e5fa056eb30fb4 (diff)
Muting notifications due to focus is conditional on recording
Legacy behavior is to mute notification while an app has requested audio focus with GAIN_TRANSIENT_EXCLUSIVE. The new behavior under flag is to enforce that the muting happens only when the focus requester is also recording audio. Implementation uses a new AudioManager method that contains all audio framework-side evaluation of whether the notification should play, and avoid code duplication in NotificationManagerService and NotificationAttentionHelper. Annotated AudioAttributes field in NotificationRecord to document that they are never null (so always available to be consumed by AudioManager.shouldNotificationSoundPlay). Updated unit tests to also mock AudioManager's response for shouldNotificationPlaySound such that it's compliant with the ringer mode and volume set on the mock in the existing test. This way the test is independent of the flag state. Flag: android.media.audio.focus_exclusive_with_recording Test: atest android.media.audio.cts.AudioFocusTest Test: atest BuzzBeepBlinkTest NotificationAttentionHelperTest Bug: 316414750 Change-Id: I54147c0dcccd7785589f4c9882582f42cf1a2d65
-rw-r--r--core/api/test-current.txt1
-rw-r--r--media/java/android/media/AudioManager.java23
-rw-r--r--media/java/android/media/IAudioService.aidl4
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java40
-rw-r--r--services/core/java/com/android/server/audio/MediaFocusControl.java17
-rw-r--r--services/core/java/com/android/server/notification/NotificationAttentionHelper.java54
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java48
-rw-r--r--services/core/java/com/android/server/notification/NotificationRecord.java9
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java10
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java12
10 files changed, 176 insertions, 42 deletions
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 812ba6d5fde9..59f0345b98e7 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1871,6 +1871,7 @@ package android.media {
method public void setRampingRingerEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) public void setRs2Value(float);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setTestDeviceConnectionState(@NonNull android.media.AudioDeviceAttributes, boolean);
+ method @FlaggedApi("android.media.audio.focus_exclusive_with_recording") @RequiresPermission(android.Manifest.permission.QUERY_AUDIO_STATE) public boolean shouldNotificationSoundPlay(@NonNull android.media.AudioAttributes);
}
public static final class AudioRecord.MetricsConstants {
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index a5a69f987113..4918289e8b5c 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -21,6 +21,7 @@ import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_AUDIO;
import static android.content.Context.DEVICE_ID_DEFAULT;
import static android.media.audio.Flags.autoPublicVolumeApiHardening;
import static android.media.audio.Flags.automaticBtDeviceType;
+import static android.media.audio.Flags.FLAG_FOCUS_EXCLUSIVE_WITH_RECORDING;
import static android.media.audio.Flags.FLAG_FOCUS_FREEZE_TEST_API;
import static android.media.audiopolicy.Flags.FLAG_ENABLE_FADE_MANAGER_CONFIGURATION;
@@ -10081,6 +10082,28 @@ public class AudioManager {
}
}
+ /**
+ * @hide
+ * Checks whether a notification sound should be played or not, as reported by the state
+ * of the audio framework. Querying whether playback should proceed is favored over
+ * playing and letting the sound be muted or not.
+ * @param aa the {@link AudioAttributes} of the notification about to maybe play
+ * @return true if the audio framework state is such that the notification should be played
+ * because at time of checking, and the notification will be heard,
+ * false otherwise
+ */
+ @TestApi
+ @FlaggedApi(FLAG_FOCUS_EXCLUSIVE_WITH_RECORDING)
+ @RequiresPermission(android.Manifest.permission.QUERY_AUDIO_STATE)
+ public boolean shouldNotificationSoundPlay(@NonNull final AudioAttributes aa) {
+ final IAudioService service = getService();
+ try {
+ return service.shouldNotificationSoundPlay(Objects.requireNonNull(aa));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
//====================================================================
// Mute await connection
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 5c268d4ab652..2eec9b3d4a09 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -775,4 +775,8 @@ interface IAudioService {
@EnforcePermission("MODIFY_AUDIO_SETTINGS_PRIVILEGED")
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED)")
FadeManagerConfiguration getFadeManagerConfigurationForFocusLoss();
+
+ @EnforcePermission("QUERY_AUDIO_STATE")
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.QUERY_AUDIO_STATE)")
+ boolean shouldNotificationSoundPlay(in AudioAttributes aa);
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 37fe38924037..2036ce23a502 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -13588,6 +13588,46 @@ public class AudioService extends IAudioService.Stub
}
}
+
+ /**
+ * @see AudioManager#shouldNotificationSoundPlay(AudioAttributes)
+ */
+ @android.annotation.EnforcePermission(
+ android.Manifest.permission.QUERY_AUDIO_STATE)
+ public boolean shouldNotificationSoundPlay(@NonNull final AudioAttributes aa) {
+ super.shouldNotificationSoundPlay_enforcePermission();
+ Objects.requireNonNull(aa);
+
+ // don't play notifications if the stream volume associated with the
+ // AudioAttributes of the notification record is 0 (non-zero volume implies
+ // not silenced by SILENT or VIBRATE ringer mode)
+ final int stream = AudioAttributes.toLegacyStreamType(aa);
+ final boolean mutingFromVolume = getStreamVolume(stream) == 0;
+ if (mutingFromVolume) {
+ if (DEBUG_VOL) {
+ Slog.d(TAG, "notification should not play due to muted stream " + stream);
+ }
+ return false;
+ }
+
+ // don't play notifications if there is a user of GAIN_TRANSIENT_EXCLUSIVE audio focus
+ // and the focus owner is recording
+ final int uid = mMediaFocusControl.getExclusiveFocusOwnerUid();
+ if (uid == -1) { // return value is -1 if focus isn't GAIN_TRANSIENT_EXCLUSIVE
+ return true;
+ }
+ // is the owner of GAIN_TRANSIENT_EXCLUSIVE focus also recording?
+ final boolean mutingFromFocusAndRecording = mRecordMonitor.isRecordingActiveForUid(uid);
+ if (mutingFromFocusAndRecording) {
+ if (DEBUG_VOL) {
+ Slog.d(TAG, "notification should not play due to exclusive focus owner recording "
+ + " uid:" + uid);
+ }
+ return false;
+ }
+ return true;
+ }
+
//======================
// Audioserver state dispatch
//======================
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index 0df0006c7be3..1376bde2fb71 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -297,6 +297,23 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
}
/**
+ * Return the UID of the focus owner that has focus with exclusive focus gain
+ * @return -1 if nobody has exclusive focus, the UID of the owner otherwise
+ */
+ protected int getExclusiveFocusOwnerUid() {
+ synchronized (mAudioFocusLock) {
+ if (mFocusStack.empty()) {
+ return -1;
+ }
+ final FocusRequester owner = mFocusStack.peek();
+ if (owner.getGainRequest() != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE) {
+ return -1;
+ }
+ return owner.getClientUid();
+ }
+ }
+
+ /**
* Send AUDIOFOCUS_LOSS to a specific stack entry.
* Note this method is supporting an external API, and is restricted to LOSS in order to
* prevent allowing the stack to be in an invalid state (e.g. entry inside stack has focus)
diff --git a/services/core/java/com/android/server/notification/NotificationAttentionHelper.java b/services/core/java/com/android/server/notification/NotificationAttentionHelper.java
index 6b7db2d8d071..db7be2183e91 100644
--- a/services/core/java/com/android/server/notification/NotificationAttentionHelper.java
+++ b/services/core/java/com/android/server/notification/NotificationAttentionHelper.java
@@ -22,6 +22,7 @@ import static android.app.NotificationManager.IMPORTANCE_MIN;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
+import static android.media.audio.Flags.focusExclusiveWithRecording;
import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS;
import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_EFFECTS;
import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_NOTIFICATION_EFFECTS;
@@ -588,30 +589,41 @@ public final class NotificationAttentionHelper {
}
private boolean playSound(final NotificationRecord record, Uri soundUri) {
+ final boolean shouldPlay;
+ if (focusExclusiveWithRecording()) {
+ // flagged path
+ shouldPlay = mAudioManager.shouldNotificationSoundPlay(record.getAudioAttributes());
+ } else {
+ // legacy path
+ // play notifications if there is no user of exclusive audio focus
+ // and the stream volume is not 0 (non-zero volume implies not silenced by SILENT or
+ // VIBRATE ringer mode)
+ shouldPlay = !mAudioManager.isAudioFocusExclusive()
+ && (mAudioManager.getStreamVolume(
+ AudioAttributes.toLegacyStreamType(record.getAudioAttributes())) != 0);
+ }
+ if (!shouldPlay) {
+ if (DEBUG) Slog.v(TAG, "Not playing sound " + soundUri + " due to focus/volume");
+ return false;
+ }
+
boolean looping = (record.getNotification().flags & FLAG_INSISTENT) != 0;
- // play notifications if there is no user of exclusive audio focus
- // and the stream volume is not 0 (non-zero volume implies not silenced by SILENT or
- // VIBRATE ringer mode)
- if (!mAudioManager.isAudioFocusExclusive()
- && (mAudioManager.getStreamVolume(
- AudioAttributes.toLegacyStreamType(record.getAudioAttributes())) != 0)) {
- final long identity = Binder.clearCallingIdentity();
- try {
- final IRingtonePlayer player = mAudioManager.getRingtonePlayer();
- if (player != null) {
- if (DEBUG) {
- Slog.v(TAG, "Playing sound " + soundUri + " with attributes "
- + record.getAudioAttributes());
- }
- player.playAsync(soundUri, record.getSbn().getUser(), looping,
- record.getAudioAttributes(), getSoundVolume(record));
- return true;
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ final IRingtonePlayer player = mAudioManager.getRingtonePlayer();
+ if (player != null) {
+ if (DEBUG) {
+ Slog.v(TAG, "Playing sound " + soundUri + " with attributes "
+ + record.getAudioAttributes());
}
- } catch (RemoteException e) {
- Log.e(TAG, "Failed playSound: " + e);
- } finally {
- Binder.restoreCallingIdentity(identity);
+ player.playAsync(soundUri, record.getSbn().getUser(), looping,
+ record.getAudioAttributes(), getSoundVolume(record));
+ return true;
}
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed playSound: " + e);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
return false;
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index ff415c155b35..c2cdcb09dbe4 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -79,6 +79,7 @@ import static android.content.pm.PackageManager.MATCH_ANY_USER;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.media.audio.Flags.focusExclusiveWithRecording;
import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
import static android.os.Flags.allowPrivateProfile;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
@@ -9052,27 +9053,40 @@ public class NotificationManagerService extends SystemService {
}
private boolean playSound(final NotificationRecord record, Uri soundUri) {
+ final boolean shouldPlay;
+ if (focusExclusiveWithRecording()) {
+ // flagged path
+ shouldPlay = mAudioManager.shouldNotificationSoundPlay(record.getAudioAttributes());
+ } else {
+ // legacy path
+ // play notifications if there is no user of exclusive audio focus
+ // and the stream volume is not 0 (non-zero volume implies not silenced by SILENT or
+ // VIBRATE ringer mode)
+ shouldPlay = !mAudioManager.isAudioFocusExclusive()
+ && (mAudioManager.getStreamVolume(
+ AudioAttributes.toLegacyStreamType(record.getAudioAttributes())) != 0);
+ }
+ if (!shouldPlay) {
+ if (DBG) Slog.v(TAG, "Not playing sound " + soundUri + " due to focus/volume");
+ return false;
+ }
+
boolean looping = (record.getNotification().flags & FLAG_INSISTENT) != 0;
- // play notifications if there is no user of exclusive audio focus
- // and the stream volume is not 0 (non-zero volume implies not silenced by SILENT or
- // VIBRATE ringer mode)
- if (!mAudioManager.isAudioFocusExclusive()
- && (mAudioManager.getStreamVolume(
- AudioAttributes.toLegacyStreamType(record.getAudioAttributes())) != 0)) {
- final long identity = Binder.clearCallingIdentity();
- try {
- final IRingtonePlayer player = mAudioManager.getRingtonePlayer();
- if (player != null) {
- if (DBG) Slog.v(TAG, "Playing sound " + soundUri
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ final IRingtonePlayer player = mAudioManager.getRingtonePlayer();
+ if (player != null) {
+ if (DBG) {
+ Slog.v(TAG, "Playing sound " + soundUri
+ " with attributes " + record.getAudioAttributes());
- player.playAsync(soundUri, record.getSbn().getUser(), looping,
- record.getAudioAttributes(), 1.0f);
- return true;
}
- } catch (RemoteException e) {
- } finally {
- Binder.restoreCallingIdentity(identity);
+ player.playAsync(soundUri, record.getSbn().getUser(), looping,
+ record.getAudioAttributes(), 1.0f);
+ return true;
}
+ } catch (RemoteException e) {
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
return false;
}
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 64d3a20e9281..1786ac53eeab 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -25,6 +25,7 @@ import static android.service.notification.NotificationListenerService.Ranking.U
import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_POSITIVE;
import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Flags;
import android.app.KeyguardManager;
@@ -167,7 +168,7 @@ public final class NotificationRecord {
private boolean mPreChannelsNotification = true;
private Uri mSound;
private VibrationEffect mVibration;
- private AudioAttributes mAttributes;
+ private @NonNull AudioAttributes mAttributes;
private NotificationChannel mChannel;
private ArrayList<String> mPeopleOverride;
private ArrayList<SnoozeCriterion> mSnoozeCriteria;
@@ -334,7 +335,7 @@ public final class NotificationRecord {
return vibration;
}
- private AudioAttributes calculateAttributes() {
+ private @NonNull AudioAttributes calculateAttributes() {
final Notification n = getSbn().getNotification();
AudioAttributes attributes = getChannel().getAudioAttributes();
if (attributes == null) {
@@ -1003,7 +1004,7 @@ public final class NotificationRecord {
}
public boolean isAudioAttributesUsage(int usage) {
- return mAttributes != null && mAttributes.getUsage() == usage;
+ return mAttributes.getUsage() == usage;
}
/**
@@ -1172,7 +1173,7 @@ public final class NotificationRecord {
return mVibration;
}
- public AudioAttributes getAudioAttributes() {
+ public @NonNull AudioAttributes getAudioAttributes() {
return mAttributes;
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 42ad73a23f0e..8622488f820e 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -158,6 +158,9 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
when(mAudioManager.isAudioFocusExclusive()).thenReturn(false);
when(mAudioManager.getRingtonePlayer()).thenReturn(mRingtonePlayer);
when(mAudioManager.getStreamVolume(anyInt())).thenReturn(10);
+ // consistent with focus not exclusive and volume not muted
+ when(mAudioManager.shouldNotificationSoundPlay(any(AudioAttributes.class)))
+ .thenReturn(true);
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
when(mAudioManager.getFocusRampTimeMs(anyInt(), any(AudioAttributes.class))).thenReturn(50);
when(mUsageStats.isAlertRateLimited(any())).thenReturn(false);
@@ -869,6 +872,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
// the phone is quiet
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
+ when(mAudioManager.shouldNotificationSoundPlay(any())).thenReturn(false);
mService.buzzBeepBlinkLocked(r);
@@ -886,6 +890,8 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
// the phone is quiet
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
when(mAudioManager.getStreamVolume(anyInt())).thenReturn(1);
+ // all streams at 1 means no muting from audio framework
+ when(mAudioManager.shouldNotificationSoundPlay(any())).thenReturn(true);
mService.buzzBeepBlinkLocked(r);
@@ -904,6 +910,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
// the phone is quiet
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
+ when(mAudioManager.shouldNotificationSoundPlay(any())).thenReturn(false);
mService.buzzBeepBlinkLocked(r);
@@ -924,6 +931,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
// the phone is quiet
when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
+ when(mAudioManager.shouldNotificationSoundPlay(any())).thenReturn(false);
mService.buzzBeepBlinkLocked(r);
@@ -1195,6 +1203,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
// the phone is quiet
when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
+ when(mAudioManager.shouldNotificationSoundPlay(any())).thenReturn(false);
mService.buzzBeepBlinkLocked(r);
verifyDelayedVibrate(mService.getVibratorHelper().createFallbackVibration(false));
@@ -1923,6 +1932,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
NotificationRecord r = getBuzzyBeepyNotification();
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_SILENT);
when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
+ when(mAudioManager.shouldNotificationSoundPlay(any())).thenReturn(false);
mService.buzzBeepBlinkLocked(r);
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 cf8548cfe689..f0f97ac4919a 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java
@@ -25,9 +25,11 @@ import static android.app.NotificationManager.IMPORTANCE_MIN;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
import static android.media.AudioAttributes.USAGE_NOTIFICATION;
import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
+
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.mockito.ArgumentMatchers.anyFloat;
@@ -178,6 +180,8 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase {
when(mAudioManager.getStreamVolume(anyInt())).thenReturn(10);
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
when(mAudioManager.getFocusRampTimeMs(anyInt(), any(AudioAttributes.class))).thenReturn(50);
+ when(mAudioManager.shouldNotificationSoundPlay(any(AudioAttributes.class)))
+ .thenReturn(true);
when(mUsageStats.isAlertRateLimited(any())).thenReturn(false);
when(mVibrator.hasFrequencyControl()).thenReturn(false);
when(mKeyguardManager.isDeviceLocked(anyInt())).thenReturn(false);
@@ -915,6 +919,8 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase {
// the phone is quiet
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
+ when(mAudioManager.shouldNotificationSoundPlay(any(AudioAttributes.class)))
+ .thenReturn(false);
mAttentionHelper.buzzBeepBlinkLocked(r, DEFAULT_SIGNALS);
@@ -932,6 +938,8 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase {
// the phone is quiet
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
when(mAudioManager.getStreamVolume(anyInt())).thenReturn(1);
+ // all streams at 1 means no muting from audio framework
+ when(mAudioManager.shouldNotificationSoundPlay(any())).thenReturn(true);
mAttentionHelper.buzzBeepBlinkLocked(r, DEFAULT_SIGNALS);
@@ -950,6 +958,7 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase {
// the phone is quiet
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
+ when(mAudioManager.shouldNotificationSoundPlay(any())).thenReturn(false);
mAttentionHelper.buzzBeepBlinkLocked(r, DEFAULT_SIGNALS);
@@ -971,6 +980,7 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase {
// the phone is quiet
when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
+ when(mAudioManager.shouldNotificationSoundPlay(any())).thenReturn(false);
mAttentionHelper.buzzBeepBlinkLocked(r, DEFAULT_SIGNALS);
@@ -1243,6 +1253,7 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase {
// the phone is quiet
when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
+ when(mAudioManager.shouldNotificationSoundPlay(any())).thenReturn(false);
mAttentionHelper.buzzBeepBlinkLocked(r, DEFAULT_SIGNALS);
verifyDelayedVibrate(mAttentionHelper.getVibratorHelper().createFallbackVibration(false));
@@ -1973,6 +1984,7 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase {
NotificationRecord r = getBuzzyBeepyNotification();
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_SILENT);
when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
+ when(mAudioManager.shouldNotificationSoundPlay(any())).thenReturn(false);
mAttentionHelper.buzzBeepBlinkLocked(r, DEFAULT_SIGNALS);