Loading core/jni/android_media_AudioSystem.cpp +14 −0 Original line number Diff line number Diff line Loading @@ -713,6 +713,19 @@ android_media_AudioSystem_getForceUse(JNIEnv *env, jobject thiz, jint usage) AudioSystem::getForceUse(static_cast<audio_policy_force_use_t>(usage))); } static jint android_media_AudioSystem_setDeviceAbsoluteVolumeEnabled(JNIEnv *env, jobject thiz, jint device, jstring address, jboolean enabled, jint stream) { const char *c_address = env->GetStringUTFChars(address, nullptr); int state = check_AudioSystem_Command( AudioSystem::setDeviceAbsoluteVolumeEnabled(static_cast<audio_devices_t>(device), c_address, enabled, static_cast<audio_stream_type_t>(stream))); env->ReleaseStringUTFChars(address, c_address); return state; } static jint android_media_AudioSystem_initStreamVolume(JNIEnv *env, jobject thiz, jint stream, jint indexMin, jint indexMax) { Loading Loading @@ -3373,6 +3386,7 @@ static const JNINativeMethod gMethods[] = MAKE_AUDIO_SYSTEM_METHOD(setPhoneState), MAKE_AUDIO_SYSTEM_METHOD(setForceUse), MAKE_AUDIO_SYSTEM_METHOD(getForceUse), MAKE_AUDIO_SYSTEM_METHOD(setDeviceAbsoluteVolumeEnabled), MAKE_AUDIO_SYSTEM_METHOD(initStreamVolume), MAKE_AUDIO_SYSTEM_METHOD(setStreamVolumeIndex), MAKE_AUDIO_SYSTEM_METHOD(getStreamVolumeIndex), Loading media/java/android/media/AudioSystem.java +4 −0 Original line number Diff line number Diff line Loading @@ -1764,6 +1764,10 @@ public class AudioSystem public static native int getForceUse(int usage); /** @hide */ @UnsupportedAppUsage public static native int setDeviceAbsoluteVolumeEnabled(int nativeDeviceType, @NonNull String address, boolean enabled, int streamToDriveAbs); /** @hide */ @UnsupportedAppUsage public static native int initStreamVolume(int stream, int indexMin, int indexMax); @UnsupportedAppUsage private static native int setStreamVolumeIndex(int stream, int index, int device); Loading services/core/java/com/android/server/audio/AudioService.java +123 −22 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ import static android.provider.Settings.Secure.VOLUME_HUSH_OFF; import static android.provider.Settings.Secure.VOLUME_HUSH_VIBRATE; import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; import static com.android.media.audio.Flags.absVolumeIndexFix; import static com.android.media.audio.Flags.alarmMinVolumeZero; import static com.android.media.audio.Flags.disablePrescaleAbsoluteVolume; import static com.android.media.audio.Flags.ringerModeAffectsAlarm; Loading Loading @@ -632,6 +633,17 @@ public class AudioService extends IAudioService.Stub // If absolute volume is supported in AVRCP device private volatile boolean mAvrcpAbsVolSupported = false; private final Object mCachedAbsVolDrivingStreamsLock = new Object(); // Contains for all the device types which support absolute volume the current streams that // are driving the volume changes @GuardedBy("mCachedAbsVolDrivingStreamsLock") private final HashMap<Integer, Integer> mCachedAbsVolDrivingStreams = new HashMap<>( Map.of(AudioSystem.DEVICE_OUT_BLE_HEADSET, AudioSystem.STREAM_MUSIC, AudioSystem.DEVICE_OUT_BLE_SPEAKER, AudioSystem.STREAM_MUSIC, AudioSystem.DEVICE_OUT_BLE_BROADCAST, AudioSystem.STREAM_MUSIC, AudioSystem.DEVICE_OUT_HEARING_AID, AudioSystem.STREAM_MUSIC )); /** * Default stream type used for volume control in the absence of playback * e.g. user on homescreen, no app playing anything, presses hardware volume buttons, this Loading Loading @@ -1472,6 +1484,13 @@ public class AudioService extends IAudioService.Stub // check on volume initialization checkVolumeRangeInitialization("AudioService()"); synchronized (mCachedAbsVolDrivingStreamsLock) { mCachedAbsVolDrivingStreams.forEach((dev, stream) -> { mAudioSystem.setDeviceAbsoluteVolumeEnabled(dev, /*address=*/"", /*enabled=*/true, stream); }); } } private SubscriptionManager.OnSubscriptionsChangedListener mSubscriptionChangedListener = Loading Loading @@ -1911,6 +1930,14 @@ public class AudioService extends IAudioService.Stub } onIndicateSystemReady(); synchronized (mCachedAbsVolDrivingStreamsLock) { mCachedAbsVolDrivingStreams.forEach((dev, stream) -> { mAudioSystem.setDeviceAbsoluteVolumeEnabled(dev, /*address=*/"", /*enabled=*/true, stream); }); } // indicate the end of reconfiguration phase to audio HAL AudioSystem.setParameters("restarting=false"); Loading Loading @@ -3737,8 +3764,10 @@ public class AudioService extends IAudioService.Stub int newIndex = mStreamStates[streamType].getIndex(device); int streamToDriveAbsVol = absVolumeIndexFix() ? getBluetoothContextualVolumeStream() : AudioSystem.STREAM_MUSIC; // Check if volume update should be send to AVRCP if (streamTypeAlias == AudioSystem.STREAM_MUSIC if (streamTypeAlias == streamToDriveAbsVol && AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device) && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) { if (DEBUG_VOL) { Loading Loading @@ -4540,6 +4569,8 @@ public class AudioService extends IAudioService.Stub + scoManagedByAudio()); pw.println("\tcom.android.media.audio.vgsVssSyncMuteOrder:" + vgsVssSyncMuteOrder()); pw.println("\tcom.android.media.audio.absVolumeIndexFix:" + absVolumeIndexFix()); } private void dumpAudioMode(PrintWriter pw) { Loading Loading @@ -4735,7 +4766,9 @@ public class AudioService extends IAudioService.Stub } } if (streamTypeAlias == AudioSystem.STREAM_MUSIC int streamToDriveAbsVol = absVolumeIndexFix() ? getBluetoothContextualVolumeStream() : AudioSystem.STREAM_MUSIC; if (streamTypeAlias == streamToDriveAbsVol && AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device) && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) { if (DEBUG_VOL) { Loading Loading @@ -6184,6 +6217,17 @@ public class AudioService extends IAudioService.Stub setLeAudioVolumeOnModeUpdate(mode, device, streamAlias, index, maxIndex); synchronized (mCachedAbsVolDrivingStreamsLock) { mCachedAbsVolDrivingStreams.replaceAll((absDev, stream) -> { int streamToDriveAbs = getBluetoothContextualVolumeStream(); if (stream != streamToDriveAbs) { mAudioSystem.setDeviceAbsoluteVolumeEnabled(absDev, /*address=*/ "", /*enabled*/true, streamToDriveAbs); } return streamToDriveAbs; }); } // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all SCO // connections not started by the application changing the mode when pid changes mDeviceBroker.postSetModeOwner(mode, pid, uid); Loading Loading @@ -8105,6 +8149,10 @@ public class AudioService extends IAudioService.Stub return mAudioVolumeGroup.name(); } public int getId() { return mAudioVolumeGroup.getId(); } /** * Volume group with non null minimum index are considered as non mutable, thus * bijectivity is broken with potential associated stream type. Loading Loading @@ -8755,12 +8803,17 @@ public class AudioService extends IAudioService.Stub } private int getAbsoluteVolumeIndex(int index) { if (absVolumeIndexFix()) { // The attenuation is applied in the APM. No need to manipulate the index here return index; } else { /* Special handling for Bluetooth Absolute Volume scenario * If we send full audio gain, some accessories are too loud even at its lowest * volume. We are not able to enumerate all such accessories, so here is the * workaround from phone side. * Pre-scale volume at lowest volume steps 1 2 and 3. * For volume step 0, set audio gain to 0 as some accessories won't mute on their end. * For volume step 0, set audio gain to 0 as some accessories won't mute on their * end. */ if (index == 0) { // 0% for volume 0 Loading @@ -8774,6 +8827,7 @@ public class AudioService extends IAudioService.Stub } return index; } } private void setStreamVolumeIndex(int index, int device) { // Only set audio policy BT SCO stream volume to 0 when the stream is actually muted. Loading @@ -8783,6 +8837,11 @@ public class AudioService extends IAudioService.Stub && !isFullyMuted()) { index = 1; } if (DEBUG_VOL) { Log.d(TAG, "setStreamVolumeIndexAS(" + mStreamType + ", " + index + ", " + device + ")"); } mAudioSystem.setStreamVolumeIndexAS(mStreamType, index, device); } Loading @@ -8794,14 +8853,24 @@ public class AudioService extends IAudioService.Stub } else if (isAbsoluteVolumeDevice(device) || isA2dpAbsoluteVolumeDevice(device) || AudioSystem.isLeAudioDeviceType(device)) { // do not change the volume logic for dynamic abs behavior devices like HDMI if (absVolumeIndexFix() && isAbsoluteVolumeDevice(device)) { index = getAbsoluteVolumeIndex((mIndexMax + 5) / 10); } else { index = getAbsoluteVolumeIndex((getIndex(device) + 5) / 10); } } else if (isFullVolumeDevice(device)) { index = (mIndexMax + 5)/10; } else if (device == AudioSystem.DEVICE_OUT_HEARING_AID) { if (absVolumeIndexFix()) { index = getAbsoluteVolumeIndex((getIndex(device) + 5) / 10); } else { index = (mIndexMax + 5) / 10; } } else { index = (getIndex(device) + 5)/10; } setStreamVolumeIndex(index, device); } Loading @@ -8819,11 +8888,22 @@ public class AudioService extends IAudioService.Stub || isA2dpAbsoluteVolumeDevice(device) || AudioSystem.isLeAudioDeviceType(device)) { isAbsoluteVolume = true; // do not change the volume logic for dynamic abs behavior devices // like HDMI if (absVolumeIndexFix() && isAbsoluteVolumeDevice(device)) { index = getAbsoluteVolumeIndex((mIndexMax + 5) / 10); } else { index = getAbsoluteVolumeIndex((getIndex(device) + 5) / 10); } } else if (isFullVolumeDevice(device)) { index = (mIndexMax + 5)/10; } else if (device == AudioSystem.DEVICE_OUT_HEARING_AID) { if (absVolumeIndexFix()) { isAbsoluteVolume = true; index = getAbsoluteVolumeIndex((getIndex(device) + 5) / 10); } else { index = (mIndexMax + 5) / 10; } } else { index = (mIndexMap.valueAt(i) + 5)/10; } Loading Loading @@ -9820,6 +9900,27 @@ public class AudioService extends IAudioService.Stub /*package*/ void setAvrcpAbsoluteVolumeSupported(boolean support) { mAvrcpAbsVolSupported = support; if (absVolumeIndexFix()) { int a2dpDev = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP; synchronized (mCachedAbsVolDrivingStreamsLock) { mCachedAbsVolDrivingStreams.compute(a2dpDev, (dev, stream) -> { if (stream != null && !mAvrcpAbsVolSupported) { mAudioSystem.setDeviceAbsoluteVolumeEnabled(a2dpDev, /*address=*/ "", /*enabled*/false, AudioSystem.DEVICE_NONE); return null; } // For A2DP and AVRCP we need to set the driving stream based on the // BT contextual stream. Hence, we need to make sure in adjustStreamVolume // and setStreamVolume that the driving abs volume stream is consistent. int streamToDriveAbs = getBluetoothContextualVolumeStream(); if (stream == null || stream != streamToDriveAbs) { mAudioSystem.setDeviceAbsoluteVolumeEnabled(a2dpDev, /*address=*/ "", /*enabled*/true, streamToDriveAbs); } return streamToDriveAbs; }); } } sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, mStreamStates[AudioSystem.STREAM_MUSIC], 0); Loading services/core/java/com/android/server/audio/AudioSystemAdapter.java +15 −0 Original line number Diff line number Diff line Loading @@ -597,6 +597,21 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback, return AudioSystem.getForceUse(usage); } /** * Same as {@link AudioSystem#setDeviceAbsoluteVolumeEnabled(int, String, boolean, int)} * @param nativeDeviceType the internal device type for which absolute volume is * enabled/disabled * @param address the address of the device for which absolute volume is enabled/disabled * @param enabled whether the absolute volume is enabled/disabled * @param streamToDriveAbs the stream that is controlling the absolute volume * @return status of indicating the success of this operation */ public int setDeviceAbsoluteVolumeEnabled(int nativeDeviceType, @NonNull String address, boolean enabled, int streamToDriveAbs) { return AudioSystem.setDeviceAbsoluteVolumeEnabled(nativeDeviceType, address, enabled, streamToDriveAbs); } /** * Same as {@link AudioSystem#registerPolicyMixes(ArrayList, boolean)} * @param mixes Loading services/tests/servicestests/src/com/android/server/audio/VolumeHelperTest.java +3 −1 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import static android.view.KeyEvent.ACTION_DOWN; import static android.view.KeyEvent.KEYCODE_VOLUME_UP; import static com.android.media.audio.Flags.FLAG_DISABLE_PRESCALE_ABSOLUTE_VOLUME; import static com.android.media.audio.Flags.FLAG_ABS_VOLUME_INDEX_FIX; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; Loading Loading @@ -552,7 +553,7 @@ public class VolumeHelperTest { } @Test @RequiresFlagsDisabled(FLAG_DISABLE_PRESCALE_ABSOLUTE_VOLUME) @RequiresFlagsDisabled({FLAG_DISABLE_PRESCALE_ABSOLUTE_VOLUME, FLAG_ABS_VOLUME_INDEX_FIX}) public void configurablePreScaleAbsoluteVolume_checkIndex() throws Exception { final int minIndex = mAm.getStreamMinVolume(STREAM_MUSIC); final int maxIndex = mAm.getStreamMaxVolume(STREAM_MUSIC); Loading Loading @@ -607,6 +608,7 @@ public class VolumeHelperTest { @Test @RequiresFlagsEnabled(FLAG_DISABLE_PRESCALE_ABSOLUTE_VOLUME) @RequiresFlagsDisabled(FLAG_ABS_VOLUME_INDEX_FIX) public void disablePreScaleAbsoluteVolume_checkIndex() throws Exception { final int minIndex = mAm.getStreamMinVolume(STREAM_MUSIC); final int maxIndex = mAm.getStreamMaxVolume(STREAM_MUSIC); Loading Loading
core/jni/android_media_AudioSystem.cpp +14 −0 Original line number Diff line number Diff line Loading @@ -713,6 +713,19 @@ android_media_AudioSystem_getForceUse(JNIEnv *env, jobject thiz, jint usage) AudioSystem::getForceUse(static_cast<audio_policy_force_use_t>(usage))); } static jint android_media_AudioSystem_setDeviceAbsoluteVolumeEnabled(JNIEnv *env, jobject thiz, jint device, jstring address, jboolean enabled, jint stream) { const char *c_address = env->GetStringUTFChars(address, nullptr); int state = check_AudioSystem_Command( AudioSystem::setDeviceAbsoluteVolumeEnabled(static_cast<audio_devices_t>(device), c_address, enabled, static_cast<audio_stream_type_t>(stream))); env->ReleaseStringUTFChars(address, c_address); return state; } static jint android_media_AudioSystem_initStreamVolume(JNIEnv *env, jobject thiz, jint stream, jint indexMin, jint indexMax) { Loading Loading @@ -3373,6 +3386,7 @@ static const JNINativeMethod gMethods[] = MAKE_AUDIO_SYSTEM_METHOD(setPhoneState), MAKE_AUDIO_SYSTEM_METHOD(setForceUse), MAKE_AUDIO_SYSTEM_METHOD(getForceUse), MAKE_AUDIO_SYSTEM_METHOD(setDeviceAbsoluteVolumeEnabled), MAKE_AUDIO_SYSTEM_METHOD(initStreamVolume), MAKE_AUDIO_SYSTEM_METHOD(setStreamVolumeIndex), MAKE_AUDIO_SYSTEM_METHOD(getStreamVolumeIndex), Loading
media/java/android/media/AudioSystem.java +4 −0 Original line number Diff line number Diff line Loading @@ -1764,6 +1764,10 @@ public class AudioSystem public static native int getForceUse(int usage); /** @hide */ @UnsupportedAppUsage public static native int setDeviceAbsoluteVolumeEnabled(int nativeDeviceType, @NonNull String address, boolean enabled, int streamToDriveAbs); /** @hide */ @UnsupportedAppUsage public static native int initStreamVolume(int stream, int indexMin, int indexMax); @UnsupportedAppUsage private static native int setStreamVolumeIndex(int stream, int index, int device); Loading
services/core/java/com/android/server/audio/AudioService.java +123 −22 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ import static android.provider.Settings.Secure.VOLUME_HUSH_OFF; import static android.provider.Settings.Secure.VOLUME_HUSH_VIBRATE; import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; import static com.android.media.audio.Flags.absVolumeIndexFix; import static com.android.media.audio.Flags.alarmMinVolumeZero; import static com.android.media.audio.Flags.disablePrescaleAbsoluteVolume; import static com.android.media.audio.Flags.ringerModeAffectsAlarm; Loading Loading @@ -632,6 +633,17 @@ public class AudioService extends IAudioService.Stub // If absolute volume is supported in AVRCP device private volatile boolean mAvrcpAbsVolSupported = false; private final Object mCachedAbsVolDrivingStreamsLock = new Object(); // Contains for all the device types which support absolute volume the current streams that // are driving the volume changes @GuardedBy("mCachedAbsVolDrivingStreamsLock") private final HashMap<Integer, Integer> mCachedAbsVolDrivingStreams = new HashMap<>( Map.of(AudioSystem.DEVICE_OUT_BLE_HEADSET, AudioSystem.STREAM_MUSIC, AudioSystem.DEVICE_OUT_BLE_SPEAKER, AudioSystem.STREAM_MUSIC, AudioSystem.DEVICE_OUT_BLE_BROADCAST, AudioSystem.STREAM_MUSIC, AudioSystem.DEVICE_OUT_HEARING_AID, AudioSystem.STREAM_MUSIC )); /** * Default stream type used for volume control in the absence of playback * e.g. user on homescreen, no app playing anything, presses hardware volume buttons, this Loading Loading @@ -1472,6 +1484,13 @@ public class AudioService extends IAudioService.Stub // check on volume initialization checkVolumeRangeInitialization("AudioService()"); synchronized (mCachedAbsVolDrivingStreamsLock) { mCachedAbsVolDrivingStreams.forEach((dev, stream) -> { mAudioSystem.setDeviceAbsoluteVolumeEnabled(dev, /*address=*/"", /*enabled=*/true, stream); }); } } private SubscriptionManager.OnSubscriptionsChangedListener mSubscriptionChangedListener = Loading Loading @@ -1911,6 +1930,14 @@ public class AudioService extends IAudioService.Stub } onIndicateSystemReady(); synchronized (mCachedAbsVolDrivingStreamsLock) { mCachedAbsVolDrivingStreams.forEach((dev, stream) -> { mAudioSystem.setDeviceAbsoluteVolumeEnabled(dev, /*address=*/"", /*enabled=*/true, stream); }); } // indicate the end of reconfiguration phase to audio HAL AudioSystem.setParameters("restarting=false"); Loading Loading @@ -3737,8 +3764,10 @@ public class AudioService extends IAudioService.Stub int newIndex = mStreamStates[streamType].getIndex(device); int streamToDriveAbsVol = absVolumeIndexFix() ? getBluetoothContextualVolumeStream() : AudioSystem.STREAM_MUSIC; // Check if volume update should be send to AVRCP if (streamTypeAlias == AudioSystem.STREAM_MUSIC if (streamTypeAlias == streamToDriveAbsVol && AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device) && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) { if (DEBUG_VOL) { Loading Loading @@ -4540,6 +4569,8 @@ public class AudioService extends IAudioService.Stub + scoManagedByAudio()); pw.println("\tcom.android.media.audio.vgsVssSyncMuteOrder:" + vgsVssSyncMuteOrder()); pw.println("\tcom.android.media.audio.absVolumeIndexFix:" + absVolumeIndexFix()); } private void dumpAudioMode(PrintWriter pw) { Loading Loading @@ -4735,7 +4766,9 @@ public class AudioService extends IAudioService.Stub } } if (streamTypeAlias == AudioSystem.STREAM_MUSIC int streamToDriveAbsVol = absVolumeIndexFix() ? getBluetoothContextualVolumeStream() : AudioSystem.STREAM_MUSIC; if (streamTypeAlias == streamToDriveAbsVol && AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device) && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) { if (DEBUG_VOL) { Loading Loading @@ -6184,6 +6217,17 @@ public class AudioService extends IAudioService.Stub setLeAudioVolumeOnModeUpdate(mode, device, streamAlias, index, maxIndex); synchronized (mCachedAbsVolDrivingStreamsLock) { mCachedAbsVolDrivingStreams.replaceAll((absDev, stream) -> { int streamToDriveAbs = getBluetoothContextualVolumeStream(); if (stream != streamToDriveAbs) { mAudioSystem.setDeviceAbsoluteVolumeEnabled(absDev, /*address=*/ "", /*enabled*/true, streamToDriveAbs); } return streamToDriveAbs; }); } // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all SCO // connections not started by the application changing the mode when pid changes mDeviceBroker.postSetModeOwner(mode, pid, uid); Loading Loading @@ -8105,6 +8149,10 @@ public class AudioService extends IAudioService.Stub return mAudioVolumeGroup.name(); } public int getId() { return mAudioVolumeGroup.getId(); } /** * Volume group with non null minimum index are considered as non mutable, thus * bijectivity is broken with potential associated stream type. Loading Loading @@ -8755,12 +8803,17 @@ public class AudioService extends IAudioService.Stub } private int getAbsoluteVolumeIndex(int index) { if (absVolumeIndexFix()) { // The attenuation is applied in the APM. No need to manipulate the index here return index; } else { /* Special handling for Bluetooth Absolute Volume scenario * If we send full audio gain, some accessories are too loud even at its lowest * volume. We are not able to enumerate all such accessories, so here is the * workaround from phone side. * Pre-scale volume at lowest volume steps 1 2 and 3. * For volume step 0, set audio gain to 0 as some accessories won't mute on their end. * For volume step 0, set audio gain to 0 as some accessories won't mute on their * end. */ if (index == 0) { // 0% for volume 0 Loading @@ -8774,6 +8827,7 @@ public class AudioService extends IAudioService.Stub } return index; } } private void setStreamVolumeIndex(int index, int device) { // Only set audio policy BT SCO stream volume to 0 when the stream is actually muted. Loading @@ -8783,6 +8837,11 @@ public class AudioService extends IAudioService.Stub && !isFullyMuted()) { index = 1; } if (DEBUG_VOL) { Log.d(TAG, "setStreamVolumeIndexAS(" + mStreamType + ", " + index + ", " + device + ")"); } mAudioSystem.setStreamVolumeIndexAS(mStreamType, index, device); } Loading @@ -8794,14 +8853,24 @@ public class AudioService extends IAudioService.Stub } else if (isAbsoluteVolumeDevice(device) || isA2dpAbsoluteVolumeDevice(device) || AudioSystem.isLeAudioDeviceType(device)) { // do not change the volume logic for dynamic abs behavior devices like HDMI if (absVolumeIndexFix() && isAbsoluteVolumeDevice(device)) { index = getAbsoluteVolumeIndex((mIndexMax + 5) / 10); } else { index = getAbsoluteVolumeIndex((getIndex(device) + 5) / 10); } } else if (isFullVolumeDevice(device)) { index = (mIndexMax + 5)/10; } else if (device == AudioSystem.DEVICE_OUT_HEARING_AID) { if (absVolumeIndexFix()) { index = getAbsoluteVolumeIndex((getIndex(device) + 5) / 10); } else { index = (mIndexMax + 5) / 10; } } else { index = (getIndex(device) + 5)/10; } setStreamVolumeIndex(index, device); } Loading @@ -8819,11 +8888,22 @@ public class AudioService extends IAudioService.Stub || isA2dpAbsoluteVolumeDevice(device) || AudioSystem.isLeAudioDeviceType(device)) { isAbsoluteVolume = true; // do not change the volume logic for dynamic abs behavior devices // like HDMI if (absVolumeIndexFix() && isAbsoluteVolumeDevice(device)) { index = getAbsoluteVolumeIndex((mIndexMax + 5) / 10); } else { index = getAbsoluteVolumeIndex((getIndex(device) + 5) / 10); } } else if (isFullVolumeDevice(device)) { index = (mIndexMax + 5)/10; } else if (device == AudioSystem.DEVICE_OUT_HEARING_AID) { if (absVolumeIndexFix()) { isAbsoluteVolume = true; index = getAbsoluteVolumeIndex((getIndex(device) + 5) / 10); } else { index = (mIndexMax + 5) / 10; } } else { index = (mIndexMap.valueAt(i) + 5)/10; } Loading Loading @@ -9820,6 +9900,27 @@ public class AudioService extends IAudioService.Stub /*package*/ void setAvrcpAbsoluteVolumeSupported(boolean support) { mAvrcpAbsVolSupported = support; if (absVolumeIndexFix()) { int a2dpDev = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP; synchronized (mCachedAbsVolDrivingStreamsLock) { mCachedAbsVolDrivingStreams.compute(a2dpDev, (dev, stream) -> { if (stream != null && !mAvrcpAbsVolSupported) { mAudioSystem.setDeviceAbsoluteVolumeEnabled(a2dpDev, /*address=*/ "", /*enabled*/false, AudioSystem.DEVICE_NONE); return null; } // For A2DP and AVRCP we need to set the driving stream based on the // BT contextual stream. Hence, we need to make sure in adjustStreamVolume // and setStreamVolume that the driving abs volume stream is consistent. int streamToDriveAbs = getBluetoothContextualVolumeStream(); if (stream == null || stream != streamToDriveAbs) { mAudioSystem.setDeviceAbsoluteVolumeEnabled(a2dpDev, /*address=*/ "", /*enabled*/true, streamToDriveAbs); } return streamToDriveAbs; }); } } sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, mStreamStates[AudioSystem.STREAM_MUSIC], 0); Loading
services/core/java/com/android/server/audio/AudioSystemAdapter.java +15 −0 Original line number Diff line number Diff line Loading @@ -597,6 +597,21 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback, return AudioSystem.getForceUse(usage); } /** * Same as {@link AudioSystem#setDeviceAbsoluteVolumeEnabled(int, String, boolean, int)} * @param nativeDeviceType the internal device type for which absolute volume is * enabled/disabled * @param address the address of the device for which absolute volume is enabled/disabled * @param enabled whether the absolute volume is enabled/disabled * @param streamToDriveAbs the stream that is controlling the absolute volume * @return status of indicating the success of this operation */ public int setDeviceAbsoluteVolumeEnabled(int nativeDeviceType, @NonNull String address, boolean enabled, int streamToDriveAbs) { return AudioSystem.setDeviceAbsoluteVolumeEnabled(nativeDeviceType, address, enabled, streamToDriveAbs); } /** * Same as {@link AudioSystem#registerPolicyMixes(ArrayList, boolean)} * @param mixes Loading
services/tests/servicestests/src/com/android/server/audio/VolumeHelperTest.java +3 −1 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import static android.view.KeyEvent.ACTION_DOWN; import static android.view.KeyEvent.KEYCODE_VOLUME_UP; import static com.android.media.audio.Flags.FLAG_DISABLE_PRESCALE_ABSOLUTE_VOLUME; import static com.android.media.audio.Flags.FLAG_ABS_VOLUME_INDEX_FIX; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; Loading Loading @@ -552,7 +553,7 @@ public class VolumeHelperTest { } @Test @RequiresFlagsDisabled(FLAG_DISABLE_PRESCALE_ABSOLUTE_VOLUME) @RequiresFlagsDisabled({FLAG_DISABLE_PRESCALE_ABSOLUTE_VOLUME, FLAG_ABS_VOLUME_INDEX_FIX}) public void configurablePreScaleAbsoluteVolume_checkIndex() throws Exception { final int minIndex = mAm.getStreamMinVolume(STREAM_MUSIC); final int maxIndex = mAm.getStreamMaxVolume(STREAM_MUSIC); Loading Loading @@ -607,6 +608,7 @@ public class VolumeHelperTest { @Test @RequiresFlagsEnabled(FLAG_DISABLE_PRESCALE_ABSOLUTE_VOLUME) @RequiresFlagsDisabled(FLAG_ABS_VOLUME_INDEX_FIX) public void disablePreScaleAbsoluteVolume_checkIndex() throws Exception { final int minIndex = mAm.getStreamMinVolume(STREAM_MUSIC); final int maxIndex = mAm.getStreamMaxVolume(STREAM_MUSIC); Loading