Loading android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +3 −3 Original line number Diff line number Diff line Loading @@ -415,7 +415,7 @@ public class LeAudioService extends ProfileService { sLeAudioService = instance; } private int getGroupVolume(int groupId) { private int getAudioDeviceGroupVolume(int groupId) { if (mVolumeControlService == null) { mVolumeControlService = mServiceFactory.getVolumeControlService(); if (mVolumeControlService == null) { Loading @@ -424,7 +424,7 @@ public class LeAudioService extends ProfileService { } } return mVolumeControlService.getGroupVolume(groupId); return mVolumeControlService.getAudioDeviceGroupVolume(groupId); } public boolean connect(BluetoothDevice device) { Loading Loading @@ -926,7 +926,7 @@ public class LeAudioService extends ProfileService { } int volume = IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME; if (mActiveAudioOutDevice != null) { volume = getGroupVolume(groupId); volume = getAudioDeviceGroupVolume(groupId); } mAudioManager.handleBluetoothActiveDeviceChanged(mActiveAudioOutDevice, Loading android/app/src/com/android/bluetooth/vc/VolumeControlService.java +14 −0 Original line number Diff line number Diff line Loading @@ -586,6 +586,11 @@ public class VolumeControlService extends ProfileService { * {@hide} */ public void setGroupVolume(int groupId, int volume) { if (volume < 0) { Log.w(TAG, "Tried to set invalid volume " + volume + ". Ignored."); return; } mGroupVolumeCache.put(groupId, volume); mVolumeControlNativeInterface.setGroupVolume(groupId, volume); } Loading Loading @@ -683,6 +688,15 @@ public class VolumeControlService extends ProfileService { } } /** * {@hide} */ public int getAudioDeviceGroupVolume(int groupId) { int volume = getGroupVolume(groupId); if (volume == IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME) return -1; return getDeviceVolume(getBluetoothContextualVolumeStream(), volume); } int getDeviceVolume(int streamType, int bleVolume) { int deviceMaxVolume = mAudioManager.getStreamMaxVolume(streamType); Loading android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java +2 −2 Original line number Diff line number Diff line Loading @@ -1428,7 +1428,7 @@ public class LeAudioServiceTest { //Add location support. injectAudioConfChanged(groupId, availableContexts); doReturn(-1).when(mVolumeControlService).getGroupVolume(groupId); doReturn(-1).when(mVolumeControlService).getAudioDeviceGroupVolume(groupId); //Set group and device as active. injectGroupStatusChange(groupId, LeAudioStackEvent.GROUP_STATUS_ACTIVE); Loading @@ -1445,7 +1445,7 @@ public class LeAudioServiceTest { verify(mAudioManager, times(1)).handleBluetoothActiveDeviceChanged(eq(null), any(), any(BluetoothProfileConnectionInfo.class)); doReturn(100).when(mVolumeControlService).getGroupVolume(groupId); doReturn(100).when(mVolumeControlService).getAudioDeviceGroupVolume(groupId); //Set back to active and check if last volume is restored. injectGroupStatusChange(groupId, LeAudioStackEvent.GROUP_STATUS_ACTIVE); Loading system/bta/vc/vc.cc +35 −20 Original line number Diff line number Diff line Loading @@ -743,13 +743,23 @@ class VolumeControlImpl : public VolumeControl { int group_id, bool is_autonomous, uint8_t opcode, std::vector<uint8_t>& arguments) { DLOG(INFO) << __func__ << " num of devices: " << devices.size() << " group_id: " << group_id << " is_autonomous: " << is_autonomous << " opcode: " << +opcode << " arg size: " << arguments.size(); LOG_DEBUG( "num of devices: %zu, group_id: %d, is_autonomous: %s opcode: %d, arg " "size: %zu", devices.size(), group_id, is_autonomous ? "true" : "false", +opcode, arguments.size()); if (std::find_if(ongoing_operations_.begin(), ongoing_operations_.end(), [opcode, &arguments](const VolumeOperation& op) { return (op.opcode_ == opcode) && std::equal(op.arguments_.begin(), op.arguments_.end(), arguments.begin()); }) == ongoing_operations_.end()) { ongoing_operations_.emplace_back(latest_operation_id_++, group_id, is_autonomous, opcode, arguments, devices); is_autonomous, opcode, arguments, devices); } } void MuteUnmute(std::variant<RawAddress, int> addr_or_group_id, bool mute) { Loading @@ -760,11 +770,13 @@ class VolumeControlImpl : public VolumeControl { if (std::holds_alternative<RawAddress>(addr_or_group_id)) { LOG_DEBUG("Address: %s: ", (std::get<RawAddress>(addr_or_group_id)).ToString().c_str()); std::vector<RawAddress> devices = { std::get<RawAddress>(addr_or_group_id)}; VolumeControlDevice* dev = volume_control_devices_.FindByAddress( std::get<RawAddress>(addr_or_group_id)); if (dev && dev->IsConnected()) { std::vector<RawAddress> devices = {dev->address}; PrepareVolumeControlOperation(devices, bluetooth::groups::kGroupUnknown, false, opcode, arg); } } else { /* Handle group change */ auto group_id = std::get<int>(addr_or_group_id); Loading Loading @@ -815,14 +827,17 @@ class VolumeControlImpl : public VolumeControl { uint8_t opcode = kControlPointOpcodeSetAbsoluteVolume; if (std::holds_alternative<RawAddress>(addr_or_group_id)) { DLOG(INFO) << __func__ << " " << std::get<RawAddress>(addr_or_group_id); std::vector<RawAddress> devices = { std::get<RawAddress>(addr_or_group_id)}; LOG_DEBUG("Address: %s: ", std::get<RawAddress>(addr_or_group_id).ToString().c_str()); VolumeControlDevice* dev = volume_control_devices_.FindByAddress( std::get<RawAddress>(addr_or_group_id)); if (dev && dev->IsConnected() && (dev->volume != volume)) { std::vector<RawAddress> devices = {dev->address}; RemovePendingVolumeControlOperations(devices, bluetooth::groups::kGroupUnknown); PrepareVolumeControlOperation(devices, bluetooth::groups::kGroupUnknown, false, opcode, arg); } } else { /* Handle group change */ auto group_id = std::get<int>(addr_or_group_id); Loading system/bta/vc/vc_test.cc +30 −3 Original line number Diff line number Diff line Loading @@ -915,10 +915,37 @@ class VolumeControlValueSetTest : public VolumeControlTest { }; TEST_F(VolumeControlValueSetTest, test_set_volume) { std::vector<uint8_t> expected_data({0x04, 0x00, 0x10}); EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0024, expected_data, GATT_WRITE, _, _)); ON_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0024, _, GATT_WRITE, _, _)) .WillByDefault([this](uint16_t conn_id, uint16_t handle, std::vector<uint8_t> value, tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb, void* cb_data) { std::vector<uint8_t> ntf_value({ value[2], // volume level 0, // muted static_cast<uint8_t>(value[1] + 1), // change counter }); GetNotificationEvent(0x0021, ntf_value); }); const std::vector<uint8_t> vol_x10({0x04, 0x00, 0x10}); EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0024, vol_x10, GATT_WRITE, _, _)) .Times(1); VolumeControl::Get()->SetVolume(test_address, 0x10); // Same volume level should not be applied twice const std::vector<uint8_t> vol_x10_2({0x04, 0x01, 0x10}); EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0024, vol_x10_2, GATT_WRITE, _, _)) .Times(0); VolumeControl::Get()->SetVolume(test_address, 0x10); const std::vector<uint8_t> vol_x20({0x04, 0x01, 0x20}); EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0024, vol_x20, GATT_WRITE, _, _)) .Times(1); VolumeControl::Get()->SetVolume(test_address, 0x20); } TEST_F(VolumeControlValueSetTest, test_mute) { Loading Loading
android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +3 −3 Original line number Diff line number Diff line Loading @@ -415,7 +415,7 @@ public class LeAudioService extends ProfileService { sLeAudioService = instance; } private int getGroupVolume(int groupId) { private int getAudioDeviceGroupVolume(int groupId) { if (mVolumeControlService == null) { mVolumeControlService = mServiceFactory.getVolumeControlService(); if (mVolumeControlService == null) { Loading @@ -424,7 +424,7 @@ public class LeAudioService extends ProfileService { } } return mVolumeControlService.getGroupVolume(groupId); return mVolumeControlService.getAudioDeviceGroupVolume(groupId); } public boolean connect(BluetoothDevice device) { Loading Loading @@ -926,7 +926,7 @@ public class LeAudioService extends ProfileService { } int volume = IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME; if (mActiveAudioOutDevice != null) { volume = getGroupVolume(groupId); volume = getAudioDeviceGroupVolume(groupId); } mAudioManager.handleBluetoothActiveDeviceChanged(mActiveAudioOutDevice, Loading
android/app/src/com/android/bluetooth/vc/VolumeControlService.java +14 −0 Original line number Diff line number Diff line Loading @@ -586,6 +586,11 @@ public class VolumeControlService extends ProfileService { * {@hide} */ public void setGroupVolume(int groupId, int volume) { if (volume < 0) { Log.w(TAG, "Tried to set invalid volume " + volume + ". Ignored."); return; } mGroupVolumeCache.put(groupId, volume); mVolumeControlNativeInterface.setGroupVolume(groupId, volume); } Loading Loading @@ -683,6 +688,15 @@ public class VolumeControlService extends ProfileService { } } /** * {@hide} */ public int getAudioDeviceGroupVolume(int groupId) { int volume = getGroupVolume(groupId); if (volume == IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME) return -1; return getDeviceVolume(getBluetoothContextualVolumeStream(), volume); } int getDeviceVolume(int streamType, int bleVolume) { int deviceMaxVolume = mAudioManager.getStreamMaxVolume(streamType); Loading
android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java +2 −2 Original line number Diff line number Diff line Loading @@ -1428,7 +1428,7 @@ public class LeAudioServiceTest { //Add location support. injectAudioConfChanged(groupId, availableContexts); doReturn(-1).when(mVolumeControlService).getGroupVolume(groupId); doReturn(-1).when(mVolumeControlService).getAudioDeviceGroupVolume(groupId); //Set group and device as active. injectGroupStatusChange(groupId, LeAudioStackEvent.GROUP_STATUS_ACTIVE); Loading @@ -1445,7 +1445,7 @@ public class LeAudioServiceTest { verify(mAudioManager, times(1)).handleBluetoothActiveDeviceChanged(eq(null), any(), any(BluetoothProfileConnectionInfo.class)); doReturn(100).when(mVolumeControlService).getGroupVolume(groupId); doReturn(100).when(mVolumeControlService).getAudioDeviceGroupVolume(groupId); //Set back to active and check if last volume is restored. injectGroupStatusChange(groupId, LeAudioStackEvent.GROUP_STATUS_ACTIVE); Loading
system/bta/vc/vc.cc +35 −20 Original line number Diff line number Diff line Loading @@ -743,13 +743,23 @@ class VolumeControlImpl : public VolumeControl { int group_id, bool is_autonomous, uint8_t opcode, std::vector<uint8_t>& arguments) { DLOG(INFO) << __func__ << " num of devices: " << devices.size() << " group_id: " << group_id << " is_autonomous: " << is_autonomous << " opcode: " << +opcode << " arg size: " << arguments.size(); LOG_DEBUG( "num of devices: %zu, group_id: %d, is_autonomous: %s opcode: %d, arg " "size: %zu", devices.size(), group_id, is_autonomous ? "true" : "false", +opcode, arguments.size()); if (std::find_if(ongoing_operations_.begin(), ongoing_operations_.end(), [opcode, &arguments](const VolumeOperation& op) { return (op.opcode_ == opcode) && std::equal(op.arguments_.begin(), op.arguments_.end(), arguments.begin()); }) == ongoing_operations_.end()) { ongoing_operations_.emplace_back(latest_operation_id_++, group_id, is_autonomous, opcode, arguments, devices); is_autonomous, opcode, arguments, devices); } } void MuteUnmute(std::variant<RawAddress, int> addr_or_group_id, bool mute) { Loading @@ -760,11 +770,13 @@ class VolumeControlImpl : public VolumeControl { if (std::holds_alternative<RawAddress>(addr_or_group_id)) { LOG_DEBUG("Address: %s: ", (std::get<RawAddress>(addr_or_group_id)).ToString().c_str()); std::vector<RawAddress> devices = { std::get<RawAddress>(addr_or_group_id)}; VolumeControlDevice* dev = volume_control_devices_.FindByAddress( std::get<RawAddress>(addr_or_group_id)); if (dev && dev->IsConnected()) { std::vector<RawAddress> devices = {dev->address}; PrepareVolumeControlOperation(devices, bluetooth::groups::kGroupUnknown, false, opcode, arg); } } else { /* Handle group change */ auto group_id = std::get<int>(addr_or_group_id); Loading Loading @@ -815,14 +827,17 @@ class VolumeControlImpl : public VolumeControl { uint8_t opcode = kControlPointOpcodeSetAbsoluteVolume; if (std::holds_alternative<RawAddress>(addr_or_group_id)) { DLOG(INFO) << __func__ << " " << std::get<RawAddress>(addr_or_group_id); std::vector<RawAddress> devices = { std::get<RawAddress>(addr_or_group_id)}; LOG_DEBUG("Address: %s: ", std::get<RawAddress>(addr_or_group_id).ToString().c_str()); VolumeControlDevice* dev = volume_control_devices_.FindByAddress( std::get<RawAddress>(addr_or_group_id)); if (dev && dev->IsConnected() && (dev->volume != volume)) { std::vector<RawAddress> devices = {dev->address}; RemovePendingVolumeControlOperations(devices, bluetooth::groups::kGroupUnknown); PrepareVolumeControlOperation(devices, bluetooth::groups::kGroupUnknown, false, opcode, arg); } } else { /* Handle group change */ auto group_id = std::get<int>(addr_or_group_id); Loading
system/bta/vc/vc_test.cc +30 −3 Original line number Diff line number Diff line Loading @@ -915,10 +915,37 @@ class VolumeControlValueSetTest : public VolumeControlTest { }; TEST_F(VolumeControlValueSetTest, test_set_volume) { std::vector<uint8_t> expected_data({0x04, 0x00, 0x10}); EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0024, expected_data, GATT_WRITE, _, _)); ON_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0024, _, GATT_WRITE, _, _)) .WillByDefault([this](uint16_t conn_id, uint16_t handle, std::vector<uint8_t> value, tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb, void* cb_data) { std::vector<uint8_t> ntf_value({ value[2], // volume level 0, // muted static_cast<uint8_t>(value[1] + 1), // change counter }); GetNotificationEvent(0x0021, ntf_value); }); const std::vector<uint8_t> vol_x10({0x04, 0x00, 0x10}); EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0024, vol_x10, GATT_WRITE, _, _)) .Times(1); VolumeControl::Get()->SetVolume(test_address, 0x10); // Same volume level should not be applied twice const std::vector<uint8_t> vol_x10_2({0x04, 0x01, 0x10}); EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0024, vol_x10_2, GATT_WRITE, _, _)) .Times(0); VolumeControl::Get()->SetVolume(test_address, 0x10); const std::vector<uint8_t> vol_x20({0x04, 0x01, 0x20}); EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0024, vol_x20, GATT_WRITE, _, _)) .Times(1); VolumeControl::Get()->SetVolume(test_address, 0x20); } TEST_F(VolumeControlValueSetTest, test_mute) { Loading