CSD: Fixed volume not lowering to RS1
Fixed AppOps blocking the volume lowering and calling lower volume when
the SysUI lower volume button is clicked by the user.
Flag: NONE
Test: trigger CSD warnings and check that volume is lowered
Bug: 309861467
Change-Id: Ic91db26c87c5daed88b1d2a896713b3dbf1a443d
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 8584dbc..12ddf9b 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -303,7 +303,7 @@
void disableSafeMediaVolume(String callingPackage);
- void lowerVolumeToRs1(String callingPackage);
+ oneway void lowerVolumeToRs1(String callingPackage);
@EnforcePermission("MODIFY_AUDIO_SETTINGS_PRIVILEGED")
float getOutputRs2UpperBound();
diff --git a/packages/SystemUI/src/com/android/systemui/volume/CsdWarningDialog.java b/packages/SystemUI/src/com/android/systemui/volume/CsdWarningDialog.java
index eb0bf46..d6e6f3f 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/CsdWarningDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/CsdWarningDialog.java
@@ -35,8 +35,8 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.messages.nano.SystemMessageProto;
-import com.android.systemui.res.R;
import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.res.R;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.util.NotificationChannels;
import com.android.systemui.util.concurrency.DelayableExecutor;
@@ -46,7 +46,8 @@
import dagger.assisted.AssistedInject;
/**
- * A class that implements the four Computed Sound Dose-related warnings defined in {@link AudioManager}:
+ * A class that implements the three Computed Sound Dose-related warnings defined in
+ * {@link AudioManager}:
* <ul>
* <li>{@link AudioManager#CSD_WARNING_DOSE_REACHED_1X}</li>
* <li>{@link AudioManager#CSD_WARNING_DOSE_REPEATED_5X}</li>
@@ -188,8 +189,8 @@
public void onClick(DialogInterface dialog, int which) {
if (which == DialogInterface.BUTTON_NEGATIVE) {
Log.d(TAG, "Lower volume pressed for CSD warning " + mCsdWarning);
+ mAudioManager.lowerVolumeToRs1();
dismiss();
-
}
if (D.BUG) Log.d(TAG, "on click " + which);
}
@@ -216,10 +217,6 @@
@Override
public void onDismiss(DialogInterface unused) {
- if (mCsdWarning == AudioManager.CSD_WARNING_DOSE_REPEATED_5X) {
- // level is always reduced to RS1 beyond the 5x dose
- mAudioManager.lowerVolumeToRs1();
- }
try {
mContext.unregisterReceiver(mReceiver);
} catch (IllegalArgumentException e) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index b209fb0..41655e2 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -16,8 +16,8 @@
package com.android.server.audio;
-import static android.app.BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT;
import static android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED;
+import static android.app.BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT;
import static android.media.AudioDeviceInfo.TYPE_BLE_HEADSET;
import static android.media.AudioDeviceInfo.TYPE_BLE_SPEAKER;
import static android.media.AudioDeviceInfo.TYPE_BLUETOOTH_A2DP;
@@ -29,7 +29,6 @@
import static android.media.AudioManager.RINGER_MODE_NORMAL;
import static android.media.AudioManager.RINGER_MODE_SILENT;
import static android.media.AudioManager.RINGER_MODE_VIBRATE;
-import static android.media.AudioManager.STREAM_MUSIC;
import static android.media.AudioManager.STREAM_SYSTEM;
import static android.os.Process.FIRST_APPLICATION_UID;
import static android.os.Process.INVALID_UID;
@@ -409,7 +408,6 @@
private static final int MSG_RESET_SPATIALIZER = 50;
private static final int MSG_NO_LOG_FOR_PLAYER_I = 51;
private static final int MSG_DISPATCH_PREFERRED_MIXER_ATTRIBUTES = 52;
- private static final int MSG_LOWER_VOLUME_TO_RS1 = 53;
private static final int MSG_CONFIGURATION_CHANGED = 54;
private static final int MSG_BROADCAST_MASTER_MUTE = 55;
@@ -3534,7 +3532,7 @@
return;
}
- mSoundDoseHelper.invalidatPendingVolumeCommand();
+ mSoundDoseHelper.invalidatePendingVolumeCommand();
flags &= ~AudioManager.FLAG_FIXED_VOLUME;
if (streamTypeAlias == AudioSystem.STREAM_MUSIC && isFixedVolumeDevice(device)) {
@@ -4605,7 +4603,7 @@
return;
}
- mSoundDoseHelper.invalidatPendingVolumeCommand();
+ mSoundDoseHelper.invalidatePendingVolumeCommand();
oldIndex = streamState.getIndex(device);
@@ -9542,10 +9540,6 @@
onDispatchPreferredMixerAttributesChanged(msg.getData(), msg.arg1);
break;
- case MSG_LOWER_VOLUME_TO_RS1:
- onLowerVolumeToRs1();
- break;
-
case MSG_CONFIGURATION_CHANGED:
onConfigurationChanged();
break;
@@ -9560,6 +9554,7 @@
case SoundDoseHelper.MSG_PERSIST_MUSIC_ACTIVE_MS:
case SoundDoseHelper.MSG_PERSIST_CSD_VALUES:
case SoundDoseHelper.MSG_CSD_UPDATE_ATTENUATION:
+ case SoundDoseHelper.MSG_LOWER_VOLUME_TO_RS1:
mSoundDoseHelper.handleMessage(msg);
break;
@@ -10944,31 +10939,11 @@
}
/*package*/ void postLowerVolumeToRs1() {
- sendMsg(mAudioHandler, MSG_LOWER_VOLUME_TO_RS1, SENDMSG_QUEUE,
+ sendMsg(mAudioHandler, SoundDoseHelper.MSG_LOWER_VOLUME_TO_RS1, SENDMSG_QUEUE,
// no params, no delay
0, 0, null, 0);
}
- /**
- * Called when handling MSG_LOWER_VOLUME_TO_RS1
- */
- private void onLowerVolumeToRs1() {
- final ArrayList<AudioDeviceAttributes> devices = getDevicesForAttributesInt(
- new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build(), true);
- final int nativeDeviceType;
- final AudioDeviceAttributes ada;
- if (!devices.isEmpty()) {
- ada = devices.get(0);
- nativeDeviceType = ada.getInternalType();
- } else {
- nativeDeviceType = AudioSystem.DEVICE_OUT_USB_HEADSET;
- ada = new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_USB_HEADSET, "");
- }
- final int index = mSoundDoseHelper.safeMediaVolumeIndex(nativeDeviceType);
- setStreamVolumeWithAttributionInt(STREAM_MUSIC, index, /*flags*/ 0, ada,
- "com.android.server.audio", "AudioService");
- }
-
@Override
@android.annotation.EnforcePermission(MODIFY_AUDIO_SETTINGS_PRIVILEGED)
public float getOutputRs2UpperBound() {
diff --git a/services/core/java/com/android/server/audio/AudioServiceEvents.java b/services/core/java/com/android/server/audio/AudioServiceEvents.java
index aac868f..21a7d31 100644
--- a/services/core/java/com/android/server/audio/AudioServiceEvents.java
+++ b/services/core/java/com/android/server/audio/AudioServiceEvents.java
@@ -539,6 +539,8 @@
static final int DOSE_UPDATE = 1;
static final int DOSE_REPEAT_5X = 2;
static final int DOSE_ACCUMULATION_START = 3;
+ static final int LOWER_VOLUME_TO_RS1 = 4;
+
final int mEventType;
final float mFloatValue;
final long mLongValue;
@@ -565,6 +567,10 @@
return new SoundDoseEvent(DOSE_ACCUMULATION_START, 0 /*ignored*/, 0 /*ignored*/);
}
+ static SoundDoseEvent getLowerVolumeToRs1Event() {
+ return new SoundDoseEvent(LOWER_VOLUME_TO_RS1, 0 /*ignored*/, 0 /*ignored*/);
+ }
+
@Override
public String eventToString() {
switch (mEventType) {
@@ -578,6 +584,8 @@
return "CSD reached 500%";
case DOSE_ACCUMULATION_START:
return "CSD accumulating: RS2 entered";
+ case LOWER_VOLUME_TO_RS1:
+ return "CSD lowering volume to RS1";
}
return new StringBuilder("FIXME invalid event type:").append(mEventType).toString();
}
diff --git a/services/core/java/com/android/server/audio/SoundDoseHelper.java b/services/core/java/com/android/server/audio/SoundDoseHelper.java
index d65c7c2c..793752f 100644
--- a/services/core/java/com/android/server/audio/SoundDoseHelper.java
+++ b/services/core/java/com/android/server/audio/SoundDoseHelper.java
@@ -18,6 +18,7 @@
import static android.media.AudioManager.AUDIO_DEVICE_CATEGORY_HEADPHONES;
import static android.media.AudioManager.AUDIO_DEVICE_CATEGORY_UNKNOWN;
+import static android.media.AudioManager.STREAM_MUSIC;
import static com.android.server.audio.AudioService.MAX_STREAM_VOLUME;
import static com.android.server.audio.AudioService.MIN_STREAM_VOLUME;
@@ -31,6 +32,8 @@
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
+import android.media.AudioAttributes;
+import android.media.AudioDeviceAttributes;
import android.media.AudioManager;
import android.media.AudioSystem;
import android.media.ISoundDose;
@@ -115,6 +118,9 @@
/*package*/ static final int MSG_PERSIST_CSD_VALUES = SAFE_MEDIA_VOLUME_MSG_START + 5;
/*package*/ static final int MSG_CSD_UPDATE_ATTENUATION = SAFE_MEDIA_VOLUME_MSG_START + 6;
+ /*package*/ static final int MSG_LOWER_VOLUME_TO_RS1 = SAFE_MEDIA_VOLUME_MSG_START + 7;
+
+
private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours
private static final int MOMENTARY_EXPOSURE_TIMEOUT_MS = (20 * 3600 * 1000); // 20 hours
@@ -774,7 +780,7 @@
return mSafeMediaVolumeDevices.get(device, SAFE_MEDIA_VOLUME_UNINITIALIZED) >= 0;
}
- /*package*/ void invalidatPendingVolumeCommand() {
+ /*package*/ void invalidatePendingVolumeCommand() {
synchronized (mSafeMediaVolumeStateLock) {
mPendingVolumeCommand = null;
}
@@ -808,6 +814,9 @@
updateDoseAttenuation(streamState.getIndex(device), device,
streamState.getStreamType(), isAbsoluteVolume);
break;
+ case MSG_LOWER_VOLUME_TO_RS1:
+ onLowerVolumeToRs1();
+ break;
default:
Log.e(TAG, "Unexpected msg to handle: " + msg.what);
break;
@@ -1272,6 +1281,25 @@
return value;
}
+ /** Called when handling MSG_LOWER_VOLUME_TO_RS1 */
+ private void onLowerVolumeToRs1() {
+ mLogger.enqueue(SoundDoseEvent.getLowerVolumeToRs1Event());
+ final ArrayList<AudioDeviceAttributes> devices = mAudioService.getDevicesForAttributesInt(
+ new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build(), true);
+ final int nativeDeviceType;
+ final AudioDeviceAttributes ada;
+ if (!devices.isEmpty()) {
+ ada = devices.get(0);
+ nativeDeviceType = ada.getInternalType();
+ } else {
+ nativeDeviceType = AudioSystem.DEVICE_OUT_USB_HEADSET;
+ ada = new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_USB_HEADSET, "");
+ }
+ final int index = safeMediaVolumeIndex(nativeDeviceType);
+ mAudioService.setStreamVolumeWithAttributionInt(STREAM_MUSIC, index / 10, /*flags*/ 0, ada,
+ mContext.getOpPackageName(), /*attributionTag=*/null);
+ }
+
// StreamVolumeCommand contains the information needed to defer the process of
// setStreamVolume() in case the user has to acknowledge the safe volume warning message.
private static class StreamVolumeCommand {