Loading bluetooth/aidl/vts/VtsHalBluetoothTargetTest.cpp +394 −27 Original line number Diff line number Diff line Loading @@ -46,8 +46,13 @@ static constexpr uint8_t kHciMinimumHciVersion = 5; // Bluetooth Core Specification 3.0 + HS static constexpr uint8_t kHciMinimumLmpVersion = 5; static constexpr size_t kNumHciCommandsBandwidth = 100; static constexpr size_t kNumScoPacketsBandwidth = 100; static constexpr size_t kNumAclPacketsBandwidth = 100; static constexpr std::chrono::milliseconds kWaitForInitTimeout(2000); static constexpr std::chrono::milliseconds kWaitForHciEventTimeout(2000); static constexpr std::chrono::milliseconds kWaitForScoDataTimeout(1000); static constexpr std::chrono::milliseconds kWaitForAclDataTimeout(1000); static constexpr std::chrono::milliseconds kInterfaceCloseDelayMs(200); static constexpr uint8_t kCommandHciShouldBeUnknown[] = { Loading @@ -55,15 +60,24 @@ static constexpr uint8_t kCommandHciShouldBeUnknown[] = { static constexpr uint8_t kCommandHciReadLocalVersionInformation[] = {0x01, 0x10, 0x00}; static constexpr uint8_t kCommandHciReadBufferSize[] = {0x05, 0x10, 0x00}; static constexpr uint8_t kCommandHciWriteLoopbackModeLocal[] = {0x02, 0x18, 0x01, 0x01}; static constexpr uint8_t kCommandHciReset[] = {0x03, 0x0c, 0x00}; static constexpr uint8_t kCommandHciSynchronousFlowControlEnable[] = { 0x2f, 0x0c, 0x01, 0x01}; static constexpr uint8_t kCommandHciWriteLocalName[] = {0x13, 0x0c, 0xf8}; static constexpr uint8_t kHciStatusSuccess = 0x00; static constexpr uint8_t kHciStatusUnknownHciCommand = 0x01; static constexpr uint8_t kEventConnectionComplete = 0x03; static constexpr uint8_t kEventCommandComplete = 0x0e; static constexpr uint8_t kEventCommandStatus = 0x0f; static constexpr uint8_t kEventNumberOfCompletedPackets = 0x13; static constexpr uint8_t kEventLoopbackCommand = 0x19; static constexpr size_t kEventCodeByte = 0; static constexpr size_t kEventLengthByte = 1; static constexpr size_t kEventFirstPayloadByte = 2; static constexpr size_t kEventCommandStatusStatusByte = 2; static constexpr size_t kEventCommandStatusOpcodeLsByte = 4; // Bytes 4 and 5 static constexpr size_t kEventCommandCompleteOpcodeLsByte = 3; // Bytes 3 and 4 Loading @@ -74,15 +88,33 @@ static constexpr size_t kEventLocalHciVersionByte = static constexpr size_t kEventLocalLmpVersionByte = kEventLocalHciVersionByte + 3; static constexpr size_t kEventConnectionCompleteParamLength = 11; static constexpr size_t kEventConnectionCompleteType = 11; static constexpr size_t kEventConnectionCompleteTypeSco = 0; static constexpr size_t kEventConnectionCompleteTypeAcl = 1; static constexpr size_t kEventConnectionCompleteHandleLsByte = 3; static constexpr size_t kEventNumberOfCompletedPacketsNumHandles = 2; static constexpr size_t kAclBroadcastFlagOffset = 6; static constexpr uint8_t kAclBroadcastFlagPointToPoint = 0x0; static constexpr uint8_t kAclBroadcastPointToPoint = (kAclBroadcastFlagPointToPoint << kAclBroadcastFlagOffset); static constexpr uint8_t kAclPacketBoundaryFlagOffset = 4; static constexpr uint8_t kAclPacketBoundaryFlagFirstAutoFlushable = 0x2; static constexpr uint8_t kAclPacketBoundaryFirstAutoFlushable = kAclPacketBoundaryFlagFirstAutoFlushable << kAclPacketBoundaryFlagOffset; // To discard Qualcomm ACL debugging static constexpr uint16_t kAclHandleQcaDebugMessage = 0xedc; class ThroughputLogger { public: ThroughputLogger(std::string task) : task_(task), start_time_(std::chrono::steady_clock::now()) {} : total_bytes_(0), task_(task), start_time_(std::chrono::steady_clock::now()) {} ~ThroughputLogger() { if (total_bytes_ == 0) { Loading Loading @@ -153,6 +185,7 @@ class BluetoothAidlTest : public ::testing::TestWithParam<std::string> { ASSERT_TRUE(hci->close().isOk()); std::this_thread::sleep_for(kInterfaceCloseDelayMs); handle_no_ops(); discard_qca_debugging(); EXPECT_EQ(static_cast<size_t>(0), event_queue.size()); EXPECT_EQ(static_cast<size_t>(0), sco_queue.size()); EXPECT_EQ(static_cast<size_t>(0), acl_queue.size()); Loading @@ -160,9 +193,18 @@ class BluetoothAidlTest : public ::testing::TestWithParam<std::string> { } void setBufferSizes(); void setSynchronousFlowControlEnable(); // Functions called from within tests in loopback mode void sendAndCheckHci(int num_packets); void sendAndCheckSco(int num_packets, size_t size, uint16_t handle); void sendAndCheckAcl(int num_packets, size_t size, uint16_t handle); // Helper functions to try to get a handle on verbosity void reset(); void enterLoopbackMode(); void handle_no_ops(); void discard_qca_debugging(); void wait_for_event(bool timeout_is_error); void wait_for_command_complete_event(std::vector<uint8_t> cmd); int wait_for_completed_packets_event(uint16_t handle); Loading Loading @@ -304,6 +346,9 @@ class BluetoothAidlTest : public ::testing::TestWithParam<std::string> { int max_sco_data_packet_length; int max_acl_data_packets; int max_sco_data_packets; std::vector<uint16_t> sco_connection_handles; std::vector<uint16_t> acl_connection_handles; }; // Discard NO-OPs from the event queue. Loading @@ -326,7 +371,10 @@ void BluetoothAidlTest::handle_no_ops() { break; } } } // Discard Qualcomm ACL debugging void BluetoothAidlTest::discard_qca_debugging() { while (!acl_queue.empty()) { std::vector<uint8_t> acl_packet; acl_queue.front(acl_packet); Loading @@ -344,24 +392,28 @@ void BluetoothAidlTest::handle_no_ops() { // Receive an event, discarding NO-OPs. void BluetoothAidlTest::wait_for_event(bool timeout_is_error = true) { if (timeout_is_error) { ASSERT_TRUE(event_queue.waitWithTimeout(kWaitForHciEventTimeout)); } else { event_queue.wait(); } ASSERT_LT(static_cast<size_t>(0), event_queue.size()); // Wait until we get something that's not a no-op. while (true) { bool event_ready = event_queue.waitWithTimeout(kWaitForHciEventTimeout); ASSERT_TRUE(event_ready || !timeout_is_error); if (event_queue.empty()) { // waitWithTimeout timed out return; } handle_no_ops(); if (!event_queue.empty()) { // There's an event in the queue that's not a no-op. return; } } } // Wait until a command complete is received. void BluetoothAidlTest::wait_for_command_complete_event( std::vector<uint8_t> cmd) { wait_for_event(); ASSERT_NO_FATAL_FAILURE(wait_for_event()); std::vector<uint8_t> event; ASSERT_FALSE(event_queue.empty()); ASSERT_TRUE(event_queue.pop(event)); ASSERT_GT(event.size(), static_cast<size_t>(kEventCommandCompleteStatusByte)); Loading @@ -378,7 +430,7 @@ void BluetoothAidlTest::setBufferSizes() { kCommandHciReadBufferSize + sizeof(kCommandHciReadBufferSize)}; hci->sendHciCommand(cmd); wait_for_event(); ASSERT_NO_FATAL_FAILURE(wait_for_event()); if (event_queue.empty()) { return; } Loading Loading @@ -406,6 +458,155 @@ void BluetoothAidlTest::setBufferSizes() { static_cast<int>(max_sco_data_packets)); } // Enable flow control packets for SCO void BluetoothAidlTest::setSynchronousFlowControlEnable() { std::vector<uint8_t> cmd{kCommandHciSynchronousFlowControlEnable, kCommandHciSynchronousFlowControlEnable + sizeof(kCommandHciSynchronousFlowControlEnable)}; hci->sendHciCommand(cmd); wait_for_command_complete_event(cmd); } // Send an HCI command (in Loopback mode) and check the response. void BluetoothAidlTest::sendAndCheckHci(int num_packets) { ThroughputLogger logger = {__func__}; int command_size = 0; for (int n = 0; n < num_packets; n++) { // Send an HCI packet std::vector<uint8_t> write_name{ kCommandHciWriteLocalName, kCommandHciWriteLocalName + sizeof(kCommandHciWriteLocalName)}; // With a name char new_name[] = "John Jacob Jingleheimer Schmidt ___________________0"; size_t new_name_length = strlen(new_name); for (size_t i = 0; i < new_name_length; i++) { write_name.push_back(static_cast<uint8_t>(new_name[i])); } // And the packet number size_t i = new_name_length - 1; for (int digits = n; digits > 0; digits = digits / 10, i--) { write_name[i] = static_cast<uint8_t>('0' + digits % 10); } // And padding for (size_t i = 0; i < 248 - new_name_length; i++) { write_name.push_back(static_cast<uint8_t>(0)); } hci->sendHciCommand(write_name); // Check the loopback of the HCI packet ASSERT_NO_FATAL_FAILURE(wait_for_event()); std::vector<uint8_t> event; ASSERT_TRUE(event_queue.pop(event)); size_t compare_length = (write_name.size() > static_cast<size_t>(0xff) ? static_cast<size_t>(0xff) : write_name.size()); ASSERT_GT(event.size(), compare_length + kEventFirstPayloadByte - 1); ASSERT_EQ(kEventLoopbackCommand, event[kEventCodeByte]); ASSERT_EQ(compare_length, event[kEventLengthByte]); // Don't compare past the end of the event. if (compare_length + kEventFirstPayloadByte > event.size()) { compare_length = event.size() - kEventFirstPayloadByte; ALOGE("Only comparing %d bytes", static_cast<int>(compare_length)); } if (n == num_packets - 1) { command_size = write_name.size(); } for (size_t i = 0; i < compare_length; i++) { ASSERT_EQ(write_name[i], event[kEventFirstPayloadByte + i]); } } logger.setTotalBytes(command_size * num_packets * 2); } // Send a SCO data packet (in Loopback mode) and check the response. void BluetoothAidlTest::sendAndCheckSco(int num_packets, size_t size, uint16_t handle) { ThroughputLogger logger = {__func__}; for (int n = 0; n < num_packets; n++) { // Send a SCO packet std::vector<uint8_t> sco_packet; sco_packet.push_back(static_cast<uint8_t>(handle & 0xff)); sco_packet.push_back(static_cast<uint8_t>((handle & 0x0f00) >> 8)); sco_packet.push_back(static_cast<uint8_t>(size & 0xff)); for (size_t i = 0; i < size; i++) { sco_packet.push_back(static_cast<uint8_t>(i + n)); } hci->sendScoData(sco_packet); // Check the loopback of the SCO packet std::vector<uint8_t> sco_loopback; ASSERT_TRUE( sco_queue.tryPopWithTimeout(sco_loopback, kWaitForScoDataTimeout)); ASSERT_EQ(sco_packet.size(), sco_loopback.size()); size_t successful_bytes = 0; for (size_t i = 0; i < sco_packet.size(); i++) { if (sco_packet[i] == sco_loopback[i]) { successful_bytes = i; } else { ALOGE("Miscompare at %d (expected %x, got %x)", static_cast<int>(i), sco_packet[i], sco_loopback[i]); ALOGE("At %d (expected %x, got %x)", static_cast<int>(i + 1), sco_packet[i + 1], sco_loopback[i + 1]); break; } } ASSERT_EQ(sco_packet.size(), successful_bytes + 1); } logger.setTotalBytes(num_packets * size * 2); } // Send an ACL data packet (in Loopback mode) and check the response. void BluetoothAidlTest::sendAndCheckAcl(int num_packets, size_t size, uint16_t handle) { ThroughputLogger logger = {__func__}; for (int n = 0; n < num_packets; n++) { // Send an ACL packet std::vector<uint8_t> acl_packet; acl_packet.push_back(static_cast<uint8_t>(handle & 0xff)); acl_packet.push_back(static_cast<uint8_t>((handle & 0x0f00) >> 8) | kAclBroadcastPointToPoint | kAclPacketBoundaryFirstAutoFlushable); acl_packet.push_back(static_cast<uint8_t>(size & 0xff)); acl_packet.push_back(static_cast<uint8_t>((size & 0xff00) >> 8)); for (size_t i = 0; i < size; i++) { acl_packet.push_back(static_cast<uint8_t>(i + n)); } hci->sendAclData(acl_packet); std::vector<uint8_t> acl_loopback; // Check the loopback of the ACL packet ASSERT_TRUE( acl_queue.tryPopWithTimeout(acl_loopback, kWaitForAclDataTimeout)); ASSERT_EQ(acl_packet.size(), acl_loopback.size()); size_t successful_bytes = 0; for (size_t i = 0; i < acl_packet.size(); i++) { if (acl_packet[i] == acl_loopback[i]) { successful_bytes = i; } else { ALOGE("Miscompare at %d (expected %x, got %x)", static_cast<int>(i), acl_packet[i], acl_loopback[i]); ALOGE("At %d (expected %x, got %x)", static_cast<int>(i + 1), acl_packet[i + 1], acl_loopback[i + 1]); break; } } ASSERT_EQ(acl_packet.size(), successful_bytes + 1); } logger.setTotalBytes(num_packets * size * 2); } // Return the number of completed packets reported by the controller. int BluetoothAidlTest::wait_for_completed_packets_event(uint16_t handle) { int packets_processed = 0; Loading @@ -429,11 +630,8 @@ int BluetoothAidlTest::wait_for_completed_packets_event(uint16_t handle) { return packets_processed; } // Empty test: Initialize()/Close() are called in SetUp()/TearDown(). TEST_P(BluetoothAidlTest, InitializeAndClose) {} // Send an HCI Reset with sendHciCommand and wait for a command complete event. TEST_P(BluetoothAidlTest, HciReset) { // Send the reset command and wait for a response. void BluetoothAidlTest::reset() { std::vector<uint8_t> reset{kCommandHciReset, kCommandHciReset + sizeof(kCommandHciReset)}; hci->sendHciCommand(reset); Loading @@ -441,17 +639,74 @@ TEST_P(BluetoothAidlTest, HciReset) { wait_for_command_complete_event(reset); } // Send local loopback command and initialize SCO and ACL handles. void BluetoothAidlTest::enterLoopbackMode() { std::vector<uint8_t> cmd{kCommandHciWriteLoopbackModeLocal, kCommandHciWriteLoopbackModeLocal + sizeof(kCommandHciWriteLoopbackModeLocal)}; hci->sendHciCommand(cmd); // Receive connection complete events with data channels int connection_event_count = 0; bool command_complete_received = false; while (true) { wait_for_event(false); if (event_queue.empty()) { // Fail if there was no event received or no connections completed. ASSERT_TRUE(command_complete_received); ASSERT_LT(0, connection_event_count); return; } std::vector<uint8_t> event; ASSERT_TRUE(event_queue.pop(event)); ASSERT_GT(event.size(), static_cast<size_t>(kEventCommandCompleteStatusByte)); if (event[kEventCodeByte] == kEventConnectionComplete) { ASSERT_GT(event.size(), static_cast<size_t>(kEventConnectionCompleteType)); ASSERT_EQ(event[kEventLengthByte], kEventConnectionCompleteParamLength); uint8_t connection_type = event[kEventConnectionCompleteType]; ASSERT_TRUE(connection_type == kEventConnectionCompleteTypeSco || connection_type == kEventConnectionCompleteTypeAcl); // Save handles uint16_t handle = event[kEventConnectionCompleteHandleLsByte] | event[kEventConnectionCompleteHandleLsByte + 1] << 8; if (connection_type == kEventConnectionCompleteTypeSco) { sco_connection_handles.push_back(handle); } else { acl_connection_handles.push_back(handle); } ALOGD("Connect complete type = %d handle = %d", event[kEventConnectionCompleteType], handle); connection_event_count++; } else { ASSERT_EQ(kEventCommandComplete, event[kEventCodeByte]); ASSERT_EQ(cmd[0], event[kEventCommandCompleteOpcodeLsByte]); ASSERT_EQ(cmd[1], event[kEventCommandCompleteOpcodeLsByte + 1]); ASSERT_EQ(kHciStatusSuccess, event[kEventCommandCompleteStatusByte]); command_complete_received = true; } } } // Empty test: Initialize()/Close() are called in SetUp()/TearDown(). TEST_P(BluetoothAidlTest, InitializeAndClose) {} // Send an HCI Reset with sendHciCommand and wait for a command complete event. TEST_P(BluetoothAidlTest, HciReset) { reset(); } // Read and check the HCI version of the controller. TEST_P(BluetoothAidlTest, HciVersionTest) { reset(); std::vector<uint8_t> cmd{kCommandHciReadLocalVersionInformation, kCommandHciReadLocalVersionInformation + sizeof(kCommandHciReadLocalVersionInformation)}; hci->sendHciCommand(cmd); wait_for_event(); if (event_queue.empty()) { return; } ASSERT_NO_FATAL_FAILURE(wait_for_event()); std::vector<uint8_t> event; ASSERT_TRUE(event_queue.pop(event)); Loading @@ -468,15 +723,13 @@ TEST_P(BluetoothAidlTest, HciVersionTest) { // Send an unknown HCI command and wait for the error message. TEST_P(BluetoothAidlTest, HciUnknownCommand) { reset(); std::vector<uint8_t> cmd{ kCommandHciShouldBeUnknown, kCommandHciShouldBeUnknown + sizeof(kCommandHciShouldBeUnknown)}; hci->sendHciCommand(cmd); wait_for_event(); if (event_queue.empty()) { return; } ASSERT_NO_FATAL_FAILURE(wait_for_event()); std::vector<uint8_t> event; ASSERT_TRUE(event_queue.pop(event)); Loading @@ -496,8 +749,121 @@ TEST_P(BluetoothAidlTest, HciUnknownCommand) { } } // Enter loopback mode, but don't send any packets. TEST_P(BluetoothAidlTest, WriteLoopbackMode) { reset(); enterLoopbackMode(); } // Enter loopback mode and send a single command. TEST_P(BluetoothAidlTest, LoopbackModeSingleCommand) { reset(); setBufferSizes(); enterLoopbackMode(); sendAndCheckHci(1); } // Enter loopback mode and send a single SCO packet. TEST_P(BluetoothAidlTest, LoopbackModeSingleSco) { reset(); setBufferSizes(); setSynchronousFlowControlEnable(); enterLoopbackMode(); if (!sco_connection_handles.empty()) { ASSERT_LT(0, max_sco_data_packet_length); sendAndCheckSco(1, max_sco_data_packet_length, sco_connection_handles[0]); int sco_packets_sent = 1; int completed_packets = wait_for_completed_packets_event(sco_connection_handles[0]); if (sco_packets_sent != completed_packets) { ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__, sco_packets_sent, completed_packets); } } } // Enter loopback mode and send a single ACL packet. TEST_P(BluetoothAidlTest, LoopbackModeSingleAcl) { reset(); setBufferSizes(); enterLoopbackMode(); if (!acl_connection_handles.empty()) { ASSERT_LT(0, max_acl_data_packet_length); sendAndCheckAcl(1, max_acl_data_packet_length - 1, acl_connection_handles[0]); int acl_packets_sent = 1; int completed_packets = wait_for_completed_packets_event(acl_connection_handles[0]); if (acl_packets_sent != completed_packets) { ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__, acl_packets_sent, completed_packets); } } ASSERT_GE(acl_cb_count, 1); } // Enter loopback mode and send command packets for bandwidth measurements. TEST_P(BluetoothAidlTest, LoopbackModeCommandBandwidth) { reset(); setBufferSizes(); enterLoopbackMode(); sendAndCheckHci(kNumHciCommandsBandwidth); } // Enter loopback mode and send SCO packets for bandwidth measurements. TEST_P(BluetoothAidlTest, LoopbackModeScoBandwidth) { reset(); setBufferSizes(); setSynchronousFlowControlEnable(); enterLoopbackMode(); if (!sco_connection_handles.empty()) { ASSERT_LT(0, max_sco_data_packet_length); sendAndCheckSco(kNumScoPacketsBandwidth, max_sco_data_packet_length, sco_connection_handles[0]); int sco_packets_sent = kNumScoPacketsBandwidth; int completed_packets = wait_for_completed_packets_event(sco_connection_handles[0]); if (sco_packets_sent != completed_packets) { ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__, sco_packets_sent, completed_packets); } } } // Enter loopback mode and send packets for ACL bandwidth measurements. TEST_P(BluetoothAidlTest, LoopbackModeAclBandwidth) { reset(); setBufferSizes(); enterLoopbackMode(); if (!acl_connection_handles.empty()) { ASSERT_LT(0, max_acl_data_packet_length); sendAndCheckAcl(kNumAclPacketsBandwidth, max_acl_data_packet_length - 1, acl_connection_handles[0]); int acl_packets_sent = kNumAclPacketsBandwidth; int completed_packets = wait_for_completed_packets_event(acl_connection_handles[0]); if (acl_packets_sent != completed_packets) { ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__, acl_packets_sent, completed_packets); } } } // Set all bits in the event mask TEST_P(BluetoothAidlTest, SetEventMask) { reset(); std::vector<uint8_t> set_event_mask{ 0x01, 0x0c, 0x08 /*parameter bytes*/, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; Loading @@ -507,6 +873,7 @@ TEST_P(BluetoothAidlTest, SetEventMask) { // Set all bits in the LE event mask TEST_P(BluetoothAidlTest, SetLeEventMask) { reset(); std::vector<uint8_t> set_event_mask{ 0x20, 0x0c, 0x08 /*parameter bytes*/, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; Loading Loading
bluetooth/aidl/vts/VtsHalBluetoothTargetTest.cpp +394 −27 Original line number Diff line number Diff line Loading @@ -46,8 +46,13 @@ static constexpr uint8_t kHciMinimumHciVersion = 5; // Bluetooth Core Specification 3.0 + HS static constexpr uint8_t kHciMinimumLmpVersion = 5; static constexpr size_t kNumHciCommandsBandwidth = 100; static constexpr size_t kNumScoPacketsBandwidth = 100; static constexpr size_t kNumAclPacketsBandwidth = 100; static constexpr std::chrono::milliseconds kWaitForInitTimeout(2000); static constexpr std::chrono::milliseconds kWaitForHciEventTimeout(2000); static constexpr std::chrono::milliseconds kWaitForScoDataTimeout(1000); static constexpr std::chrono::milliseconds kWaitForAclDataTimeout(1000); static constexpr std::chrono::milliseconds kInterfaceCloseDelayMs(200); static constexpr uint8_t kCommandHciShouldBeUnknown[] = { Loading @@ -55,15 +60,24 @@ static constexpr uint8_t kCommandHciShouldBeUnknown[] = { static constexpr uint8_t kCommandHciReadLocalVersionInformation[] = {0x01, 0x10, 0x00}; static constexpr uint8_t kCommandHciReadBufferSize[] = {0x05, 0x10, 0x00}; static constexpr uint8_t kCommandHciWriteLoopbackModeLocal[] = {0x02, 0x18, 0x01, 0x01}; static constexpr uint8_t kCommandHciReset[] = {0x03, 0x0c, 0x00}; static constexpr uint8_t kCommandHciSynchronousFlowControlEnable[] = { 0x2f, 0x0c, 0x01, 0x01}; static constexpr uint8_t kCommandHciWriteLocalName[] = {0x13, 0x0c, 0xf8}; static constexpr uint8_t kHciStatusSuccess = 0x00; static constexpr uint8_t kHciStatusUnknownHciCommand = 0x01; static constexpr uint8_t kEventConnectionComplete = 0x03; static constexpr uint8_t kEventCommandComplete = 0x0e; static constexpr uint8_t kEventCommandStatus = 0x0f; static constexpr uint8_t kEventNumberOfCompletedPackets = 0x13; static constexpr uint8_t kEventLoopbackCommand = 0x19; static constexpr size_t kEventCodeByte = 0; static constexpr size_t kEventLengthByte = 1; static constexpr size_t kEventFirstPayloadByte = 2; static constexpr size_t kEventCommandStatusStatusByte = 2; static constexpr size_t kEventCommandStatusOpcodeLsByte = 4; // Bytes 4 and 5 static constexpr size_t kEventCommandCompleteOpcodeLsByte = 3; // Bytes 3 and 4 Loading @@ -74,15 +88,33 @@ static constexpr size_t kEventLocalHciVersionByte = static constexpr size_t kEventLocalLmpVersionByte = kEventLocalHciVersionByte + 3; static constexpr size_t kEventConnectionCompleteParamLength = 11; static constexpr size_t kEventConnectionCompleteType = 11; static constexpr size_t kEventConnectionCompleteTypeSco = 0; static constexpr size_t kEventConnectionCompleteTypeAcl = 1; static constexpr size_t kEventConnectionCompleteHandleLsByte = 3; static constexpr size_t kEventNumberOfCompletedPacketsNumHandles = 2; static constexpr size_t kAclBroadcastFlagOffset = 6; static constexpr uint8_t kAclBroadcastFlagPointToPoint = 0x0; static constexpr uint8_t kAclBroadcastPointToPoint = (kAclBroadcastFlagPointToPoint << kAclBroadcastFlagOffset); static constexpr uint8_t kAclPacketBoundaryFlagOffset = 4; static constexpr uint8_t kAclPacketBoundaryFlagFirstAutoFlushable = 0x2; static constexpr uint8_t kAclPacketBoundaryFirstAutoFlushable = kAclPacketBoundaryFlagFirstAutoFlushable << kAclPacketBoundaryFlagOffset; // To discard Qualcomm ACL debugging static constexpr uint16_t kAclHandleQcaDebugMessage = 0xedc; class ThroughputLogger { public: ThroughputLogger(std::string task) : task_(task), start_time_(std::chrono::steady_clock::now()) {} : total_bytes_(0), task_(task), start_time_(std::chrono::steady_clock::now()) {} ~ThroughputLogger() { if (total_bytes_ == 0) { Loading Loading @@ -153,6 +185,7 @@ class BluetoothAidlTest : public ::testing::TestWithParam<std::string> { ASSERT_TRUE(hci->close().isOk()); std::this_thread::sleep_for(kInterfaceCloseDelayMs); handle_no_ops(); discard_qca_debugging(); EXPECT_EQ(static_cast<size_t>(0), event_queue.size()); EXPECT_EQ(static_cast<size_t>(0), sco_queue.size()); EXPECT_EQ(static_cast<size_t>(0), acl_queue.size()); Loading @@ -160,9 +193,18 @@ class BluetoothAidlTest : public ::testing::TestWithParam<std::string> { } void setBufferSizes(); void setSynchronousFlowControlEnable(); // Functions called from within tests in loopback mode void sendAndCheckHci(int num_packets); void sendAndCheckSco(int num_packets, size_t size, uint16_t handle); void sendAndCheckAcl(int num_packets, size_t size, uint16_t handle); // Helper functions to try to get a handle on verbosity void reset(); void enterLoopbackMode(); void handle_no_ops(); void discard_qca_debugging(); void wait_for_event(bool timeout_is_error); void wait_for_command_complete_event(std::vector<uint8_t> cmd); int wait_for_completed_packets_event(uint16_t handle); Loading Loading @@ -304,6 +346,9 @@ class BluetoothAidlTest : public ::testing::TestWithParam<std::string> { int max_sco_data_packet_length; int max_acl_data_packets; int max_sco_data_packets; std::vector<uint16_t> sco_connection_handles; std::vector<uint16_t> acl_connection_handles; }; // Discard NO-OPs from the event queue. Loading @@ -326,7 +371,10 @@ void BluetoothAidlTest::handle_no_ops() { break; } } } // Discard Qualcomm ACL debugging void BluetoothAidlTest::discard_qca_debugging() { while (!acl_queue.empty()) { std::vector<uint8_t> acl_packet; acl_queue.front(acl_packet); Loading @@ -344,24 +392,28 @@ void BluetoothAidlTest::handle_no_ops() { // Receive an event, discarding NO-OPs. void BluetoothAidlTest::wait_for_event(bool timeout_is_error = true) { if (timeout_is_error) { ASSERT_TRUE(event_queue.waitWithTimeout(kWaitForHciEventTimeout)); } else { event_queue.wait(); } ASSERT_LT(static_cast<size_t>(0), event_queue.size()); // Wait until we get something that's not a no-op. while (true) { bool event_ready = event_queue.waitWithTimeout(kWaitForHciEventTimeout); ASSERT_TRUE(event_ready || !timeout_is_error); if (event_queue.empty()) { // waitWithTimeout timed out return; } handle_no_ops(); if (!event_queue.empty()) { // There's an event in the queue that's not a no-op. return; } } } // Wait until a command complete is received. void BluetoothAidlTest::wait_for_command_complete_event( std::vector<uint8_t> cmd) { wait_for_event(); ASSERT_NO_FATAL_FAILURE(wait_for_event()); std::vector<uint8_t> event; ASSERT_FALSE(event_queue.empty()); ASSERT_TRUE(event_queue.pop(event)); ASSERT_GT(event.size(), static_cast<size_t>(kEventCommandCompleteStatusByte)); Loading @@ -378,7 +430,7 @@ void BluetoothAidlTest::setBufferSizes() { kCommandHciReadBufferSize + sizeof(kCommandHciReadBufferSize)}; hci->sendHciCommand(cmd); wait_for_event(); ASSERT_NO_FATAL_FAILURE(wait_for_event()); if (event_queue.empty()) { return; } Loading Loading @@ -406,6 +458,155 @@ void BluetoothAidlTest::setBufferSizes() { static_cast<int>(max_sco_data_packets)); } // Enable flow control packets for SCO void BluetoothAidlTest::setSynchronousFlowControlEnable() { std::vector<uint8_t> cmd{kCommandHciSynchronousFlowControlEnable, kCommandHciSynchronousFlowControlEnable + sizeof(kCommandHciSynchronousFlowControlEnable)}; hci->sendHciCommand(cmd); wait_for_command_complete_event(cmd); } // Send an HCI command (in Loopback mode) and check the response. void BluetoothAidlTest::sendAndCheckHci(int num_packets) { ThroughputLogger logger = {__func__}; int command_size = 0; for (int n = 0; n < num_packets; n++) { // Send an HCI packet std::vector<uint8_t> write_name{ kCommandHciWriteLocalName, kCommandHciWriteLocalName + sizeof(kCommandHciWriteLocalName)}; // With a name char new_name[] = "John Jacob Jingleheimer Schmidt ___________________0"; size_t new_name_length = strlen(new_name); for (size_t i = 0; i < new_name_length; i++) { write_name.push_back(static_cast<uint8_t>(new_name[i])); } // And the packet number size_t i = new_name_length - 1; for (int digits = n; digits > 0; digits = digits / 10, i--) { write_name[i] = static_cast<uint8_t>('0' + digits % 10); } // And padding for (size_t i = 0; i < 248 - new_name_length; i++) { write_name.push_back(static_cast<uint8_t>(0)); } hci->sendHciCommand(write_name); // Check the loopback of the HCI packet ASSERT_NO_FATAL_FAILURE(wait_for_event()); std::vector<uint8_t> event; ASSERT_TRUE(event_queue.pop(event)); size_t compare_length = (write_name.size() > static_cast<size_t>(0xff) ? static_cast<size_t>(0xff) : write_name.size()); ASSERT_GT(event.size(), compare_length + kEventFirstPayloadByte - 1); ASSERT_EQ(kEventLoopbackCommand, event[kEventCodeByte]); ASSERT_EQ(compare_length, event[kEventLengthByte]); // Don't compare past the end of the event. if (compare_length + kEventFirstPayloadByte > event.size()) { compare_length = event.size() - kEventFirstPayloadByte; ALOGE("Only comparing %d bytes", static_cast<int>(compare_length)); } if (n == num_packets - 1) { command_size = write_name.size(); } for (size_t i = 0; i < compare_length; i++) { ASSERT_EQ(write_name[i], event[kEventFirstPayloadByte + i]); } } logger.setTotalBytes(command_size * num_packets * 2); } // Send a SCO data packet (in Loopback mode) and check the response. void BluetoothAidlTest::sendAndCheckSco(int num_packets, size_t size, uint16_t handle) { ThroughputLogger logger = {__func__}; for (int n = 0; n < num_packets; n++) { // Send a SCO packet std::vector<uint8_t> sco_packet; sco_packet.push_back(static_cast<uint8_t>(handle & 0xff)); sco_packet.push_back(static_cast<uint8_t>((handle & 0x0f00) >> 8)); sco_packet.push_back(static_cast<uint8_t>(size & 0xff)); for (size_t i = 0; i < size; i++) { sco_packet.push_back(static_cast<uint8_t>(i + n)); } hci->sendScoData(sco_packet); // Check the loopback of the SCO packet std::vector<uint8_t> sco_loopback; ASSERT_TRUE( sco_queue.tryPopWithTimeout(sco_loopback, kWaitForScoDataTimeout)); ASSERT_EQ(sco_packet.size(), sco_loopback.size()); size_t successful_bytes = 0; for (size_t i = 0; i < sco_packet.size(); i++) { if (sco_packet[i] == sco_loopback[i]) { successful_bytes = i; } else { ALOGE("Miscompare at %d (expected %x, got %x)", static_cast<int>(i), sco_packet[i], sco_loopback[i]); ALOGE("At %d (expected %x, got %x)", static_cast<int>(i + 1), sco_packet[i + 1], sco_loopback[i + 1]); break; } } ASSERT_EQ(sco_packet.size(), successful_bytes + 1); } logger.setTotalBytes(num_packets * size * 2); } // Send an ACL data packet (in Loopback mode) and check the response. void BluetoothAidlTest::sendAndCheckAcl(int num_packets, size_t size, uint16_t handle) { ThroughputLogger logger = {__func__}; for (int n = 0; n < num_packets; n++) { // Send an ACL packet std::vector<uint8_t> acl_packet; acl_packet.push_back(static_cast<uint8_t>(handle & 0xff)); acl_packet.push_back(static_cast<uint8_t>((handle & 0x0f00) >> 8) | kAclBroadcastPointToPoint | kAclPacketBoundaryFirstAutoFlushable); acl_packet.push_back(static_cast<uint8_t>(size & 0xff)); acl_packet.push_back(static_cast<uint8_t>((size & 0xff00) >> 8)); for (size_t i = 0; i < size; i++) { acl_packet.push_back(static_cast<uint8_t>(i + n)); } hci->sendAclData(acl_packet); std::vector<uint8_t> acl_loopback; // Check the loopback of the ACL packet ASSERT_TRUE( acl_queue.tryPopWithTimeout(acl_loopback, kWaitForAclDataTimeout)); ASSERT_EQ(acl_packet.size(), acl_loopback.size()); size_t successful_bytes = 0; for (size_t i = 0; i < acl_packet.size(); i++) { if (acl_packet[i] == acl_loopback[i]) { successful_bytes = i; } else { ALOGE("Miscompare at %d (expected %x, got %x)", static_cast<int>(i), acl_packet[i], acl_loopback[i]); ALOGE("At %d (expected %x, got %x)", static_cast<int>(i + 1), acl_packet[i + 1], acl_loopback[i + 1]); break; } } ASSERT_EQ(acl_packet.size(), successful_bytes + 1); } logger.setTotalBytes(num_packets * size * 2); } // Return the number of completed packets reported by the controller. int BluetoothAidlTest::wait_for_completed_packets_event(uint16_t handle) { int packets_processed = 0; Loading @@ -429,11 +630,8 @@ int BluetoothAidlTest::wait_for_completed_packets_event(uint16_t handle) { return packets_processed; } // Empty test: Initialize()/Close() are called in SetUp()/TearDown(). TEST_P(BluetoothAidlTest, InitializeAndClose) {} // Send an HCI Reset with sendHciCommand and wait for a command complete event. TEST_P(BluetoothAidlTest, HciReset) { // Send the reset command and wait for a response. void BluetoothAidlTest::reset() { std::vector<uint8_t> reset{kCommandHciReset, kCommandHciReset + sizeof(kCommandHciReset)}; hci->sendHciCommand(reset); Loading @@ -441,17 +639,74 @@ TEST_P(BluetoothAidlTest, HciReset) { wait_for_command_complete_event(reset); } // Send local loopback command and initialize SCO and ACL handles. void BluetoothAidlTest::enterLoopbackMode() { std::vector<uint8_t> cmd{kCommandHciWriteLoopbackModeLocal, kCommandHciWriteLoopbackModeLocal + sizeof(kCommandHciWriteLoopbackModeLocal)}; hci->sendHciCommand(cmd); // Receive connection complete events with data channels int connection_event_count = 0; bool command_complete_received = false; while (true) { wait_for_event(false); if (event_queue.empty()) { // Fail if there was no event received or no connections completed. ASSERT_TRUE(command_complete_received); ASSERT_LT(0, connection_event_count); return; } std::vector<uint8_t> event; ASSERT_TRUE(event_queue.pop(event)); ASSERT_GT(event.size(), static_cast<size_t>(kEventCommandCompleteStatusByte)); if (event[kEventCodeByte] == kEventConnectionComplete) { ASSERT_GT(event.size(), static_cast<size_t>(kEventConnectionCompleteType)); ASSERT_EQ(event[kEventLengthByte], kEventConnectionCompleteParamLength); uint8_t connection_type = event[kEventConnectionCompleteType]; ASSERT_TRUE(connection_type == kEventConnectionCompleteTypeSco || connection_type == kEventConnectionCompleteTypeAcl); // Save handles uint16_t handle = event[kEventConnectionCompleteHandleLsByte] | event[kEventConnectionCompleteHandleLsByte + 1] << 8; if (connection_type == kEventConnectionCompleteTypeSco) { sco_connection_handles.push_back(handle); } else { acl_connection_handles.push_back(handle); } ALOGD("Connect complete type = %d handle = %d", event[kEventConnectionCompleteType], handle); connection_event_count++; } else { ASSERT_EQ(kEventCommandComplete, event[kEventCodeByte]); ASSERT_EQ(cmd[0], event[kEventCommandCompleteOpcodeLsByte]); ASSERT_EQ(cmd[1], event[kEventCommandCompleteOpcodeLsByte + 1]); ASSERT_EQ(kHciStatusSuccess, event[kEventCommandCompleteStatusByte]); command_complete_received = true; } } } // Empty test: Initialize()/Close() are called in SetUp()/TearDown(). TEST_P(BluetoothAidlTest, InitializeAndClose) {} // Send an HCI Reset with sendHciCommand and wait for a command complete event. TEST_P(BluetoothAidlTest, HciReset) { reset(); } // Read and check the HCI version of the controller. TEST_P(BluetoothAidlTest, HciVersionTest) { reset(); std::vector<uint8_t> cmd{kCommandHciReadLocalVersionInformation, kCommandHciReadLocalVersionInformation + sizeof(kCommandHciReadLocalVersionInformation)}; hci->sendHciCommand(cmd); wait_for_event(); if (event_queue.empty()) { return; } ASSERT_NO_FATAL_FAILURE(wait_for_event()); std::vector<uint8_t> event; ASSERT_TRUE(event_queue.pop(event)); Loading @@ -468,15 +723,13 @@ TEST_P(BluetoothAidlTest, HciVersionTest) { // Send an unknown HCI command and wait for the error message. TEST_P(BluetoothAidlTest, HciUnknownCommand) { reset(); std::vector<uint8_t> cmd{ kCommandHciShouldBeUnknown, kCommandHciShouldBeUnknown + sizeof(kCommandHciShouldBeUnknown)}; hci->sendHciCommand(cmd); wait_for_event(); if (event_queue.empty()) { return; } ASSERT_NO_FATAL_FAILURE(wait_for_event()); std::vector<uint8_t> event; ASSERT_TRUE(event_queue.pop(event)); Loading @@ -496,8 +749,121 @@ TEST_P(BluetoothAidlTest, HciUnknownCommand) { } } // Enter loopback mode, but don't send any packets. TEST_P(BluetoothAidlTest, WriteLoopbackMode) { reset(); enterLoopbackMode(); } // Enter loopback mode and send a single command. TEST_P(BluetoothAidlTest, LoopbackModeSingleCommand) { reset(); setBufferSizes(); enterLoopbackMode(); sendAndCheckHci(1); } // Enter loopback mode and send a single SCO packet. TEST_P(BluetoothAidlTest, LoopbackModeSingleSco) { reset(); setBufferSizes(); setSynchronousFlowControlEnable(); enterLoopbackMode(); if (!sco_connection_handles.empty()) { ASSERT_LT(0, max_sco_data_packet_length); sendAndCheckSco(1, max_sco_data_packet_length, sco_connection_handles[0]); int sco_packets_sent = 1; int completed_packets = wait_for_completed_packets_event(sco_connection_handles[0]); if (sco_packets_sent != completed_packets) { ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__, sco_packets_sent, completed_packets); } } } // Enter loopback mode and send a single ACL packet. TEST_P(BluetoothAidlTest, LoopbackModeSingleAcl) { reset(); setBufferSizes(); enterLoopbackMode(); if (!acl_connection_handles.empty()) { ASSERT_LT(0, max_acl_data_packet_length); sendAndCheckAcl(1, max_acl_data_packet_length - 1, acl_connection_handles[0]); int acl_packets_sent = 1; int completed_packets = wait_for_completed_packets_event(acl_connection_handles[0]); if (acl_packets_sent != completed_packets) { ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__, acl_packets_sent, completed_packets); } } ASSERT_GE(acl_cb_count, 1); } // Enter loopback mode and send command packets for bandwidth measurements. TEST_P(BluetoothAidlTest, LoopbackModeCommandBandwidth) { reset(); setBufferSizes(); enterLoopbackMode(); sendAndCheckHci(kNumHciCommandsBandwidth); } // Enter loopback mode and send SCO packets for bandwidth measurements. TEST_P(BluetoothAidlTest, LoopbackModeScoBandwidth) { reset(); setBufferSizes(); setSynchronousFlowControlEnable(); enterLoopbackMode(); if (!sco_connection_handles.empty()) { ASSERT_LT(0, max_sco_data_packet_length); sendAndCheckSco(kNumScoPacketsBandwidth, max_sco_data_packet_length, sco_connection_handles[0]); int sco_packets_sent = kNumScoPacketsBandwidth; int completed_packets = wait_for_completed_packets_event(sco_connection_handles[0]); if (sco_packets_sent != completed_packets) { ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__, sco_packets_sent, completed_packets); } } } // Enter loopback mode and send packets for ACL bandwidth measurements. TEST_P(BluetoothAidlTest, LoopbackModeAclBandwidth) { reset(); setBufferSizes(); enterLoopbackMode(); if (!acl_connection_handles.empty()) { ASSERT_LT(0, max_acl_data_packet_length); sendAndCheckAcl(kNumAclPacketsBandwidth, max_acl_data_packet_length - 1, acl_connection_handles[0]); int acl_packets_sent = kNumAclPacketsBandwidth; int completed_packets = wait_for_completed_packets_event(acl_connection_handles[0]); if (acl_packets_sent != completed_packets) { ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__, acl_packets_sent, completed_packets); } } } // Set all bits in the event mask TEST_P(BluetoothAidlTest, SetEventMask) { reset(); std::vector<uint8_t> set_event_mask{ 0x01, 0x0c, 0x08 /*parameter bytes*/, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; Loading @@ -507,6 +873,7 @@ TEST_P(BluetoothAidlTest, SetEventMask) { // Set all bits in the LE event mask TEST_P(BluetoothAidlTest, SetLeEventMask) { reset(); std::vector<uint8_t> set_event_mask{ 0x20, 0x0c, 0x08 /*parameter bytes*/, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; Loading