Loading android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +34 −19 Original line number Diff line number Diff line Loading @@ -495,17 +495,23 @@ public class LeAudioService extends ProfileService { sLeAudioService = instance; } @VisibleForTesting int getAudioDeviceGroupVolume(int groupId) { VolumeControlService getVolumeControlService() { if (mVolumeControlService == null) { mVolumeControlService = mServiceFactory.getVolumeControlService(); if (mVolumeControlService == null) { Log.e(TAG, "Volume control service is not available"); return IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME; } } return mVolumeControlService; } return mVolumeControlService.getAudioDeviceGroupVolume(groupId); @VisibleForTesting int getAudioDeviceGroupVolume(int groupId) { VolumeControlService volumeControlService = getVolumeControlService(); if (volumeControlService == null) { return IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME; } return volumeControlService.getAudioDeviceGroupVolume(groupId); } LeAudioDeviceDescriptor createDeviceDescriptor(BluetoothDevice device, Loading Loading @@ -1224,6 +1230,20 @@ public class LeAudioService extends ProfileService { | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); sendBroadcast(intent, BLUETOOTH_CONNECT); } void notifyVolumeControlServiceAboutActiveGroup(BluetoothDevice device) { VolumeControlService volumeControlService = getVolumeControlService(); if (volumeControlService == null) { return; } if (mExposedActiveDevice != null) { volumeControlService.setGroupActive(getGroupId(mExposedActiveDevice), false); } volumeControlService.setGroupActive(getGroupId(device), true); } /** * Send broadcast intent about LeAudio active device. * This is called when AudioManager confirms, LeAudio device Loading @@ -1238,6 +1258,7 @@ public class LeAudioService extends ProfileService { mAdapterService.handleActiveDeviceChange(BluetoothProfile.LE_AUDIO, device); sentActiveDeviceChangeIntent(device); notifyVolumeControlServiceAboutActiveGroup(device); mExposedActiveDevice = device; } Loading Loading @@ -2711,11 +2732,9 @@ public class LeAudioService extends ProfileService { Log.d(TAG, "setLeAudioGattClientProfilesPolicy for device " + device + " to policy=" + connectionPolicy); } if (mVolumeControlService == null) { mVolumeControlService = mServiceFactory.getVolumeControlService(); } if (mVolumeControlService != null) { mVolumeControlService.setConnectionPolicy(device, connectionPolicy); VolumeControlService volumeControlService = getVolumeControlService(); if (volumeControlService != null) { volumeControlService.setConnectionPolicy(device, connectionPolicy); } if (mHapClientService == null) { Loading Loading @@ -2812,11 +2831,9 @@ public class LeAudioService extends ProfileService { return; } if (mVolumeControlService == null) { mVolumeControlService = mServiceFactory.getVolumeControlService(); } if (mVolumeControlService != null) { mVolumeControlService.setGroupVolume(currentlyActiveGroupId, volume); VolumeControlService volumeControlService = getVolumeControlService(); if (volumeControlService != null) { volumeControlService.setGroupVolume(currentlyActiveGroupId, volume); } } Loading Loading @@ -2938,11 +2955,9 @@ public class LeAudioService extends ProfileService { } private void notifyGroupNodeAdded(BluetoothDevice device, int groupId) { if (mVolumeControlService == null) { mVolumeControlService = mServiceFactory.getVolumeControlService(); } if (mVolumeControlService != null) { mVolumeControlService.handleGroupNodeAdded(groupId, device); VolumeControlService volumeControlService = getVolumeControlService(); if (volumeControlService != null) { volumeControlService.handleGroupNodeAdded(groupId, device); } if (mLeAudioCallbacks != null) { Loading android/app/src/com/android/bluetooth/vc/VolumeControlService.java +43 −1 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.bluetooth.vc; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static com.android.bluetooth.Utils.enforceBluetoothPrivilegedPermission; import android.annotation.RequiresPermission; Loading Loading @@ -639,6 +638,30 @@ public class VolumeControlService extends ProfileService { IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME); } /** * This should be called by LeAudioService when LE Audio group change it * active state. * * @param groupId the group identifier * @param active indicator if group is active or not */ public void setGroupActive(int groupId, boolean active) { if (DBG) { Log.d(TAG, "setGroupActive: " + groupId + ", active: " + active); } if (!active) { /* For now we don't need to handle group inactivation */ return; } int groupVolume = getGroupVolume(groupId); Boolean groupMute = getGroupMute(groupId); if (groupVolume != IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME) { updateGroupCacheAndAudioSystem(groupId, groupVolume, groupMute); } } /** * @param groupId the group identifier */ Loading Loading @@ -1384,6 +1407,25 @@ public class VolumeControlService extends ProfileService { } } @Override public void setGroupActive( int groupId, boolean active, AttributionSource source, SynchronousResultReceiver receiver) { try { Objects.requireNonNull(source, "source cannot be null"); Objects.requireNonNull(receiver, "receiver cannot be null"); VolumeControlService service = getService(source); receiver.send(null); if (service != null) { service.setGroupActive(groupId, active); } } catch (RuntimeException e) { receiver.propagateException(e); } } @Override public void mute(BluetoothDevice device, AttributionSource source, Loading android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlServiceTest.java +37 −0 Original line number Diff line number Diff line Loading @@ -677,6 +677,43 @@ public class VolumeControlServiceTest { Assert.assertEquals(volume, mService.getGroupVolume(groupId)); } /** Test Active Group change */ @Test public void testActiveGroupChange() throws Exception { int groupId_1 = 1; int volume_groupId_1 = 6; int groupId_2 = 2; int volume_groupId_2 = 20; Assert.assertEquals(-1, mService.getGroupVolume(groupId_1)); Assert.assertEquals(-1, mService.getGroupVolume(groupId_2)); SynchronousResultReceiver<Void> voidRecv = SynchronousResultReceiver.get(); mServiceBinder.setGroupVolume(groupId_1, volume_groupId_1, mAttributionSource, voidRecv); voidRecv.awaitResultNoInterrupt(Duration.ofMillis(TIMEOUT_MS)); voidRecv = SynchronousResultReceiver.get(); mServiceBinder.setGroupVolume(groupId_2, volume_groupId_2, mAttributionSource, voidRecv); voidRecv.awaitResultNoInterrupt(Duration.ofMillis(TIMEOUT_MS)); voidRecv = SynchronousResultReceiver.get(); mServiceBinder.setGroupActive(groupId_1, true, mAttributionSource, voidRecv); voidRecv.awaitResultNoInterrupt(Duration.ofMillis(TIMEOUT_MS)); // Expected index for STREAM_MUSIC int expectedVol = (int) Math.round((double) (volume_groupId_1 * MEDIA_MAX_VOL) / BT_LE_AUDIO_MAX_VOL); verify(mAudioManager, times(1)).setStreamVolume(anyInt(), eq(expectedVol), anyInt()); voidRecv = SynchronousResultReceiver.get(); mServiceBinder.setGroupActive(groupId_2, true, mAttributionSource, voidRecv); expectedVol = (int) Math.round((double) (volume_groupId_2 * MEDIA_MAX_VOL) / BT_LE_AUDIO_MAX_VOL); verify(mAudioManager, times(1)).setStreamVolume(anyInt(), eq(expectedVol), anyInt()); voidRecv.awaitResultNoInterrupt(Duration.ofMillis(TIMEOUT_MS)); } /** * Test Volume Control Mute cache. */ Loading system/binder/android/bluetooth/IBluetoothVolumeControl.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,9 @@ oneway interface IBluetoothVolumeControl { void setGroupVolume(int group_id, int volume, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") void getGroupVolume(int group_id, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") void setGroupActive(int group_id, boolean active, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") void mute(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); Loading Loading
android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +34 −19 Original line number Diff line number Diff line Loading @@ -495,17 +495,23 @@ public class LeAudioService extends ProfileService { sLeAudioService = instance; } @VisibleForTesting int getAudioDeviceGroupVolume(int groupId) { VolumeControlService getVolumeControlService() { if (mVolumeControlService == null) { mVolumeControlService = mServiceFactory.getVolumeControlService(); if (mVolumeControlService == null) { Log.e(TAG, "Volume control service is not available"); return IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME; } } return mVolumeControlService; } return mVolumeControlService.getAudioDeviceGroupVolume(groupId); @VisibleForTesting int getAudioDeviceGroupVolume(int groupId) { VolumeControlService volumeControlService = getVolumeControlService(); if (volumeControlService == null) { return IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME; } return volumeControlService.getAudioDeviceGroupVolume(groupId); } LeAudioDeviceDescriptor createDeviceDescriptor(BluetoothDevice device, Loading Loading @@ -1224,6 +1230,20 @@ public class LeAudioService extends ProfileService { | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); sendBroadcast(intent, BLUETOOTH_CONNECT); } void notifyVolumeControlServiceAboutActiveGroup(BluetoothDevice device) { VolumeControlService volumeControlService = getVolumeControlService(); if (volumeControlService == null) { return; } if (mExposedActiveDevice != null) { volumeControlService.setGroupActive(getGroupId(mExposedActiveDevice), false); } volumeControlService.setGroupActive(getGroupId(device), true); } /** * Send broadcast intent about LeAudio active device. * This is called when AudioManager confirms, LeAudio device Loading @@ -1238,6 +1258,7 @@ public class LeAudioService extends ProfileService { mAdapterService.handleActiveDeviceChange(BluetoothProfile.LE_AUDIO, device); sentActiveDeviceChangeIntent(device); notifyVolumeControlServiceAboutActiveGroup(device); mExposedActiveDevice = device; } Loading Loading @@ -2711,11 +2732,9 @@ public class LeAudioService extends ProfileService { Log.d(TAG, "setLeAudioGattClientProfilesPolicy for device " + device + " to policy=" + connectionPolicy); } if (mVolumeControlService == null) { mVolumeControlService = mServiceFactory.getVolumeControlService(); } if (mVolumeControlService != null) { mVolumeControlService.setConnectionPolicy(device, connectionPolicy); VolumeControlService volumeControlService = getVolumeControlService(); if (volumeControlService != null) { volumeControlService.setConnectionPolicy(device, connectionPolicy); } if (mHapClientService == null) { Loading Loading @@ -2812,11 +2831,9 @@ public class LeAudioService extends ProfileService { return; } if (mVolumeControlService == null) { mVolumeControlService = mServiceFactory.getVolumeControlService(); } if (mVolumeControlService != null) { mVolumeControlService.setGroupVolume(currentlyActiveGroupId, volume); VolumeControlService volumeControlService = getVolumeControlService(); if (volumeControlService != null) { volumeControlService.setGroupVolume(currentlyActiveGroupId, volume); } } Loading Loading @@ -2938,11 +2955,9 @@ public class LeAudioService extends ProfileService { } private void notifyGroupNodeAdded(BluetoothDevice device, int groupId) { if (mVolumeControlService == null) { mVolumeControlService = mServiceFactory.getVolumeControlService(); } if (mVolumeControlService != null) { mVolumeControlService.handleGroupNodeAdded(groupId, device); VolumeControlService volumeControlService = getVolumeControlService(); if (volumeControlService != null) { volumeControlService.handleGroupNodeAdded(groupId, device); } if (mLeAudioCallbacks != null) { Loading
android/app/src/com/android/bluetooth/vc/VolumeControlService.java +43 −1 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.bluetooth.vc; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static com.android.bluetooth.Utils.enforceBluetoothPrivilegedPermission; import android.annotation.RequiresPermission; Loading Loading @@ -639,6 +638,30 @@ public class VolumeControlService extends ProfileService { IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME); } /** * This should be called by LeAudioService when LE Audio group change it * active state. * * @param groupId the group identifier * @param active indicator if group is active or not */ public void setGroupActive(int groupId, boolean active) { if (DBG) { Log.d(TAG, "setGroupActive: " + groupId + ", active: " + active); } if (!active) { /* For now we don't need to handle group inactivation */ return; } int groupVolume = getGroupVolume(groupId); Boolean groupMute = getGroupMute(groupId); if (groupVolume != IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME) { updateGroupCacheAndAudioSystem(groupId, groupVolume, groupMute); } } /** * @param groupId the group identifier */ Loading Loading @@ -1384,6 +1407,25 @@ public class VolumeControlService extends ProfileService { } } @Override public void setGroupActive( int groupId, boolean active, AttributionSource source, SynchronousResultReceiver receiver) { try { Objects.requireNonNull(source, "source cannot be null"); Objects.requireNonNull(receiver, "receiver cannot be null"); VolumeControlService service = getService(source); receiver.send(null); if (service != null) { service.setGroupActive(groupId, active); } } catch (RuntimeException e) { receiver.propagateException(e); } } @Override public void mute(BluetoothDevice device, AttributionSource source, Loading
android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlServiceTest.java +37 −0 Original line number Diff line number Diff line Loading @@ -677,6 +677,43 @@ public class VolumeControlServiceTest { Assert.assertEquals(volume, mService.getGroupVolume(groupId)); } /** Test Active Group change */ @Test public void testActiveGroupChange() throws Exception { int groupId_1 = 1; int volume_groupId_1 = 6; int groupId_2 = 2; int volume_groupId_2 = 20; Assert.assertEquals(-1, mService.getGroupVolume(groupId_1)); Assert.assertEquals(-1, mService.getGroupVolume(groupId_2)); SynchronousResultReceiver<Void> voidRecv = SynchronousResultReceiver.get(); mServiceBinder.setGroupVolume(groupId_1, volume_groupId_1, mAttributionSource, voidRecv); voidRecv.awaitResultNoInterrupt(Duration.ofMillis(TIMEOUT_MS)); voidRecv = SynchronousResultReceiver.get(); mServiceBinder.setGroupVolume(groupId_2, volume_groupId_2, mAttributionSource, voidRecv); voidRecv.awaitResultNoInterrupt(Duration.ofMillis(TIMEOUT_MS)); voidRecv = SynchronousResultReceiver.get(); mServiceBinder.setGroupActive(groupId_1, true, mAttributionSource, voidRecv); voidRecv.awaitResultNoInterrupt(Duration.ofMillis(TIMEOUT_MS)); // Expected index for STREAM_MUSIC int expectedVol = (int) Math.round((double) (volume_groupId_1 * MEDIA_MAX_VOL) / BT_LE_AUDIO_MAX_VOL); verify(mAudioManager, times(1)).setStreamVolume(anyInt(), eq(expectedVol), anyInt()); voidRecv = SynchronousResultReceiver.get(); mServiceBinder.setGroupActive(groupId_2, true, mAttributionSource, voidRecv); expectedVol = (int) Math.round((double) (volume_groupId_2 * MEDIA_MAX_VOL) / BT_LE_AUDIO_MAX_VOL); verify(mAudioManager, times(1)).setStreamVolume(anyInt(), eq(expectedVol), anyInt()); voidRecv.awaitResultNoInterrupt(Duration.ofMillis(TIMEOUT_MS)); } /** * Test Volume Control Mute cache. */ Loading
system/binder/android/bluetooth/IBluetoothVolumeControl.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,9 @@ oneway interface IBluetoothVolumeControl { void setGroupVolume(int group_id, int volume, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") void getGroupVolume(int group_id, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") void setGroupActive(int group_id, boolean active, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") void mute(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); Loading