Loading android/app/src/com/android/bluetooth/vc/VolumeControlService.java +0 −3 Original line number Diff line number Diff line Loading @@ -956,9 +956,6 @@ public class VolumeControlService extends ProfileService { * Offset ids a countinous from 1 to number_of_ext_outputs*/ for (int i = 1; i <= numberOfExternalOutputs; i++) { offsets.add(i); mVolumeControlNativeInterface.getExtAudioOutVolumeOffset(device, i); mVolumeControlNativeInterface.getExtAudioOutLocation(device, i); mVolumeControlNativeInterface.getExtAudioOutDescription(device, i); } } Loading system/bta/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -676,6 +676,7 @@ cc_test { "liblog", ], static_libs: [ "bluetooth_flags_c_lib_for_test", "libbluetooth-types", "libbluetooth_crypto_toolbox", "libbluetooth_gd", Loading @@ -686,6 +687,7 @@ cc_test { "libbt_shim_ffi", "libchrome", "libgmock", "server_configurable_flags", ], sanitize: { cfi: false, Loading system/bta/vc/device.cc +63 −17 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ */ #include <bluetooth/log.h> #include <com_android_bluetooth_flags.h> #include <map> #include <vector> Loading Loading @@ -262,26 +263,50 @@ bool VolumeControlDevice::subscribe_for_notifications(tGATT_IF gatt_if, uint16_t */ bool VolumeControlDevice::EnqueueInitialRequests(tGATT_IF gatt_if, GATT_READ_OP_CB chrc_read_cb, GATT_WRITE_OP_CB cccd_write_cb) { log::debug("{}", address); std::map<uint16_t, uint16_t> hdls_to_subscribe{ {volume_state_handle, volume_state_ccc_handle}, }; handles_pending.clear(); // Status and Flags are mandatory handles_pending.insert(volume_state_handle); handles_pending.insert(volume_state_ccc_handle); if (!subscribe_for_notifications(gatt_if, volume_state_handle, volume_state_ccc_handle, cccd_write_cb)) { return false; handles_pending.insert(volume_flags_handle); if (GATT_HANDLE_IS_VALID(volume_flags_ccc_handle)) { hdls_to_subscribe[volume_flags_handle] = volume_flags_ccc_handle; handles_pending.insert(volume_flags_ccc_handle); } for (auto const& offset : audio_offsets.volume_offsets) { handles_pending.insert(offset.state_handle); hdls_to_subscribe[offset.state_handle] = offset.state_ccc_handle; handles_pending.insert(offset.state_ccc_handle); if (!subscribe_for_notifications(gatt_if, offset.state_handle, offset.state_ccc_handle, cccd_write_cb)) { return false; if (GATT_HANDLE_IS_VALID(offset.audio_descr_ccc_handle)) { hdls_to_subscribe[offset.audio_descr_handle] = offset.audio_descr_ccc_handle; handles_pending.insert(offset.audio_descr_ccc_handle); } BtaGattQueue::ReadCharacteristic(connection_id, offset.state_handle, chrc_read_cb, nullptr); if (GATT_HANDLE_IS_VALID(offset.audio_location_ccc_handle)) { hdls_to_subscribe[offset.audio_location_handle] = offset.audio_location_ccc_handle; handles_pending.insert(offset.audio_location_ccc_handle); } } for (auto const& handles : hdls_to_subscribe) { log::debug("{}, handle={:#x}, ccc_handle={:#x}", address, handles.first, handles.second); if (!subscribe_for_notifications(gatt_if, handles.first, handles.second, cccd_write_cb)) { log::error("{}, failed to subscribe for handle={:#x}, ccc_handle={:#x}", address, handles.first, handles.second); return false; } } BtaGattQueue::ReadCharacteristic(connection_id, volume_state_handle, chrc_read_cb, nullptr); BtaGattQueue::ReadCharacteristic(connection_id, volume_flags_handle, chrc_read_cb, nullptr); return true; } Loading @@ -293,21 +318,42 @@ bool VolumeControlDevice::EnqueueInitialRequests(tGATT_IF gatt_if, GATT_READ_OP_ * In each case we subscribe first to be sure we do not miss any value change. */ void VolumeControlDevice::EnqueueRemainingRequests(tGATT_IF gatt_if, GATT_READ_OP_CB chrc_read_cb, GATT_READ_MULTI_OP_CB chrc_multi_read_cb, GATT_WRITE_OP_CB cccd_write_cb) { std::map<uint16_t, uint16_t> handle_pairs{ {volume_flags_handle, volume_flags_ccc_handle}, }; std::vector<uint16_t> handles_to_read; for (auto const& offset : audio_offsets.volume_offsets) { handle_pairs[offset.audio_location_handle] = offset.audio_location_ccc_handle; handle_pairs[offset.audio_descr_handle] = offset.audio_descr_ccc_handle; handles_to_read.push_back(offset.state_handle); handles_to_read.push_back(offset.audio_location_handle); handles_to_read.push_back(offset.audio_descr_handle); } for (auto const& handles : handle_pairs) { if (GATT_HANDLE_IS_VALID(handles.second)) { subscribe_for_notifications(gatt_if, handles.first, handles.second, cccd_write_cb); log::debug("{}, number of handles={}", address, handles_to_read.size()); if (!com::android::bluetooth::flags::le_ase_read_multiple_variable()) { for (auto const& handle : handles_to_read) { BtaGattQueue::ReadCharacteristic(connection_id, handle, chrc_read_cb, nullptr); } BtaGattQueue::ReadCharacteristic(connection_id, handles.first, chrc_read_cb, nullptr); return; } size_t sent_cnt = 0; while (sent_cnt < handles_to_read.size()) { tBTA_GATTC_MULTI multi_read{}; size_t remain_cnt = (handles_to_read.size() - sent_cnt); multi_read.num_attr = remain_cnt > GATT_MAX_READ_MULTI_HANDLES ? GATT_MAX_READ_MULTI_HANDLES : remain_cnt; auto handles_begin = handles_to_read.begin() + sent_cnt; std::copy(handles_begin, handles_begin + multi_read.num_attr, multi_read.handles); sent_cnt += multi_read.num_attr; log::debug{"{}, calling multi with {} attributes, sent_cnt {} ", address, multi_read.num_attr, sent_cnt}; BtaGattQueue::ReadMultiCharacteristic(connection_id, multi_read, chrc_multi_read_cb, nullptr); } } Loading system/bta/vc/devices.h +1 −0 Original line number Diff line number Diff line Loading @@ -136,6 +136,7 @@ public: bool EnqueueInitialRequests(tGATT_IF gatt_if, GATT_READ_OP_CB chrc_read_cb, GATT_WRITE_OP_CB cccd_write_cb); void EnqueueRemainingRequests(tGATT_IF gatt_if, GATT_READ_OP_CB chrc_read_cb, GATT_READ_MULTI_OP_CB chrc_multi_read, GATT_WRITE_OP_CB cccd_write_cb); bool VerifyReady(uint16_t handle); bool IsReady() { return device_ready; } Loading system/bta/vc/devices_test.cc +85 −24 Original line number Diff line number Diff line Loading @@ -17,8 +17,10 @@ #include "bta/vc/devices.h" #include <com_android_bluetooth_flags.h> #include <gmock/gmock.h> #include <gtest/gtest.h> #include <log/log.h> #include <list> #include <map> Loading @@ -40,6 +42,7 @@ using ::testing::DoAll; using ::testing::Invoke; using ::testing::Mock; using ::testing::Return; using ::testing::SaveArg; using ::testing::SetArgPointee; using ::testing::Test; Loading @@ -52,12 +55,15 @@ RawAddress GetTestAddress(int index) { class VolumeControlDevicesTest : public ::testing::Test { protected: void SetUp() override { __android_log_set_minimum_priority(ANDROID_LOG_VERBOSE); devices_ = new VolumeControlDevices(); gatt::SetMockBtaGattInterface(&gatt_interface); gatt::SetMockBtaGattQueue(&gatt_queue); } void TearDown() override { com::android::bluetooth::flags::provider_->reset_flags(); gatt::SetMockBtaGattQueue(nullptr); gatt::SetMockBtaGattInterface(nullptr); delete devices_; Loading Loading @@ -211,6 +217,7 @@ TEST_F(VolumeControlDevicesTest, test_control_point_skip_not_connected) { class VolumeControlDeviceTest : public ::testing::Test { protected: void SetUp() override { __android_log_set_minimum_priority(ANDROID_LOG_VERBOSE); device = new VolumeControlDevice(GetTestAddress(1), true); gatt::SetMockBtaGattInterface(&gatt_interface); gatt::SetMockBtaGattQueue(&gatt_queue); Loading Loading @@ -242,9 +249,13 @@ protected: })); ON_CALL(gatt_interface, GetServices(_)).WillByDefault(Return(&services)); ON_CALL(gatt_interface, RegisterForNotifications(_, _, _)) .WillByDefault(DoAll(Return(GATT_SUCCESS))); } void TearDown() override { com::android::bluetooth::flags::provider_->reset_flags(); bluetooth::manager::SetMockBtmInterface(nullptr); gatt::SetMockBtaGattQueue(nullptr); gatt::SetMockBtaGattInterface(nullptr); Loading @@ -254,14 +265,18 @@ protected: /* sample database 1xVCS, 2xAICS, 2xVOCS */ void SetSampleDatabase1(void) { gatt::DatabaseBuilder builder; builder.AddService(0x0001, 0x0016, kVolumeControlUuid, true); builder.AddService(0x0001, 0x0017, kVolumeControlUuid, true); builder.AddIncludedService(0x0004, kVolumeOffsetUuid, 0x0060, 0x0069); builder.AddIncludedService(0x0005, kVolumeOffsetUuid, 0x0080, 0x008b); builder.AddCharacteristic(0x0010, 0x0011, kVolumeControlStateUuid, GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY); builder.AddDescriptor(0x0012, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG)); builder.AddCharacteristic(0x0013, 0x0014, kVolumeControlPointUuid, GATT_CHAR_PROP_BIT_WRITE); builder.AddCharacteristic(0x0015, 0x0016, kVolumeFlagsUuid, GATT_CHAR_PROP_BIT_READ); builder.AddCharacteristic(0x0015, 0x0016, kVolumeFlagsUuid, GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY); builder.AddDescriptor(0x0017, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG)); // First VOCS builder.AddService(0x0060, 0x0069, kVolumeOffsetUuid, false); builder.AddCharacteristic(0x0061, 0x0062, kVolumeOffsetStateUuid, GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY); Loading @@ -271,6 +286,8 @@ protected: GATT_CHAR_PROP_BIT_WRITE); builder.AddCharacteristic(0x0068, 0x0069, kVolumeOffsetOutputDescriptionUuid, GATT_CHAR_PROP_BIT_READ); // Second VOCS builder.AddService(0x0080, 0x008b, kVolumeOffsetUuid, false); builder.AddCharacteristic(0x0081, 0x0082, kVolumeOffsetStateUuid, GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY); Loading Loading @@ -432,12 +449,18 @@ TEST_F(VolumeControlDeviceTest, test_enqueue_initial_requests) { tGATT_IF gatt_if = 0x0001; std::vector<uint8_t> register_for_notification_data({0x01, 0x00}); std::map<uint16_t, uint16_t> expected_to_read_write{{0x0011, 0x0012} /* volume control state */, std::map<uint16_t, uint16_t> expected_subscribtions{ {0x0011, 0x0012} /* volume control state */, {0x0016, 0x0017} /* volume control flags */, {0x0062, 0x0063} /* volume offset state 1 */, {0x0082, 0x0083} /* volume offset state 2 */}; for (auto const& handle_pair : expected_to_read_write) { EXPECT_CALL(gatt_queue, ReadCharacteristic(_, handle_pair.first, _, _)); {0x0082, 0x0083} /* volume offset state 2 */, {0x0085, 0x0086} /* volume offset location 2 */, {0x008a, 0x008b} /* volume offset description 2 */}; // Expected read for state and flags Volume State EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0011, _, _)); EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0016, _, _)); for (auto const& handle_pair : expected_subscribtions) { EXPECT_CALL(gatt_queue, WriteDescriptor(_, handle_pair.second, register_for_notification_data, GATT_WRITE, _, _)); EXPECT_CALL(gatt_interface, RegisterForNotifications(gatt_if, _, handle_pair.first)); Loading @@ -448,6 +471,8 @@ TEST_F(VolumeControlDeviceTest, test_enqueue_initial_requests) { auto cccd_write_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, const uint8_t* value, void* data) {}; ASSERT_EQ(true, device->EnqueueInitialRequests(gatt_if, chrc_read_cb, cccd_write_cb)); Mock::VerifyAndClearExpectations(&gatt_queue); Mock::VerifyAndClearExpectations(&gatt_interface); } TEST_F(VolumeControlDeviceTest, test_device_ready) { Loading Loading @@ -487,36 +512,72 @@ TEST_F(VolumeControlDeviceTest, test_device_ready) { } TEST_F(VolumeControlDeviceTest, test_enqueue_remaining_requests) { com::android::bluetooth::flags::provider_->le_ase_read_multiple_variable(false); SetSampleDatabase1(); tGATT_IF gatt_if = 0x0001; std::vector<uint8_t> register_for_notification_data({0x01, 0x00}); std::vector<uint16_t> expected_to_read{0x0016 /* volume flags */, 0x0065 /* audio location 1 */, 0x0069 /* audio output description 1 */, 0x0085 /* audio location 1 */, 0x008a /* audio output description 1 */}; std::map<uint16_t, uint16_t> expected_to_write_value_ccc_handle_map{ {0x0085, 0x0086} /* audio location ccc 2 */, {0x008a, 0x008b} /* audio output description ccc */ }; std::vector<uint16_t> expected_to_read{ 0x0062 /* audio output state 1 */, 0x0065 /* audio output location 1 */, 0x0069 /* audio output description 1 */, 0x0082 /* audio output state 1 */, 0x0085 /* audio output location 1 */, 0x008a /* audio output description 1 */}; for (uint16_t handle : expected_to_read) { EXPECT_CALL(gatt_queue, ReadCharacteristic(_, handle, _, _)); } for (auto const& handle_pair : expected_to_write_value_ccc_handle_map) { EXPECT_CALL(gatt_queue, WriteDescriptor(_, handle_pair.second, register_for_notification_data, GATT_WRITE, _, _)); EXPECT_CALL(gatt_interface, RegisterForNotifications(gatt_if, _, handle_pair.first)); EXPECT_CALL(gatt_queue, WriteDescriptor(_, _, _, GATT_WRITE, _, _)).Times(0); EXPECT_CALL(gatt_interface, RegisterForNotifications(_, _, _)).Times(0); auto chrc_read_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, uint8_t* value, void* data) {}; auto chrc_multi_read_cb = [](uint16_t conn_id, tGATT_STATUS status, tBTA_GATTC_MULTI& handles, uint16_t len, uint8_t* value, void* data) {}; auto cccd_write_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, const uint8_t* value, void* data) {}; device->EnqueueRemainingRequests(gatt_if, chrc_read_cb, chrc_multi_read_cb, cccd_write_cb); Mock::VerifyAndClearExpectations(&gatt_queue); Mock::VerifyAndClearExpectations(&gatt_interface); } TEST_F(VolumeControlDeviceTest, test_enqueue_remaining_requests_multiread) { com::android::bluetooth::flags::provider_->le_ase_read_multiple_variable(true); SetSampleDatabase1(); tGATT_IF gatt_if = 0x0001; std::vector<uint8_t> register_for_notification_data({0x01, 0x00}); tBTA_GATTC_MULTI expected_to_read_part_1 = { .num_attr = 6, .handles = {0x0062 /* audio output state 1 */, 0x0065 /* audio output location 1 */, 0x0069 /* audio output description 1 */, 0x0082 /* audio output state 1 */, 0x0085 /* audio output location 1 */, 0x008a /* audio output description 1 */}, }; tBTA_GATTC_MULTI received_to_read_part_1{}; EXPECT_CALL(gatt_queue, ReadMultiCharacteristic(_, _, _, _)) .WillOnce(SaveArg<1>(&received_to_read_part_1)); EXPECT_CALL(gatt_queue, WriteDescriptor(_, _, _, GATT_WRITE, _, _)).Times(0); EXPECT_CALL(gatt_interface, RegisterForNotifications(_, _, _)).Times(0); auto chrc_read_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, uint8_t* value, void* data) {}; auto chrc_multi_read_cb = [](uint16_t conn_id, tGATT_STATUS status, tBTA_GATTC_MULTI& handles, uint16_t len, uint8_t* value, void* data) {}; auto cccd_write_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, const uint8_t* value, void* data) {}; device->EnqueueRemainingRequests(gatt_if, chrc_read_cb, cccd_write_cb); device->EnqueueRemainingRequests(gatt_if, chrc_read_cb, chrc_multi_read_cb, cccd_write_cb); Mock::VerifyAndClearExpectations(&gatt_queue); Mock::VerifyAndClearExpectations(&gatt_interface); ASSERT_EQ(expected_to_read_part_1.num_attr, received_to_read_part_1.num_attr); } TEST_F(VolumeControlDeviceTest, test_check_link_encrypted) { Loading Loading
android/app/src/com/android/bluetooth/vc/VolumeControlService.java +0 −3 Original line number Diff line number Diff line Loading @@ -956,9 +956,6 @@ public class VolumeControlService extends ProfileService { * Offset ids a countinous from 1 to number_of_ext_outputs*/ for (int i = 1; i <= numberOfExternalOutputs; i++) { offsets.add(i); mVolumeControlNativeInterface.getExtAudioOutVolumeOffset(device, i); mVolumeControlNativeInterface.getExtAudioOutLocation(device, i); mVolumeControlNativeInterface.getExtAudioOutDescription(device, i); } } Loading
system/bta/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -676,6 +676,7 @@ cc_test { "liblog", ], static_libs: [ "bluetooth_flags_c_lib_for_test", "libbluetooth-types", "libbluetooth_crypto_toolbox", "libbluetooth_gd", Loading @@ -686,6 +687,7 @@ cc_test { "libbt_shim_ffi", "libchrome", "libgmock", "server_configurable_flags", ], sanitize: { cfi: false, Loading
system/bta/vc/device.cc +63 −17 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ */ #include <bluetooth/log.h> #include <com_android_bluetooth_flags.h> #include <map> #include <vector> Loading Loading @@ -262,26 +263,50 @@ bool VolumeControlDevice::subscribe_for_notifications(tGATT_IF gatt_if, uint16_t */ bool VolumeControlDevice::EnqueueInitialRequests(tGATT_IF gatt_if, GATT_READ_OP_CB chrc_read_cb, GATT_WRITE_OP_CB cccd_write_cb) { log::debug("{}", address); std::map<uint16_t, uint16_t> hdls_to_subscribe{ {volume_state_handle, volume_state_ccc_handle}, }; handles_pending.clear(); // Status and Flags are mandatory handles_pending.insert(volume_state_handle); handles_pending.insert(volume_state_ccc_handle); if (!subscribe_for_notifications(gatt_if, volume_state_handle, volume_state_ccc_handle, cccd_write_cb)) { return false; handles_pending.insert(volume_flags_handle); if (GATT_HANDLE_IS_VALID(volume_flags_ccc_handle)) { hdls_to_subscribe[volume_flags_handle] = volume_flags_ccc_handle; handles_pending.insert(volume_flags_ccc_handle); } for (auto const& offset : audio_offsets.volume_offsets) { handles_pending.insert(offset.state_handle); hdls_to_subscribe[offset.state_handle] = offset.state_ccc_handle; handles_pending.insert(offset.state_ccc_handle); if (!subscribe_for_notifications(gatt_if, offset.state_handle, offset.state_ccc_handle, cccd_write_cb)) { return false; if (GATT_HANDLE_IS_VALID(offset.audio_descr_ccc_handle)) { hdls_to_subscribe[offset.audio_descr_handle] = offset.audio_descr_ccc_handle; handles_pending.insert(offset.audio_descr_ccc_handle); } BtaGattQueue::ReadCharacteristic(connection_id, offset.state_handle, chrc_read_cb, nullptr); if (GATT_HANDLE_IS_VALID(offset.audio_location_ccc_handle)) { hdls_to_subscribe[offset.audio_location_handle] = offset.audio_location_ccc_handle; handles_pending.insert(offset.audio_location_ccc_handle); } } for (auto const& handles : hdls_to_subscribe) { log::debug("{}, handle={:#x}, ccc_handle={:#x}", address, handles.first, handles.second); if (!subscribe_for_notifications(gatt_if, handles.first, handles.second, cccd_write_cb)) { log::error("{}, failed to subscribe for handle={:#x}, ccc_handle={:#x}", address, handles.first, handles.second); return false; } } BtaGattQueue::ReadCharacteristic(connection_id, volume_state_handle, chrc_read_cb, nullptr); BtaGattQueue::ReadCharacteristic(connection_id, volume_flags_handle, chrc_read_cb, nullptr); return true; } Loading @@ -293,21 +318,42 @@ bool VolumeControlDevice::EnqueueInitialRequests(tGATT_IF gatt_if, GATT_READ_OP_ * In each case we subscribe first to be sure we do not miss any value change. */ void VolumeControlDevice::EnqueueRemainingRequests(tGATT_IF gatt_if, GATT_READ_OP_CB chrc_read_cb, GATT_READ_MULTI_OP_CB chrc_multi_read_cb, GATT_WRITE_OP_CB cccd_write_cb) { std::map<uint16_t, uint16_t> handle_pairs{ {volume_flags_handle, volume_flags_ccc_handle}, }; std::vector<uint16_t> handles_to_read; for (auto const& offset : audio_offsets.volume_offsets) { handle_pairs[offset.audio_location_handle] = offset.audio_location_ccc_handle; handle_pairs[offset.audio_descr_handle] = offset.audio_descr_ccc_handle; handles_to_read.push_back(offset.state_handle); handles_to_read.push_back(offset.audio_location_handle); handles_to_read.push_back(offset.audio_descr_handle); } for (auto const& handles : handle_pairs) { if (GATT_HANDLE_IS_VALID(handles.second)) { subscribe_for_notifications(gatt_if, handles.first, handles.second, cccd_write_cb); log::debug("{}, number of handles={}", address, handles_to_read.size()); if (!com::android::bluetooth::flags::le_ase_read_multiple_variable()) { for (auto const& handle : handles_to_read) { BtaGattQueue::ReadCharacteristic(connection_id, handle, chrc_read_cb, nullptr); } BtaGattQueue::ReadCharacteristic(connection_id, handles.first, chrc_read_cb, nullptr); return; } size_t sent_cnt = 0; while (sent_cnt < handles_to_read.size()) { tBTA_GATTC_MULTI multi_read{}; size_t remain_cnt = (handles_to_read.size() - sent_cnt); multi_read.num_attr = remain_cnt > GATT_MAX_READ_MULTI_HANDLES ? GATT_MAX_READ_MULTI_HANDLES : remain_cnt; auto handles_begin = handles_to_read.begin() + sent_cnt; std::copy(handles_begin, handles_begin + multi_read.num_attr, multi_read.handles); sent_cnt += multi_read.num_attr; log::debug{"{}, calling multi with {} attributes, sent_cnt {} ", address, multi_read.num_attr, sent_cnt}; BtaGattQueue::ReadMultiCharacteristic(connection_id, multi_read, chrc_multi_read_cb, nullptr); } } Loading
system/bta/vc/devices.h +1 −0 Original line number Diff line number Diff line Loading @@ -136,6 +136,7 @@ public: bool EnqueueInitialRequests(tGATT_IF gatt_if, GATT_READ_OP_CB chrc_read_cb, GATT_WRITE_OP_CB cccd_write_cb); void EnqueueRemainingRequests(tGATT_IF gatt_if, GATT_READ_OP_CB chrc_read_cb, GATT_READ_MULTI_OP_CB chrc_multi_read, GATT_WRITE_OP_CB cccd_write_cb); bool VerifyReady(uint16_t handle); bool IsReady() { return device_ready; } Loading
system/bta/vc/devices_test.cc +85 −24 Original line number Diff line number Diff line Loading @@ -17,8 +17,10 @@ #include "bta/vc/devices.h" #include <com_android_bluetooth_flags.h> #include <gmock/gmock.h> #include <gtest/gtest.h> #include <log/log.h> #include <list> #include <map> Loading @@ -40,6 +42,7 @@ using ::testing::DoAll; using ::testing::Invoke; using ::testing::Mock; using ::testing::Return; using ::testing::SaveArg; using ::testing::SetArgPointee; using ::testing::Test; Loading @@ -52,12 +55,15 @@ RawAddress GetTestAddress(int index) { class VolumeControlDevicesTest : public ::testing::Test { protected: void SetUp() override { __android_log_set_minimum_priority(ANDROID_LOG_VERBOSE); devices_ = new VolumeControlDevices(); gatt::SetMockBtaGattInterface(&gatt_interface); gatt::SetMockBtaGattQueue(&gatt_queue); } void TearDown() override { com::android::bluetooth::flags::provider_->reset_flags(); gatt::SetMockBtaGattQueue(nullptr); gatt::SetMockBtaGattInterface(nullptr); delete devices_; Loading Loading @@ -211,6 +217,7 @@ TEST_F(VolumeControlDevicesTest, test_control_point_skip_not_connected) { class VolumeControlDeviceTest : public ::testing::Test { protected: void SetUp() override { __android_log_set_minimum_priority(ANDROID_LOG_VERBOSE); device = new VolumeControlDevice(GetTestAddress(1), true); gatt::SetMockBtaGattInterface(&gatt_interface); gatt::SetMockBtaGattQueue(&gatt_queue); Loading Loading @@ -242,9 +249,13 @@ protected: })); ON_CALL(gatt_interface, GetServices(_)).WillByDefault(Return(&services)); ON_CALL(gatt_interface, RegisterForNotifications(_, _, _)) .WillByDefault(DoAll(Return(GATT_SUCCESS))); } void TearDown() override { com::android::bluetooth::flags::provider_->reset_flags(); bluetooth::manager::SetMockBtmInterface(nullptr); gatt::SetMockBtaGattQueue(nullptr); gatt::SetMockBtaGattInterface(nullptr); Loading @@ -254,14 +265,18 @@ protected: /* sample database 1xVCS, 2xAICS, 2xVOCS */ void SetSampleDatabase1(void) { gatt::DatabaseBuilder builder; builder.AddService(0x0001, 0x0016, kVolumeControlUuid, true); builder.AddService(0x0001, 0x0017, kVolumeControlUuid, true); builder.AddIncludedService(0x0004, kVolumeOffsetUuid, 0x0060, 0x0069); builder.AddIncludedService(0x0005, kVolumeOffsetUuid, 0x0080, 0x008b); builder.AddCharacteristic(0x0010, 0x0011, kVolumeControlStateUuid, GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY); builder.AddDescriptor(0x0012, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG)); builder.AddCharacteristic(0x0013, 0x0014, kVolumeControlPointUuid, GATT_CHAR_PROP_BIT_WRITE); builder.AddCharacteristic(0x0015, 0x0016, kVolumeFlagsUuid, GATT_CHAR_PROP_BIT_READ); builder.AddCharacteristic(0x0015, 0x0016, kVolumeFlagsUuid, GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY); builder.AddDescriptor(0x0017, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG)); // First VOCS builder.AddService(0x0060, 0x0069, kVolumeOffsetUuid, false); builder.AddCharacteristic(0x0061, 0x0062, kVolumeOffsetStateUuid, GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY); Loading @@ -271,6 +286,8 @@ protected: GATT_CHAR_PROP_BIT_WRITE); builder.AddCharacteristic(0x0068, 0x0069, kVolumeOffsetOutputDescriptionUuid, GATT_CHAR_PROP_BIT_READ); // Second VOCS builder.AddService(0x0080, 0x008b, kVolumeOffsetUuid, false); builder.AddCharacteristic(0x0081, 0x0082, kVolumeOffsetStateUuid, GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY); Loading Loading @@ -432,12 +449,18 @@ TEST_F(VolumeControlDeviceTest, test_enqueue_initial_requests) { tGATT_IF gatt_if = 0x0001; std::vector<uint8_t> register_for_notification_data({0x01, 0x00}); std::map<uint16_t, uint16_t> expected_to_read_write{{0x0011, 0x0012} /* volume control state */, std::map<uint16_t, uint16_t> expected_subscribtions{ {0x0011, 0x0012} /* volume control state */, {0x0016, 0x0017} /* volume control flags */, {0x0062, 0x0063} /* volume offset state 1 */, {0x0082, 0x0083} /* volume offset state 2 */}; for (auto const& handle_pair : expected_to_read_write) { EXPECT_CALL(gatt_queue, ReadCharacteristic(_, handle_pair.first, _, _)); {0x0082, 0x0083} /* volume offset state 2 */, {0x0085, 0x0086} /* volume offset location 2 */, {0x008a, 0x008b} /* volume offset description 2 */}; // Expected read for state and flags Volume State EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0011, _, _)); EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0016, _, _)); for (auto const& handle_pair : expected_subscribtions) { EXPECT_CALL(gatt_queue, WriteDescriptor(_, handle_pair.second, register_for_notification_data, GATT_WRITE, _, _)); EXPECT_CALL(gatt_interface, RegisterForNotifications(gatt_if, _, handle_pair.first)); Loading @@ -448,6 +471,8 @@ TEST_F(VolumeControlDeviceTest, test_enqueue_initial_requests) { auto cccd_write_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, const uint8_t* value, void* data) {}; ASSERT_EQ(true, device->EnqueueInitialRequests(gatt_if, chrc_read_cb, cccd_write_cb)); Mock::VerifyAndClearExpectations(&gatt_queue); Mock::VerifyAndClearExpectations(&gatt_interface); } TEST_F(VolumeControlDeviceTest, test_device_ready) { Loading Loading @@ -487,36 +512,72 @@ TEST_F(VolumeControlDeviceTest, test_device_ready) { } TEST_F(VolumeControlDeviceTest, test_enqueue_remaining_requests) { com::android::bluetooth::flags::provider_->le_ase_read_multiple_variable(false); SetSampleDatabase1(); tGATT_IF gatt_if = 0x0001; std::vector<uint8_t> register_for_notification_data({0x01, 0x00}); std::vector<uint16_t> expected_to_read{0x0016 /* volume flags */, 0x0065 /* audio location 1 */, 0x0069 /* audio output description 1 */, 0x0085 /* audio location 1 */, 0x008a /* audio output description 1 */}; std::map<uint16_t, uint16_t> expected_to_write_value_ccc_handle_map{ {0x0085, 0x0086} /* audio location ccc 2 */, {0x008a, 0x008b} /* audio output description ccc */ }; std::vector<uint16_t> expected_to_read{ 0x0062 /* audio output state 1 */, 0x0065 /* audio output location 1 */, 0x0069 /* audio output description 1 */, 0x0082 /* audio output state 1 */, 0x0085 /* audio output location 1 */, 0x008a /* audio output description 1 */}; for (uint16_t handle : expected_to_read) { EXPECT_CALL(gatt_queue, ReadCharacteristic(_, handle, _, _)); } for (auto const& handle_pair : expected_to_write_value_ccc_handle_map) { EXPECT_CALL(gatt_queue, WriteDescriptor(_, handle_pair.second, register_for_notification_data, GATT_WRITE, _, _)); EXPECT_CALL(gatt_interface, RegisterForNotifications(gatt_if, _, handle_pair.first)); EXPECT_CALL(gatt_queue, WriteDescriptor(_, _, _, GATT_WRITE, _, _)).Times(0); EXPECT_CALL(gatt_interface, RegisterForNotifications(_, _, _)).Times(0); auto chrc_read_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, uint8_t* value, void* data) {}; auto chrc_multi_read_cb = [](uint16_t conn_id, tGATT_STATUS status, tBTA_GATTC_MULTI& handles, uint16_t len, uint8_t* value, void* data) {}; auto cccd_write_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, const uint8_t* value, void* data) {}; device->EnqueueRemainingRequests(gatt_if, chrc_read_cb, chrc_multi_read_cb, cccd_write_cb); Mock::VerifyAndClearExpectations(&gatt_queue); Mock::VerifyAndClearExpectations(&gatt_interface); } TEST_F(VolumeControlDeviceTest, test_enqueue_remaining_requests_multiread) { com::android::bluetooth::flags::provider_->le_ase_read_multiple_variable(true); SetSampleDatabase1(); tGATT_IF gatt_if = 0x0001; std::vector<uint8_t> register_for_notification_data({0x01, 0x00}); tBTA_GATTC_MULTI expected_to_read_part_1 = { .num_attr = 6, .handles = {0x0062 /* audio output state 1 */, 0x0065 /* audio output location 1 */, 0x0069 /* audio output description 1 */, 0x0082 /* audio output state 1 */, 0x0085 /* audio output location 1 */, 0x008a /* audio output description 1 */}, }; tBTA_GATTC_MULTI received_to_read_part_1{}; EXPECT_CALL(gatt_queue, ReadMultiCharacteristic(_, _, _, _)) .WillOnce(SaveArg<1>(&received_to_read_part_1)); EXPECT_CALL(gatt_queue, WriteDescriptor(_, _, _, GATT_WRITE, _, _)).Times(0); EXPECT_CALL(gatt_interface, RegisterForNotifications(_, _, _)).Times(0); auto chrc_read_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, uint8_t* value, void* data) {}; auto chrc_multi_read_cb = [](uint16_t conn_id, tGATT_STATUS status, tBTA_GATTC_MULTI& handles, uint16_t len, uint8_t* value, void* data) {}; auto cccd_write_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, const uint8_t* value, void* data) {}; device->EnqueueRemainingRequests(gatt_if, chrc_read_cb, cccd_write_cb); device->EnqueueRemainingRequests(gatt_if, chrc_read_cb, chrc_multi_read_cb, cccd_write_cb); Mock::VerifyAndClearExpectations(&gatt_queue); Mock::VerifyAndClearExpectations(&gatt_interface); ASSERT_EQ(expected_to_read_part_1.num_attr, received_to_read_part_1.num_attr); } TEST_F(VolumeControlDeviceTest, test_check_link_encrypted) { Loading