Loading system/gd/hci/hci_layer.cc +14 −4 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ #include "os/metrics.h" #include "os/queue.h" #include "osi/include/stack_power_telemetry.h" #include "packet/raw_builder.h" #include "storage/storage_module.h" namespace bluetooth { Loading Loading @@ -218,10 +219,19 @@ struct HciLayer::impl { // we can't treat this as hard failure since we have no way of probing this lack of support at // earlier time. Instead we let the command complete handler handle a empty Command Complete // packet, which will be interpreted as invalid response. CommandCompleteView command_complete_view = CommandCompleteView::Create( EventView::Create(PacketView<kLittleEndian>(std::make_shared<std::vector<uint8_t>>(std::vector<uint8_t>())))); command_queue_.front().GetCallback<CommandCompleteView>()->Invoke( std::move(command_complete_view)); auto payload = std::make_unique<packet::RawBuilder>(); payload->AddOctets1(static_cast<uint8_t>(status_view.GetStatus())); auto complete_event_builder = CommandCompleteBuilder::Create( status_view.GetNumHciCommandPackets(), status_view.GetCommandOpCode(), std::move(payload)); auto complete = std::make_shared<std::vector<std::uint8_t>>(complete_event_builder->SerializeToBytes()); CommandCompleteView command_complete_view = CommandCompleteView::Create(EventView::Create(PacketView<kLittleEndian>(complete))); ASSERT(command_complete_view.IsValid()); command_queue_.front().GetCallback<CommandCompleteView>()->Invoke(command_complete_view); } else { ASSERT_LOG( command_queue_.front().waiting_for_status_ == is_status, Loading system/gd/hci/hci_layer_unittest.cc +24 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <chrono> #include <future> #include <memory> #include "common/bind.h" #include "common/init_flags.h" Loading Loading @@ -433,6 +434,29 @@ TEST_F(HciLayerTest, our_command_status_callback_is_invoked) { hal_->InjectEvent(ReadClockOffsetStatusBuilder::Create(ErrorCode::SUCCESS, 1)); } TEST_F(HciLayerTest, vendor_specific_status_instead_of_complete) { std::promise<OpCode> callback_promise; auto callback_future = callback_promise.get_future(); FailIfResetNotSent(); hal_->InjectEvent(ResetCompleteBuilder::Create(1, ErrorCode::SUCCESS)); hci_->EnqueueCommand( LeGetVendorCapabilitiesBuilder::Create(), hci_handler_->BindOnce( [](std::promise<OpCode> promise, CommandCompleteView view) { ASSERT_TRUE(view.IsValid()); promise.set_value(view.GetCommandOpCode()); }, std::move(callback_promise))); hal_->InjectEvent(CommandStatusBuilder::Create( ErrorCode::UNKNOWN_HCI_COMMAND, 1, OpCode::LE_GET_VENDOR_CAPABILITIES, std::make_unique<RawBuilder>())); ASSERT_EQ(std::future_status::ready, callback_future.wait_for(std::chrono::seconds(1))); ASSERT_EQ(OpCode::LE_GET_VENDOR_CAPABILITIES, callback_future.get()); } TEST_F( HciLayerDeathTest, command_complete_callback_is_invoked_with_an_opcode_that_does_not_match_command_queue) { Loading Loading
system/gd/hci/hci_layer.cc +14 −4 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ #include "os/metrics.h" #include "os/queue.h" #include "osi/include/stack_power_telemetry.h" #include "packet/raw_builder.h" #include "storage/storage_module.h" namespace bluetooth { Loading Loading @@ -218,10 +219,19 @@ struct HciLayer::impl { // we can't treat this as hard failure since we have no way of probing this lack of support at // earlier time. Instead we let the command complete handler handle a empty Command Complete // packet, which will be interpreted as invalid response. CommandCompleteView command_complete_view = CommandCompleteView::Create( EventView::Create(PacketView<kLittleEndian>(std::make_shared<std::vector<uint8_t>>(std::vector<uint8_t>())))); command_queue_.front().GetCallback<CommandCompleteView>()->Invoke( std::move(command_complete_view)); auto payload = std::make_unique<packet::RawBuilder>(); payload->AddOctets1(static_cast<uint8_t>(status_view.GetStatus())); auto complete_event_builder = CommandCompleteBuilder::Create( status_view.GetNumHciCommandPackets(), status_view.GetCommandOpCode(), std::move(payload)); auto complete = std::make_shared<std::vector<std::uint8_t>>(complete_event_builder->SerializeToBytes()); CommandCompleteView command_complete_view = CommandCompleteView::Create(EventView::Create(PacketView<kLittleEndian>(complete))); ASSERT(command_complete_view.IsValid()); command_queue_.front().GetCallback<CommandCompleteView>()->Invoke(command_complete_view); } else { ASSERT_LOG( command_queue_.front().waiting_for_status_ == is_status, Loading
system/gd/hci/hci_layer_unittest.cc +24 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <chrono> #include <future> #include <memory> #include "common/bind.h" #include "common/init_flags.h" Loading Loading @@ -433,6 +434,29 @@ TEST_F(HciLayerTest, our_command_status_callback_is_invoked) { hal_->InjectEvent(ReadClockOffsetStatusBuilder::Create(ErrorCode::SUCCESS, 1)); } TEST_F(HciLayerTest, vendor_specific_status_instead_of_complete) { std::promise<OpCode> callback_promise; auto callback_future = callback_promise.get_future(); FailIfResetNotSent(); hal_->InjectEvent(ResetCompleteBuilder::Create(1, ErrorCode::SUCCESS)); hci_->EnqueueCommand( LeGetVendorCapabilitiesBuilder::Create(), hci_handler_->BindOnce( [](std::promise<OpCode> promise, CommandCompleteView view) { ASSERT_TRUE(view.IsValid()); promise.set_value(view.GetCommandOpCode()); }, std::move(callback_promise))); hal_->InjectEvent(CommandStatusBuilder::Create( ErrorCode::UNKNOWN_HCI_COMMAND, 1, OpCode::LE_GET_VENDOR_CAPABILITIES, std::make_unique<RawBuilder>())); ASSERT_EQ(std::future_status::ready, callback_future.wait_for(std::chrono::seconds(1))); ASSERT_EQ(OpCode::LE_GET_VENDOR_CAPABILITIES, callback_future.get()); } TEST_F( HciLayerDeathTest, command_complete_callback_is_invoked_with_an_opcode_that_does_not_match_command_queue) { Loading