This article describes why and when this dialog appears, and how to get rid of it.
Introduction
Sometimes, when you are using headphones with the Android device, the media volume may suddenly drop down and you can’t turn the volume back. To do that, you have to unlock the device and accept the warning:
The time when the dialog shows up is unpredictable: it may appear when you are driving the car/bicycle, or your hands are dirty/wet, etc. Of course, listening to loud music through the headphones may damage the hearing. But the device could not recognize what is connected: headphones or speakers. And in case of speakers, this message is meaningless.
Why It Shows Up
There are WHO-ETU standards for the listening systems. Their use is mandatory in the countries of the European Union and some other. The standards describe sound allowance for people depending on the audio volume and the listening time.
How It's Implemented in Android
Depending on the mcc (mobile country code), the warning can be enabled or disabled. It’s defined by the resource R.bool.config_safe_media_volume_enabled
. If warning is enabled, then the system counts the “unsafe listening” time and shows the warning when it reaches 20 hours.
Listening is considered “unsafe” when the volume level is greater than 85 dB and headphones are connected. The cumulative “unsafe listening” time is stored in Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS
and is updated every minute.
The safe listening system logic is implemented in AudioService.java.
Workaround for Rooted Devices
Set audio.safemedia.bypass=true
in file system/build.properties:
Why it should work?
Let’s look at some fields in AudioService.java:
private static final int SAFE_MEDIA_VOLUME_NOT_CONFIGURED = 0;
private static final int SAFE_MEDIA_VOLUME_DISABLED = 1;
private static final int SAFE_MEDIA_VOLUME_INACTIVE = 2;
private static final int SAFE_MEDIA_VOLUME_ACTIVE = 3;
private Integer mSafeMediaVolumeState;
The field mSafeMediaVolumeState
keeps the current safe listening state:
DISABLED
: Safe listening is disabled (volume level is not controlled) ACTIVE
: Safe listening is enabled, “unsafe listening” time has reached 20 hours, and user must confirm the dialog to be able to raise the volume up INACTIVE
: Safe listening is enabled, “unsafe listening” time has not reached 20 hours yet
We need mSafeMediaVolumeState
to be assigned to DISABLED.
The initial value is assigned here:
private void onConfigureSafeVolume(boolean force, String caller) {
...
boolean safeMediaVolumeEnabled =
SystemProperties.getBoolean("audio.safemedia.force", false)
|| mContext.getResources().getBoolean(
com.android.internal.R.bool.config_safe_media_volume_enabled);
boolean safeMediaVolumeBypass =
SystemProperties.getBoolean("audio.safemedia.bypass", false);
int persistedState;
if (safeMediaVolumeEnabled && !safeMediaVolumeBypass) {
persistedState = SAFE_MEDIA_VOLUME_ACTIVE;
...
} else {
persistedState = SAFE_MEDIA_VOLUME_DISABLED;
mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED;
}
It can be assigned to DISABLED
in two cases: when R.bool.config_safe_media_volume_enabled=true
(we can’t change it) or when audio.safemedia.bypass = true
(we can change it with root privileges).
Workaround With No Root
The solution is to monitor the value of Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS
and to not allow it to exceed 20 hours. The value should be reset when it gets close to the threshold.
How to Read the Current Value
int unsafeMs = Settings.Secure.getInt(contentResolver, "unsafe_volume_music_active_ms")
The same using adb:
adb shell settings get secure unsafe_volume_music_active_ms
How to Update the Value
Firstly, grant the permissions to change the Secure Settings:
adb shell pm grant com.example.app android.permission.WRITE_SECURE_SETTINGS
It can be done because this permission has protectionLevel="signature|privileged|development
",
Then call:
Settings.Secure.putInt(contentResolver, "unsafe_volume_music_active_ms"
, 1)
It has to be 1
, because 0
value is associated with ACTIVE
state.
The same thing using adb:
adb shell settings put secure unsafe_volume_music_active_ms 1
After the value update, we need to ask the AudioService
to read and use it. According to the source code, the only way to do that is to restart it. Audio service is a system service, so to restart it, the device must be rebooted (alternatively user can re-login).
In order to make this solution easier to use, I wrote code for a small app which periodically checks the Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS
value and reminds to reboot the device.
Of course, it takes time to reboot or re-login, but this solution does not require root privileges.
History
- 15th June, 2020: Initial version