Loading android/app/src/com/android/bluetooth/vc/VolumeControlService.java +3 −27 Original line number Diff line number Diff line Loading @@ -34,8 +34,6 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.media.AudioDeviceAttributes; import android.media.AudioDeviceInfo; import android.media.AudioManager; import android.os.HandlerThread; import android.os.ParcelUuid; Loading Loading @@ -170,11 +168,6 @@ public class VolumeControlService extends ProfileService { Map<Integer, Descriptor> mVolumeOffsets; } private int mMusicMaxVolume = 0; private int mMusicMinVolume = 0; private int mVoiceCallMaxVolume = 0; private int mVoiceCallMinVolume = 0; @VisibleForTesting VolumeControlNativeInterface mVolumeControlNativeInterface; @VisibleForTesting Loading Loading @@ -228,11 +221,6 @@ public class VolumeControlService extends ProfileService { Objects.requireNonNull(mAudioManager, "AudioManager cannot be null when VolumeControlService starts"); mMusicMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); mMusicMinVolume = mAudioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC); mVoiceCallMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL); mVoiceCallMinVolume = mAudioManager.getStreamMinVolume(AudioManager.STREAM_VOICE_CALL); // Start handler thread for state machines mStateMachines.clear(); mStateMachinesThread = new HandlerThread("VolumeControlService.StateMachines"); Loading Loading @@ -684,15 +672,11 @@ public class VolumeControlService extends ProfileService { } int getDeviceVolume(int streamType, int bleVolume) { int bleMaxVolume = 255; // min volume is zero int deviceMaxVolume = (streamType == AudioManager.STREAM_VOICE_CALL) ? mVoiceCallMaxVolume : mMusicMaxVolume; int deviceMinVolume = (streamType == AudioManager.STREAM_VOICE_CALL) ? mVoiceCallMinVolume : mMusicMinVolume; int deviceMaxVolume = mAudioManager.getStreamMaxVolume(streamType); // TODO: Investigate what happens in classic BT when BT volume is changed to zero. return (int) Math.floor( (double) bleVolume * (deviceMaxVolume - deviceMinVolume) / bleMaxVolume); double deviceVolume = (double) (bleVolume * deviceMaxVolume) / LE_AUDIO_MAX_VOL; return (int) Math.round(deviceVolume); } // Copied from AudioService.getBluetoothContextualVolumeStream() and modified it. Loading Loading @@ -881,14 +865,6 @@ public class VolumeControlService extends ProfileService { sm = VolumeControlStateMachine.make(device, this, mVolumeControlNativeInterface, mStateMachinesThread.getLooper()); mStateMachines.put(device, sm); mAudioManager.setDeviceVolumeBehavior( new AudioDeviceAttributes( AudioDeviceAttributes.ROLE_OUTPUT, // Currently, TYPE_BLUETOOTH_A2DP is the only thing that works. AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, ""), AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE); return sm; } } Loading android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlServiceTest.java +50 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import java.util.HashMap; import java.util.List; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeoutException; import java.util.stream.IntStream; @MediumTest @RunWith(AndroidJUnit4.class) Loading @@ -66,6 +67,11 @@ public class VolumeControlServiceTest { private BluetoothDevice mDevice; private HashMap<BluetoothDevice, LinkedBlockingQueue<Intent>> mDeviceQueueMap; private static final int TIMEOUT_MS = 1000; private static final int BT_LE_AUDIO_MAX_VOL = 255; private static final int MEDIA_MIN_VOL = 0; private static final int MEDIA_MAX_VOL = 25; private static final int CALL_MIN_VOL = 1; private static final int CALL_MAX_VOL = 8; private BroadcastReceiver mVolumeControlIntentReceiver; Loading @@ -92,6 +98,15 @@ public class VolumeControlServiceTest { mAdapter = BluetoothAdapter.getDefaultAdapter(); doReturn(MEDIA_MIN_VOL).when(mAudioManager) .getStreamMinVolume(eq(AudioManager.STREAM_MUSIC)); doReturn(MEDIA_MAX_VOL).when(mAudioManager) .getStreamMaxVolume(eq(AudioManager.STREAM_MUSIC)); doReturn(CALL_MIN_VOL).when(mAudioManager) .getStreamMinVolume(eq(AudioManager.STREAM_VOICE_CALL)); doReturn(CALL_MAX_VOL).when(mAudioManager) .getStreamMaxVolume(eq(AudioManager.STREAM_VOICE_CALL)); startService(); mService.mVolumeControlNativeInterface = mNativeInterface; mService.mAudioManager = mAudioManager; Loading Loading @@ -514,6 +529,41 @@ public class VolumeControlServiceTest { mService.messageFromNative(stackEvent); } int getLeAudioVolume(int index, int minIndex, int maxIndex, int streamType) { // Note: This has to be the same as mBtHelper.setLeAudioVolume() return (int) Math.round((double) index * BT_LE_AUDIO_MAX_VOL / maxIndex); } void testVolumeCalculations(int streamType, int minIdx, int maxIdx) { // Send a message to trigger volume state changed broadcast final VolumeControlStackEvent stackEvent = new VolumeControlStackEvent( VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED); stackEvent.device = null; stackEvent.valueInt1 = 1; // groupId stackEvent.valueBool1 = false; // isMuted stackEvent.valueBool2 = true; // isAutonomous IntStream.range(minIdx, maxIdx).forEach(idx -> { // Given the reference volume index, set the LeAudio Volume stackEvent.valueInt2 = getLeAudioVolume(idx, mAudioManager.getStreamMinVolume(streamType), mAudioManager.getStreamMaxVolume(streamType), streamType); mService.messageFromNative(stackEvent); // Verify that setting LeAudio Volume, sets the original volume index to Audio FW verify(mAudioManager, times(1)).setStreamVolume(eq(streamType), eq(idx), anyInt()); }); } @Test public void testAutonomousVolumeStateChange() { doReturn(AudioManager.MODE_IN_CALL).when(mAudioManager).getMode(); testVolumeCalculations(AudioManager.STREAM_VOICE_CALL, CALL_MIN_VOL, CALL_MAX_VOL); doReturn(AudioManager.MODE_NORMAL).when(mAudioManager).getMode(); testVolumeCalculations(AudioManager.STREAM_MUSIC, MEDIA_MIN_VOL, MEDIA_MAX_VOL); } /** * Test Volume Control cache. */ Loading Loading
android/app/src/com/android/bluetooth/vc/VolumeControlService.java +3 −27 Original line number Diff line number Diff line Loading @@ -34,8 +34,6 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.media.AudioDeviceAttributes; import android.media.AudioDeviceInfo; import android.media.AudioManager; import android.os.HandlerThread; import android.os.ParcelUuid; Loading Loading @@ -170,11 +168,6 @@ public class VolumeControlService extends ProfileService { Map<Integer, Descriptor> mVolumeOffsets; } private int mMusicMaxVolume = 0; private int mMusicMinVolume = 0; private int mVoiceCallMaxVolume = 0; private int mVoiceCallMinVolume = 0; @VisibleForTesting VolumeControlNativeInterface mVolumeControlNativeInterface; @VisibleForTesting Loading Loading @@ -228,11 +221,6 @@ public class VolumeControlService extends ProfileService { Objects.requireNonNull(mAudioManager, "AudioManager cannot be null when VolumeControlService starts"); mMusicMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); mMusicMinVolume = mAudioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC); mVoiceCallMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL); mVoiceCallMinVolume = mAudioManager.getStreamMinVolume(AudioManager.STREAM_VOICE_CALL); // Start handler thread for state machines mStateMachines.clear(); mStateMachinesThread = new HandlerThread("VolumeControlService.StateMachines"); Loading Loading @@ -684,15 +672,11 @@ public class VolumeControlService extends ProfileService { } int getDeviceVolume(int streamType, int bleVolume) { int bleMaxVolume = 255; // min volume is zero int deviceMaxVolume = (streamType == AudioManager.STREAM_VOICE_CALL) ? mVoiceCallMaxVolume : mMusicMaxVolume; int deviceMinVolume = (streamType == AudioManager.STREAM_VOICE_CALL) ? mVoiceCallMinVolume : mMusicMinVolume; int deviceMaxVolume = mAudioManager.getStreamMaxVolume(streamType); // TODO: Investigate what happens in classic BT when BT volume is changed to zero. return (int) Math.floor( (double) bleVolume * (deviceMaxVolume - deviceMinVolume) / bleMaxVolume); double deviceVolume = (double) (bleVolume * deviceMaxVolume) / LE_AUDIO_MAX_VOL; return (int) Math.round(deviceVolume); } // Copied from AudioService.getBluetoothContextualVolumeStream() and modified it. Loading Loading @@ -881,14 +865,6 @@ public class VolumeControlService extends ProfileService { sm = VolumeControlStateMachine.make(device, this, mVolumeControlNativeInterface, mStateMachinesThread.getLooper()); mStateMachines.put(device, sm); mAudioManager.setDeviceVolumeBehavior( new AudioDeviceAttributes( AudioDeviceAttributes.ROLE_OUTPUT, // Currently, TYPE_BLUETOOTH_A2DP is the only thing that works. AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, ""), AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE); return sm; } } Loading
android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlServiceTest.java +50 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import java.util.HashMap; import java.util.List; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeoutException; import java.util.stream.IntStream; @MediumTest @RunWith(AndroidJUnit4.class) Loading @@ -66,6 +67,11 @@ public class VolumeControlServiceTest { private BluetoothDevice mDevice; private HashMap<BluetoothDevice, LinkedBlockingQueue<Intent>> mDeviceQueueMap; private static final int TIMEOUT_MS = 1000; private static final int BT_LE_AUDIO_MAX_VOL = 255; private static final int MEDIA_MIN_VOL = 0; private static final int MEDIA_MAX_VOL = 25; private static final int CALL_MIN_VOL = 1; private static final int CALL_MAX_VOL = 8; private BroadcastReceiver mVolumeControlIntentReceiver; Loading @@ -92,6 +98,15 @@ public class VolumeControlServiceTest { mAdapter = BluetoothAdapter.getDefaultAdapter(); doReturn(MEDIA_MIN_VOL).when(mAudioManager) .getStreamMinVolume(eq(AudioManager.STREAM_MUSIC)); doReturn(MEDIA_MAX_VOL).when(mAudioManager) .getStreamMaxVolume(eq(AudioManager.STREAM_MUSIC)); doReturn(CALL_MIN_VOL).when(mAudioManager) .getStreamMinVolume(eq(AudioManager.STREAM_VOICE_CALL)); doReturn(CALL_MAX_VOL).when(mAudioManager) .getStreamMaxVolume(eq(AudioManager.STREAM_VOICE_CALL)); startService(); mService.mVolumeControlNativeInterface = mNativeInterface; mService.mAudioManager = mAudioManager; Loading Loading @@ -514,6 +529,41 @@ public class VolumeControlServiceTest { mService.messageFromNative(stackEvent); } int getLeAudioVolume(int index, int minIndex, int maxIndex, int streamType) { // Note: This has to be the same as mBtHelper.setLeAudioVolume() return (int) Math.round((double) index * BT_LE_AUDIO_MAX_VOL / maxIndex); } void testVolumeCalculations(int streamType, int minIdx, int maxIdx) { // Send a message to trigger volume state changed broadcast final VolumeControlStackEvent stackEvent = new VolumeControlStackEvent( VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED); stackEvent.device = null; stackEvent.valueInt1 = 1; // groupId stackEvent.valueBool1 = false; // isMuted stackEvent.valueBool2 = true; // isAutonomous IntStream.range(minIdx, maxIdx).forEach(idx -> { // Given the reference volume index, set the LeAudio Volume stackEvent.valueInt2 = getLeAudioVolume(idx, mAudioManager.getStreamMinVolume(streamType), mAudioManager.getStreamMaxVolume(streamType), streamType); mService.messageFromNative(stackEvent); // Verify that setting LeAudio Volume, sets the original volume index to Audio FW verify(mAudioManager, times(1)).setStreamVolume(eq(streamType), eq(idx), anyInt()); }); } @Test public void testAutonomousVolumeStateChange() { doReturn(AudioManager.MODE_IN_CALL).when(mAudioManager).getMode(); testVolumeCalculations(AudioManager.STREAM_VOICE_CALL, CALL_MIN_VOL, CALL_MAX_VOL); doReturn(AudioManager.MODE_NORMAL).when(mAudioManager).getMode(); testVolumeCalculations(AudioManager.STREAM_MUSIC, MEDIA_MIN_VOL, MEDIA_MAX_VOL); } /** * Test Volume Control cache. */ Loading