Loading media/java/android/media/IAudioService.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -303,7 +303,7 @@ interface IAudioService { void disableSafeMediaVolume(String callingPackage); void lowerVolumeToRs1(String callingPackage); oneway void lowerVolumeToRs1(String callingPackage); @EnforcePermission("MODIFY_AUDIO_SETTINGS_PRIVILEGED") float getOutputRs2UpperBound(); Loading packages/SystemUI/src/com/android/systemui/volume/CsdWarningDialog.java +4 −7 Original line number Diff line number Diff line Loading @@ -35,8 +35,8 @@ import android.view.WindowManager; 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; Loading @@ -46,7 +46,8 @@ import dagger.assisted.AssistedFactory; 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> Loading Loading @@ -188,8 +189,8 @@ public class CsdWarningDialog extends SystemUIDialog 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); } Loading @@ -216,10 +217,6 @@ public class CsdWarningDialog extends SystemUIDialog @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) { Loading services/core/java/com/android/server/audio/AudioService.java +5 −30 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -29,7 +29,6 @@ import static android.media.AudioManager.DEVICE_OUT_BLUETOOTH_A2DP; 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; Loading Loading @@ -409,7 +408,6 @@ public class AudioService extends IAudioService.Stub 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; Loading Loading @@ -3536,7 +3534,7 @@ public class AudioService extends IAudioService.Stub return; } mSoundDoseHelper.invalidatPendingVolumeCommand(); mSoundDoseHelper.invalidatePendingVolumeCommand(); flags &= ~AudioManager.FLAG_FIXED_VOLUME; if (streamTypeAlias == AudioSystem.STREAM_MUSIC && isFixedVolumeDevice(device)) { Loading Loading @@ -4607,7 +4605,7 @@ public class AudioService extends IAudioService.Stub return; } mSoundDoseHelper.invalidatPendingVolumeCommand(); mSoundDoseHelper.invalidatePendingVolumeCommand(); oldIndex = streamState.getIndex(device); Loading Loading @@ -9544,10 +9542,6 @@ public class AudioService extends IAudioService.Stub onDispatchPreferredMixerAttributesChanged(msg.getData(), msg.arg1); break; case MSG_LOWER_VOLUME_TO_RS1: onLowerVolumeToRs1(); break; case MSG_CONFIGURATION_CHANGED: onConfigurationChanged(); break; Loading @@ -9562,6 +9556,7 @@ public class AudioService extends IAudioService.Stub 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; Loading Loading @@ -10946,31 +10941,11 @@ public class AudioService extends IAudioService.Stub } /*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() { Loading services/core/java/com/android/server/audio/AudioServiceEvents.java +8 −0 Original line number Diff line number Diff line Loading @@ -539,6 +539,8 @@ public class AudioServiceEvents { 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; Loading @@ -565,6 +567,10 @@ public class AudioServiceEvents { 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) { Loading @@ -578,6 +584,8 @@ public class AudioServiceEvents { 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(); } Loading services/core/java/com/android/server/audio/SoundDoseHelper.java +29 −1 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.audio; 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; Loading @@ -31,6 +32,8 @@ import android.app.AlarmManager; 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; Loading Loading @@ -115,6 +118,9 @@ public class SoundDoseHelper { /*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 Loading Loading @@ -774,7 +780,7 @@ public class SoundDoseHelper { return mSafeMediaVolumeDevices.get(device, SAFE_MEDIA_VOLUME_UNINITIALIZED) >= 0; } /*package*/ void invalidatPendingVolumeCommand() { /*package*/ void invalidatePendingVolumeCommand() { synchronized (mSafeMediaVolumeStateLock) { mPendingVolumeCommand = null; } Loading Loading @@ -808,6 +814,9 @@ public class SoundDoseHelper { 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; Loading Loading @@ -1272,6 +1281,25 @@ public class SoundDoseHelper { 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 { Loading Loading
media/java/android/media/IAudioService.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -303,7 +303,7 @@ interface IAudioService { void disableSafeMediaVolume(String callingPackage); void lowerVolumeToRs1(String callingPackage); oneway void lowerVolumeToRs1(String callingPackage); @EnforcePermission("MODIFY_AUDIO_SETTINGS_PRIVILEGED") float getOutputRs2UpperBound(); Loading
packages/SystemUI/src/com/android/systemui/volume/CsdWarningDialog.java +4 −7 Original line number Diff line number Diff line Loading @@ -35,8 +35,8 @@ import android.view.WindowManager; 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; Loading @@ -46,7 +46,8 @@ import dagger.assisted.AssistedFactory; 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> Loading Loading @@ -188,8 +189,8 @@ public class CsdWarningDialog extends SystemUIDialog 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); } Loading @@ -216,10 +217,6 @@ public class CsdWarningDialog extends SystemUIDialog @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) { Loading
services/core/java/com/android/server/audio/AudioService.java +5 −30 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -29,7 +29,6 @@ import static android.media.AudioManager.DEVICE_OUT_BLUETOOTH_A2DP; 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; Loading Loading @@ -409,7 +408,6 @@ public class AudioService extends IAudioService.Stub 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; Loading Loading @@ -3536,7 +3534,7 @@ public class AudioService extends IAudioService.Stub return; } mSoundDoseHelper.invalidatPendingVolumeCommand(); mSoundDoseHelper.invalidatePendingVolumeCommand(); flags &= ~AudioManager.FLAG_FIXED_VOLUME; if (streamTypeAlias == AudioSystem.STREAM_MUSIC && isFixedVolumeDevice(device)) { Loading Loading @@ -4607,7 +4605,7 @@ public class AudioService extends IAudioService.Stub return; } mSoundDoseHelper.invalidatPendingVolumeCommand(); mSoundDoseHelper.invalidatePendingVolumeCommand(); oldIndex = streamState.getIndex(device); Loading Loading @@ -9544,10 +9542,6 @@ public class AudioService extends IAudioService.Stub onDispatchPreferredMixerAttributesChanged(msg.getData(), msg.arg1); break; case MSG_LOWER_VOLUME_TO_RS1: onLowerVolumeToRs1(); break; case MSG_CONFIGURATION_CHANGED: onConfigurationChanged(); break; Loading @@ -9562,6 +9556,7 @@ public class AudioService extends IAudioService.Stub 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; Loading Loading @@ -10946,31 +10941,11 @@ public class AudioService extends IAudioService.Stub } /*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() { Loading
services/core/java/com/android/server/audio/AudioServiceEvents.java +8 −0 Original line number Diff line number Diff line Loading @@ -539,6 +539,8 @@ public class AudioServiceEvents { 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; Loading @@ -565,6 +567,10 @@ public class AudioServiceEvents { 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) { Loading @@ -578,6 +584,8 @@ public class AudioServiceEvents { 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(); } Loading
services/core/java/com/android/server/audio/SoundDoseHelper.java +29 −1 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.audio; 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; Loading @@ -31,6 +32,8 @@ import android.app.AlarmManager; 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; Loading Loading @@ -115,6 +118,9 @@ public class SoundDoseHelper { /*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 Loading Loading @@ -774,7 +780,7 @@ public class SoundDoseHelper { return mSafeMediaVolumeDevices.get(device, SAFE_MEDIA_VOLUME_UNINITIALIZED) >= 0; } /*package*/ void invalidatPendingVolumeCommand() { /*package*/ void invalidatePendingVolumeCommand() { synchronized (mSafeMediaVolumeStateLock) { mPendingVolumeCommand = null; } Loading Loading @@ -808,6 +814,9 @@ public class SoundDoseHelper { 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; Loading Loading @@ -1272,6 +1281,25 @@ public class SoundDoseHelper { 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 { Loading