Loading system/gd/hci/facade/le_scanning_manager_facade.cc +29 −77 Original line number Diff line number Diff line Loading @@ -40,60 +40,46 @@ using ::grpc::ServerContext; using ::grpc::ServerWriter; using ::grpc::Status; class LeScanningManagerFacadeService : public LeScanningManagerFacade::Service, public LeScanningManagerCallbacks { class LeScanningManagerFacadeService : public LeScanningManagerFacade::Service, ScanningCallback { public: LeScanningManagerFacadeService(LeScanningManager* le_scanning_manager, os::Handler* facade_handler) : le_scanning_manager_(le_scanning_manager), facade_handler_(facade_handler) { ASSERT(le_scanning_manager_ != nullptr); ASSERT(facade_handler_ != nullptr); le_scanning_manager_->RegisterScanningCallback(this); } ::grpc::Status StartScan(::grpc::ServerContext* context, const ::google::protobuf::Empty*, ::grpc::ServerWriter<LeReportMsg>* writer) override { le_scanning_manager_->StartScan(this); le_scanning_manager_->Scan(true); return pending_events_.RunLoop(context, writer); } ::grpc::Status StopScan(::grpc::ServerContext* context, const ::google::protobuf::Empty*, ScanStoppedMsg* response) override { std::shared_ptr<std::promise<void>> on_stopped = std::make_shared<std::promise<void>>(); auto future = on_stopped->get_future(); le_scanning_manager_->StopScan( common::Bind([](std::shared_ptr<std::promise<void>> p) { p->set_value(); }, on_stopped)); auto result = future.wait_for(std::chrono::milliseconds(1000)); ASSERT(result == std::future_status::ready); le_scanning_manager_->Scan(false); return ::grpc::Status::OK; } void on_advertisements(std::vector<std::shared_ptr<LeReport>> reports) override { for (const auto report : reports) { switch (report->report_type_) { case hci::LeReport::ReportType::ADVERTISING_EVENT: { LeReportMsg le_report_msg; std::vector<LeAdvertisingReport> advertisements; LeAdvertisingReport le_advertising_report; le_advertising_report.address_type_ = static_cast<AddressType>(report->address_type_); le_advertising_report.address_ = report->address_; le_advertising_report.advertising_data_ = report->gap_data_; le_advertising_report.event_type_ = report->advertising_event_type_; le_advertising_report.rssi_ = report->rssi_; advertisements.push_back(le_advertising_report); auto builder = LeAdvertisingReportBuilder::Create(advertisements); std::vector<uint8_t> bytes; BitInserter bit_inserter(bytes); builder->Serialize(bit_inserter); le_report_msg.set_event(std::string(bytes.begin(), bytes.end())); pending_events_.OnIncomingEvent(std::move(le_report_msg)); } break; case hci::LeReport::ReportType::EXTENDED_ADVERTISING_EVENT: { void OnScannerRegistered(const bluetooth::hci::Uuid app_uuid, ScannerId scanner_id, ScanningStatus status){}; void OnScanResult( uint16_t event_type, uint8_t address_type, Address address, uint8_t primary_phy, uint8_t secondary_phy, uint8_t advertising_sid, int8_t tx_power, int8_t rssi, uint16_t periodic_advertising_interval, std::vector<GapData> advertising_data) { LeReportMsg le_report_msg; std::vector<LeExtendedAdvertisingReport> advertisements; LeExtendedAdvertisingReport le_extended_advertising_report; le_extended_advertising_report.address_type_ = report->address_type_; le_extended_advertising_report.address_ = report->address_; le_extended_advertising_report.advertising_data_ = report->gap_data_; le_extended_advertising_report.rssi_ = report->rssi_; le_extended_advertising_report.address_type_ = (DirectAdvertisingAddressType)address_type; le_extended_advertising_report.address_ = address; le_extended_advertising_report.advertising_data_ = advertising_data; le_extended_advertising_report.rssi_ = rssi; advertisements.push_back(le_extended_advertising_report); auto builder = LeExtendedAdvertisingReportBuilder::Create(advertisements); Loading @@ -102,44 +88,10 @@ class LeScanningManagerFacadeService : public LeScanningManagerFacade::Service, builder->Serialize(bit_inserter); le_report_msg.set_event(std::string(bytes.begin(), bytes.end())); pending_events_.OnIncomingEvent(std::move(le_report_msg)); } break; case hci::LeReport::ReportType::DIRECTED_ADVERTISING_EVENT: { LeReportMsg le_report_msg; std::vector<LeDirectedAdvertisingReport> advertisements; LeDirectedAdvertisingReport le_directed_advertising_report; le_directed_advertising_report.address_ = report->address_; le_directed_advertising_report.direct_address_ = ((DirectedLeReport*)report.get())->direct_address_; le_directed_advertising_report.direct_address_type_ = DirectAddressType::RANDOM_DEVICE_ADDRESS; le_directed_advertising_report.event_type_ = DirectAdvertisingEventType::ADV_DIRECT_IND; le_directed_advertising_report.rssi_ = report->rssi_; advertisements.push_back(le_directed_advertising_report); auto builder = LeDirectedAdvertisingReportBuilder::Create(advertisements); std::vector<uint8_t> bytes; BitInserter bit_inserter(bytes); builder->Serialize(bit_inserter); le_report_msg.set_event(std::string(bytes.begin(), bytes.end())); pending_events_.OnIncomingEvent(std::move(le_report_msg)); } break; default: LOG_INFO("Skipping unknown report type %d", static_cast<int>(report->report_type_)); } } } void on_timeout() override { LeReportMsg le_report_msg; auto builder = LeScanTimeoutBuilder::Create(); std::vector<uint8_t> bytes; BitInserter bit_inserter(bytes); builder->Serialize(bit_inserter); le_report_msg.set_event(std::string(bytes.begin(), bytes.end())); pending_events_.OnIncomingEvent(std::move(le_report_msg)); } os::Handler* Handler() override { return facade_handler_; } }; void OnTrackAdvFoundLost(){}; void OnBatchScanReports(int client_if, int status, int report_format, int num_records, std::vector<uint8_t> data){}; void OnTimeout(){}; LeScanningManager* le_scanning_manager_; os::Handler* facade_handler_; Loading system/gd/hci/hci_packets.pdl +1 −2 Original line number Diff line number Diff line Loading @@ -4618,8 +4618,7 @@ struct LeExtendedAdvertisingReport { address : Address, primary_phy : PrimaryPhyType, secondary_phy : SecondaryPhyType, advertising_sid : 4, // SID subfield in the ADI field _reserved_ : 4, advertising_sid : 8, // SID subfield in the ADI field tx_power : 8, rssi : 8, // -127 to +20 (0x7F means not available) periodic_advertising_interval : 16, // 0x006 to 0xFFFF (7.5 ms to 82s) Loading system/gd/hci/le_scanning_manager.cc +158 −62 Original line number Diff line number Diff line Loading @@ -50,7 +50,7 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback impl(Module* module) : module_(module), le_scanning_interface_(nullptr) {} ~impl() { if (address_manager_registered) { if (address_manager_registered_) { le_address_manager_->Unregister(this); } } Loading Loading @@ -81,22 +81,17 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback void handle_scan_results(LeMetaEventView event) { switch (event.GetSubeventCode()) { case hci::SubeventCode::ADVERTISING_REPORT: handle_advertising_report<LeAdvertisingReportView, LeAdvertisingReport, LeReport>( LeAdvertisingReportView::Create(event)); handle_advertising_report(LeAdvertisingReportView::Create(event)); break; case hci::SubeventCode::DIRECTED_ADVERTISING_REPORT: handle_advertising_report<LeDirectedAdvertisingReportView, LeDirectedAdvertisingReport, DirectedLeReport>( LeDirectedAdvertisingReportView::Create(event)); handle_directed_advertising_report(LeDirectedAdvertisingReportView::Create(event)); break; case hci::SubeventCode::EXTENDED_ADVERTISING_REPORT: handle_advertising_report<LeExtendedAdvertisingReportView, LeExtendedAdvertisingReport, ExtendedLeReport>( LeExtendedAdvertisingReportView::Create(event)); handle_extended_advertising_report(LeExtendedAdvertisingReportView::Create(event)); break; case hci::SubeventCode::SCAN_TIMEOUT: if (registered_callback_ != nullptr) { registered_callback_->Handler()->Post( common::BindOnce(&LeScanningManagerCallbacks::on_timeout, common::Unretained(registered_callback_))); registered_callback_ = nullptr; if (scanning_callbacks_ != nullptr) { scanning_callbacks_->OnTimeout(); } break; default: Loading @@ -104,9 +99,26 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback } } template <class EventType, class ReportStructType, class ReportType> void handle_advertising_report(EventType event_view) { if (registered_callback_ == nullptr) { struct ExtendedEventTypeOptions { bool connectable{false}; bool scannable{false}; bool directed{false}; bool scan_response{false}; bool legacy{false}; bool continuing{false}; bool truncated{false}; }; void transform_to_extended_event_type(uint16_t* extended_event_type, ExtendedEventTypeOptions o) { ASSERT(extended_event_type != nullptr); *extended_event_type = (o.connectable ? 0x0001 << 0 : 0) | (o.scannable ? 0x0001 << 1 : 0) | (o.directed ? 0x0001 << 2 : 0) | (o.scan_response ? 0x0001 << 3 : 0) | (o.legacy ? 0x0001 << 4 : 0) | (o.continuing ? 0x0001 << 5 : 0) | (o.truncated ? 0x0001 << 6 : 0); } void handle_advertising_report(LeAdvertisingReportView event_view) { if (scanning_callbacks_ == nullptr) { LOG_INFO("Dropping advertising event (no registered handler)"); return; } Loading @@ -114,18 +126,103 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback LOG_INFO("Dropping invalid advertising event"); return; } std::vector<ReportStructType> report_vector = event_view.GetAdvertisingReports(); if (report_vector.empty()) { std::vector<LeAdvertisingReport> reports = event_view.GetAdvertisingReports(); if (reports.empty()) { LOG_INFO("Zero results in advertising event"); return; } std::vector<std::shared_ptr<LeReport>> param; param.reserve(report_vector.size()); for (const ReportStructType& report : report_vector) { param.push_back(std::shared_ptr<LeReport>(static_cast<LeReport*>(new ReportType(report)))); // TODO: handle AdvertisingCache for scan response for (LeAdvertisingReport report : reports) { uint16_t extended_event_type = 0; switch (report.event_type_) { case hci::AdvertisingEventType::ADV_IND: transform_to_extended_event_type( &extended_event_type, {.connectable = true, .scannable = true, .legacy = true}); break; case hci::AdvertisingEventType::ADV_DIRECT_IND: transform_to_extended_event_type( &extended_event_type, {.connectable = true, .directed = true, .legacy = true}); break; case hci::AdvertisingEventType::ADV_SCAN_IND: transform_to_extended_event_type(&extended_event_type, {.scannable = true, .legacy = true}); break; case hci::AdvertisingEventType::ADV_NONCONN_IND: transform_to_extended_event_type(&extended_event_type, {.legacy = true}); break; case hci::AdvertisingEventType::SCAN_RESPONSE: transform_to_extended_event_type( &extended_event_type, {.connectable = true, .scannable = true, .scan_response = true, .legacy = true}); break; default: LOG_WARN("Unsupported event type:%d", (uint16_t)report.event_type_); return; } scanning_callbacks_->OnScanResult( (uint16_t)report.event_type_, (uint8_t)report.address_type_, report.address_, (uint8_t)PrimaryPhyType::LE_1M, (uint8_t)SecondaryPhyType::NO_PACKETS, kAdvertisingDataInfoNotPresent, kTxPowerInformationNotPresent, report.rssi_, kNotPeriodicAdvertisement, report.advertising_data_); } } void handle_directed_advertising_report(LeDirectedAdvertisingReportView event_view) { if (scanning_callbacks_ == nullptr) { LOG_INFO("Dropping advertising event (no registered handler)"); return; } if (!event_view.IsValid()) { LOG_INFO("Dropping invalid advertising event"); return; } std::vector<LeDirectedAdvertisingReport> reports = event_view.GetAdvertisingReports(); if (reports.empty()) { LOG_INFO("Zero results in advertising event"); return; } uint16_t extended_event_type = 0; transform_to_extended_event_type(&extended_event_type, {.connectable = true, .directed = true, .legacy = true}); // TODO: parse report } void handle_extended_advertising_report(LeExtendedAdvertisingReportView event_view) { if (scanning_callbacks_ == nullptr) { LOG_INFO("Dropping advertising event (no registered handler)"); return; } if (!event_view.IsValid()) { LOG_INFO("Dropping invalid advertising event"); return; } std::vector<LeExtendedAdvertisingReport> reports = event_view.GetAdvertisingReports(); if (reports.empty()) { LOG_INFO("Zero results in advertising event"); return; } // TODO: handle AdvertisingCache for scan response for (LeExtendedAdvertisingReport report : reports) { uint16_t event_type = report.connectable_ | (report.scannable_ << 1) | (report.directed_ << 2) | (report.scan_response_ << 3) | (report.legacy_ << 4) | ((uint16_t)report.data_status_ << 5); scanning_callbacks_->OnScanResult( event_type, (uint8_t)report.address_type_, report.address_, (uint8_t)report.primary_phy_, (uint8_t)report.secondary_phy_, report.advertising_sid_, report.tx_power_, report.rssi_, report.periodic_advertising_interval_, report.advertising_data_); } registered_callback_->Handler()->Post(common::BindOnce(&LeScanningManagerCallbacks::on_advertisements, common::Unretained(registered_callback_), param)); } void configure_scan() { Loading Loading @@ -196,25 +293,35 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback } } void start_scan(LeScanningManagerCallbacks* le_scanning_manager_callbacks) { registered_callback_ = le_scanning_manager_callbacks; if (!address_manager_registered) { le_address_manager_->Register(this); address_manager_registered = true; void scan(bool start) { if (start) { start_scan(); } else { if (address_manager_registered_) { le_address_manager_->Unregister(this); address_manager_registered_ = false; } stop_scan(); } } // If we receive start_scan during paused, replace the cached_registered_callback_ for OnResume if (cached_registered_callback_ != nullptr) { cached_registered_callback_ = registered_callback_; void start_scan() { // If we receive start_scan during paused, set scan_on_resume_ to true if (paused_) { scan_on_resume_ = true; return; } is_scanning_ = true; if (!address_manager_registered_) { le_address_manager_->Register(this); address_manager_registered_ = true; } switch (api_type_) { case ScanApiType::EXTENDED: le_scanning_interface_->EnqueueCommand( hci::LeSetExtendedScanEnableBuilder::Create(Enable::ENABLED, FilterDuplicates::DISABLED /* filter duplicates */, 0, 0), hci::LeSetExtendedScanEnableBuilder::Create( Enable::ENABLED, FilterDuplicates::DISABLED /* filter duplicates */, 0, 0), module_handler_->BindOnce(impl::check_status)); break; case ScanApiType::ANDROID_HCI: Loading @@ -226,30 +333,21 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback } } void stop_scan(common::Callback<void()> on_stopped, bool from_on_pause) { if (address_manager_registered && !from_on_pause) { cached_registered_callback_ = nullptr; le_address_manager_->Unregister(this); address_manager_registered = false; } if (registered_callback_ == nullptr) { return; } registered_callback_->Handler()->Post(std::move(on_stopped)); void stop_scan() { is_scanning_ = false; switch (api_type_) { case ScanApiType::EXTENDED: le_scanning_interface_->EnqueueCommand( hci::LeSetExtendedScanEnableBuilder::Create(Enable::DISABLED, FilterDuplicates::DISABLED /* filter duplicates */, 0, 0), hci::LeSetExtendedScanEnableBuilder::Create( Enable::DISABLED, FilterDuplicates::DISABLED /* filter duplicates */, 0, 0), module_handler_->BindOnce(impl::check_status)); registered_callback_ = nullptr; break; case ScanApiType::ANDROID_HCI: case ScanApiType::LEGACY: le_scanning_interface_->EnqueueCommand( hci::LeSetScanEnableBuilder::Create(Enable::DISABLED, Enable::DISABLED /* filter duplicates */), module_handler_->BindOnce(impl::check_status)); registered_callback_ = nullptr; break; } } Loading @@ -259,8 +357,10 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback } void OnPause() override { cached_registered_callback_ = registered_callback_; stop_scan(common::Bind(&impl::ack_pause, common::Unretained(this)), true); paused_ = true; scan_on_resume_ = is_scanning_; stop_scan(); ack_pause(); } void ack_pause() { Loading @@ -268,27 +368,27 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback } void OnResume() override { if (cached_registered_callback_ != nullptr) { auto cached_registered_callback = cached_registered_callback_; cached_registered_callback_ = nullptr; start_scan(cached_registered_callback); paused_ = false; if (scan_on_resume_ == true) { start_scan(); } le_address_manager_->AckResume(this); } ScanApiType api_type_; LeScanningManagerCallbacks* registered_callback_ = nullptr; LeScanningManagerCallbacks* cached_registered_callback_ = nullptr; Module* module_; os::Handler* module_handler_; hci::HciLayer* hci_layer_; hci::Controller* controller_; hci::LeScanningInterface* le_scanning_interface_; hci::LeAddressManager* le_address_manager_; bool address_manager_registered = false; bool address_manager_registered_ = false; ScanningCallback* scanning_callbacks_ = nullptr; std::vector<Scanner> scanners_; bool is_scanning_ = false; bool scan_on_resume_ = false; bool paused_ = false; uint32_t interval_ms_{1000}; uint16_t window_ms_{1000}; Loading Loading @@ -359,12 +459,8 @@ void LeScanningManager::Unregister(ScannerId scanner_id) { CallOn(pimpl_.get(), &impl::unregister_scanner, scanner_id); } void LeScanningManager::StartScan(LeScanningManagerCallbacks* callbacks) { GetHandler()->Post(common::Bind(&impl::start_scan, common::Unretained(pimpl_.get()), callbacks)); } void LeScanningManager::StopScan(common::Callback<void()> on_stopped) { GetHandler()->Post(common::Bind(&impl::stop_scan, common::Unretained(pimpl_.get()), on_stopped, false)); void LeScanningManager::Scan(bool start) { CallOn(pimpl_.get(), &impl::scan, start); } void LeScanningManager::RegisterScanningCallback(ScanningCallback* scanning_callback) { Loading system/gd/hci/le_scanning_manager.h +9 −15 Original line number Diff line number Diff line Loading @@ -26,14 +26,6 @@ namespace bluetooth { namespace hci { class LeScanningManagerCallbacks { public: virtual ~LeScanningManagerCallbacks() = default; virtual void on_advertisements(std::vector<std::shared_ptr<LeReport>>) = 0; virtual void on_timeout() = 0; virtual os::Handler* Handler() = 0; }; using ScannerId = uint8_t; class ScanningCallback { Loading @@ -49,32 +41,34 @@ class ScanningCallback { const bluetooth::hci::Uuid app_uuid, ScannerId scanner_id, ScanningStatus status) = 0; virtual void OnScanResult( uint16_t event_type, uint8_t addr_type, Address* bda, uint8_t address_type, Address address, uint8_t primary_phy, uint8_t secondary_phy, uint8_t advertising_sid, int8_t tx_power, int8_t rssi, uint16_t periodic_adv_int, std::vector<uint8_t> adv_data) = 0; uint16_t periodic_advertising_interval, std::vector<GapData> advertising_data) = 0; virtual void OnTrackAdvFoundLost() = 0; virtual void OnBatchScanReports( int client_if, int status, int report_format, int num_records, std::vector<uint8_t> data) = 0; virtual void OnTimeout() = 0; }; class LeScanningManager : public bluetooth::Module { public: static constexpr uint8_t kMaxAppNum = 32; static constexpr uint8_t kAdvertisingDataInfoNotPresent = 0xff; static constexpr uint8_t kTxPowerInformationNotPresent = 0x7f; static constexpr uint8_t kNotPeriodicAdvertisement = 0x00; LeScanningManager(); void RegisterScanner(const Uuid app_uuid); void Unregister(ScannerId scanner_id); void StartScan(LeScanningManagerCallbacks* callbacks); void StopScan(common::Callback<void()> on_stopped); void Scan(bool start); void RegisterScanningCallback(ScanningCallback* scanning_callback); Loading system/gd/hci/le_scanning_manager_test.cc +34 −16 Original line number Diff line number Diff line Loading @@ -236,9 +236,6 @@ class LeScanningManagerTest : public ::testing::Test { fake_registry_.InjectTestModule(&HciLayer::Factory, test_hci_layer_); fake_registry_.InjectTestModule(&Controller::Factory, test_controller_); fake_registry_.InjectTestModule(&AclManager::Factory, test_acl_manager_); client_handler_ = fake_registry_.GetTestModuleHandler(&HciLayer::Factory); ASSERT_NE(client_handler_, nullptr); mock_callbacks_.handler_ = client_handler_; std::future<void> config_future = test_hci_layer_->GetCommandFuture(); fake_registry_.Start<LeScanningManager>(&thread_); le_scanning_manager = Loading @@ -246,6 +243,7 @@ class LeScanningManagerTest : public ::testing::Test { auto result = config_future.wait_for(std::chrono::duration(std::chrono::milliseconds(1000))); ASSERT_EQ(std::future_status::ready, result); HandleConfiguration(); le_scanning_manager->RegisterScanningCallback(&mock_callbacks_); } void TearDown() override { Loading @@ -266,14 +264,34 @@ class LeScanningManagerTest : public ::testing::Test { LeScanningManager* le_scanning_manager = nullptr; os::Handler* client_handler_ = nullptr; class MockLeScanningManagerCallbacks : public LeScanningManagerCallbacks { class MockCallbacks : public bluetooth::hci::ScanningCallback { public: MOCK_METHOD(void, on_advertisements, (std::vector<std::shared_ptr<LeReport>>), (override)); MOCK_METHOD(void, on_timeout, (), (override)); os::Handler* Handler() { return handler_; } os::Handler* handler_{nullptr}; MOCK_METHOD( void, OnScannerRegistered, (const bluetooth::hci::Uuid app_uuid, ScannerId scanner_id, ScanningStatus status), (override)); MOCK_METHOD( void, OnScanResult, (uint16_t event_type, uint8_t address_type, Address address, uint8_t primary_phy, uint8_t secondary_phy, uint8_t advertising_sid, int8_t tx_power, int8_t rssi, uint16_t periodic_advertising_interval, std::vector<GapData> advertising_data), (override)); MOCK_METHOD(void, OnTrackAdvFoundLost, (), (override)); MOCK_METHOD( void, OnBatchScanReports, (int client_if, int status, int report_format, int num_records, std::vector<uint8_t> data), (override)); MOCK_METHOD(void, OnTimeout, (), (override)); } mock_callbacks_; OpCode param_opcode_{OpCode::LE_SET_ADVERTISING_PARAMETERS}; Loading Loading @@ -309,7 +327,7 @@ TEST_F(LeScanningManagerTest, startup_teardown) {} TEST_F(LeScanningManagerTest, start_scan_test) { auto next_command_future = test_hci_layer_->GetCommandFuture(); le_scanning_manager->StartScan(&mock_callbacks_); le_scanning_manager->Scan(true); auto result = next_command_future.wait_for(std::chrono::duration(std::chrono::milliseconds(100))); ASSERT_EQ(std::future_status::ready, result); Loading @@ -329,14 +347,14 @@ TEST_F(LeScanningManagerTest, start_scan_test) { gap_data.push_back(data_item); report.advertising_data_ = gap_data; EXPECT_CALL(mock_callbacks_, on_advertisements); EXPECT_CALL(mock_callbacks_, OnScanResult); test_hci_layer_->IncomingLeMetaEvent(LeAdvertisingReportBuilder::Create({report})); } TEST_F(LeAndroidHciScanningManagerTest, start_scan_test) { auto next_command_future = test_hci_layer_->GetCommandFuture(); le_scanning_manager->StartScan(&mock_callbacks_); le_scanning_manager->Scan(true); auto result = next_command_future.wait_for(std::chrono::duration(std::chrono::milliseconds(100))); ASSERT_EQ(std::future_status::ready, result); Loading @@ -356,14 +374,14 @@ TEST_F(LeAndroidHciScanningManagerTest, start_scan_test) { gap_data.push_back(data_item); report.advertising_data_ = gap_data; EXPECT_CALL(mock_callbacks_, on_advertisements); EXPECT_CALL(mock_callbacks_, OnScanResult); test_hci_layer_->IncomingLeMetaEvent(LeAdvertisingReportBuilder::Create({report})); } TEST_F(LeExtendedScanningManagerTest, start_scan_test) { auto next_command_future = test_hci_layer_->GetCommandFuture(); le_scanning_manager->StartScan(&mock_callbacks_); le_scanning_manager->Scan(true); auto result = next_command_future.wait_for(std::chrono::duration(std::chrono::milliseconds(100))); ASSERT_EQ(std::future_status::ready, result); Loading @@ -386,7 +404,7 @@ TEST_F(LeExtendedScanningManagerTest, start_scan_test) { gap_data.push_back(data_item); report.advertising_data_ = gap_data; EXPECT_CALL(mock_callbacks_, on_advertisements); EXPECT_CALL(mock_callbacks_, OnScanResult); test_hci_layer_->IncomingLeMetaEvent(LeExtendedAdvertisingReportBuilder::Create({report})); } Loading Loading
system/gd/hci/facade/le_scanning_manager_facade.cc +29 −77 Original line number Diff line number Diff line Loading @@ -40,60 +40,46 @@ using ::grpc::ServerContext; using ::grpc::ServerWriter; using ::grpc::Status; class LeScanningManagerFacadeService : public LeScanningManagerFacade::Service, public LeScanningManagerCallbacks { class LeScanningManagerFacadeService : public LeScanningManagerFacade::Service, ScanningCallback { public: LeScanningManagerFacadeService(LeScanningManager* le_scanning_manager, os::Handler* facade_handler) : le_scanning_manager_(le_scanning_manager), facade_handler_(facade_handler) { ASSERT(le_scanning_manager_ != nullptr); ASSERT(facade_handler_ != nullptr); le_scanning_manager_->RegisterScanningCallback(this); } ::grpc::Status StartScan(::grpc::ServerContext* context, const ::google::protobuf::Empty*, ::grpc::ServerWriter<LeReportMsg>* writer) override { le_scanning_manager_->StartScan(this); le_scanning_manager_->Scan(true); return pending_events_.RunLoop(context, writer); } ::grpc::Status StopScan(::grpc::ServerContext* context, const ::google::protobuf::Empty*, ScanStoppedMsg* response) override { std::shared_ptr<std::promise<void>> on_stopped = std::make_shared<std::promise<void>>(); auto future = on_stopped->get_future(); le_scanning_manager_->StopScan( common::Bind([](std::shared_ptr<std::promise<void>> p) { p->set_value(); }, on_stopped)); auto result = future.wait_for(std::chrono::milliseconds(1000)); ASSERT(result == std::future_status::ready); le_scanning_manager_->Scan(false); return ::grpc::Status::OK; } void on_advertisements(std::vector<std::shared_ptr<LeReport>> reports) override { for (const auto report : reports) { switch (report->report_type_) { case hci::LeReport::ReportType::ADVERTISING_EVENT: { LeReportMsg le_report_msg; std::vector<LeAdvertisingReport> advertisements; LeAdvertisingReport le_advertising_report; le_advertising_report.address_type_ = static_cast<AddressType>(report->address_type_); le_advertising_report.address_ = report->address_; le_advertising_report.advertising_data_ = report->gap_data_; le_advertising_report.event_type_ = report->advertising_event_type_; le_advertising_report.rssi_ = report->rssi_; advertisements.push_back(le_advertising_report); auto builder = LeAdvertisingReportBuilder::Create(advertisements); std::vector<uint8_t> bytes; BitInserter bit_inserter(bytes); builder->Serialize(bit_inserter); le_report_msg.set_event(std::string(bytes.begin(), bytes.end())); pending_events_.OnIncomingEvent(std::move(le_report_msg)); } break; case hci::LeReport::ReportType::EXTENDED_ADVERTISING_EVENT: { void OnScannerRegistered(const bluetooth::hci::Uuid app_uuid, ScannerId scanner_id, ScanningStatus status){}; void OnScanResult( uint16_t event_type, uint8_t address_type, Address address, uint8_t primary_phy, uint8_t secondary_phy, uint8_t advertising_sid, int8_t tx_power, int8_t rssi, uint16_t periodic_advertising_interval, std::vector<GapData> advertising_data) { LeReportMsg le_report_msg; std::vector<LeExtendedAdvertisingReport> advertisements; LeExtendedAdvertisingReport le_extended_advertising_report; le_extended_advertising_report.address_type_ = report->address_type_; le_extended_advertising_report.address_ = report->address_; le_extended_advertising_report.advertising_data_ = report->gap_data_; le_extended_advertising_report.rssi_ = report->rssi_; le_extended_advertising_report.address_type_ = (DirectAdvertisingAddressType)address_type; le_extended_advertising_report.address_ = address; le_extended_advertising_report.advertising_data_ = advertising_data; le_extended_advertising_report.rssi_ = rssi; advertisements.push_back(le_extended_advertising_report); auto builder = LeExtendedAdvertisingReportBuilder::Create(advertisements); Loading @@ -102,44 +88,10 @@ class LeScanningManagerFacadeService : public LeScanningManagerFacade::Service, builder->Serialize(bit_inserter); le_report_msg.set_event(std::string(bytes.begin(), bytes.end())); pending_events_.OnIncomingEvent(std::move(le_report_msg)); } break; case hci::LeReport::ReportType::DIRECTED_ADVERTISING_EVENT: { LeReportMsg le_report_msg; std::vector<LeDirectedAdvertisingReport> advertisements; LeDirectedAdvertisingReport le_directed_advertising_report; le_directed_advertising_report.address_ = report->address_; le_directed_advertising_report.direct_address_ = ((DirectedLeReport*)report.get())->direct_address_; le_directed_advertising_report.direct_address_type_ = DirectAddressType::RANDOM_DEVICE_ADDRESS; le_directed_advertising_report.event_type_ = DirectAdvertisingEventType::ADV_DIRECT_IND; le_directed_advertising_report.rssi_ = report->rssi_; advertisements.push_back(le_directed_advertising_report); auto builder = LeDirectedAdvertisingReportBuilder::Create(advertisements); std::vector<uint8_t> bytes; BitInserter bit_inserter(bytes); builder->Serialize(bit_inserter); le_report_msg.set_event(std::string(bytes.begin(), bytes.end())); pending_events_.OnIncomingEvent(std::move(le_report_msg)); } break; default: LOG_INFO("Skipping unknown report type %d", static_cast<int>(report->report_type_)); } } } void on_timeout() override { LeReportMsg le_report_msg; auto builder = LeScanTimeoutBuilder::Create(); std::vector<uint8_t> bytes; BitInserter bit_inserter(bytes); builder->Serialize(bit_inserter); le_report_msg.set_event(std::string(bytes.begin(), bytes.end())); pending_events_.OnIncomingEvent(std::move(le_report_msg)); } os::Handler* Handler() override { return facade_handler_; } }; void OnTrackAdvFoundLost(){}; void OnBatchScanReports(int client_if, int status, int report_format, int num_records, std::vector<uint8_t> data){}; void OnTimeout(){}; LeScanningManager* le_scanning_manager_; os::Handler* facade_handler_; Loading
system/gd/hci/hci_packets.pdl +1 −2 Original line number Diff line number Diff line Loading @@ -4618,8 +4618,7 @@ struct LeExtendedAdvertisingReport { address : Address, primary_phy : PrimaryPhyType, secondary_phy : SecondaryPhyType, advertising_sid : 4, // SID subfield in the ADI field _reserved_ : 4, advertising_sid : 8, // SID subfield in the ADI field tx_power : 8, rssi : 8, // -127 to +20 (0x7F means not available) periodic_advertising_interval : 16, // 0x006 to 0xFFFF (7.5 ms to 82s) Loading
system/gd/hci/le_scanning_manager.cc +158 −62 Original line number Diff line number Diff line Loading @@ -50,7 +50,7 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback impl(Module* module) : module_(module), le_scanning_interface_(nullptr) {} ~impl() { if (address_manager_registered) { if (address_manager_registered_) { le_address_manager_->Unregister(this); } } Loading Loading @@ -81,22 +81,17 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback void handle_scan_results(LeMetaEventView event) { switch (event.GetSubeventCode()) { case hci::SubeventCode::ADVERTISING_REPORT: handle_advertising_report<LeAdvertisingReportView, LeAdvertisingReport, LeReport>( LeAdvertisingReportView::Create(event)); handle_advertising_report(LeAdvertisingReportView::Create(event)); break; case hci::SubeventCode::DIRECTED_ADVERTISING_REPORT: handle_advertising_report<LeDirectedAdvertisingReportView, LeDirectedAdvertisingReport, DirectedLeReport>( LeDirectedAdvertisingReportView::Create(event)); handle_directed_advertising_report(LeDirectedAdvertisingReportView::Create(event)); break; case hci::SubeventCode::EXTENDED_ADVERTISING_REPORT: handle_advertising_report<LeExtendedAdvertisingReportView, LeExtendedAdvertisingReport, ExtendedLeReport>( LeExtendedAdvertisingReportView::Create(event)); handle_extended_advertising_report(LeExtendedAdvertisingReportView::Create(event)); break; case hci::SubeventCode::SCAN_TIMEOUT: if (registered_callback_ != nullptr) { registered_callback_->Handler()->Post( common::BindOnce(&LeScanningManagerCallbacks::on_timeout, common::Unretained(registered_callback_))); registered_callback_ = nullptr; if (scanning_callbacks_ != nullptr) { scanning_callbacks_->OnTimeout(); } break; default: Loading @@ -104,9 +99,26 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback } } template <class EventType, class ReportStructType, class ReportType> void handle_advertising_report(EventType event_view) { if (registered_callback_ == nullptr) { struct ExtendedEventTypeOptions { bool connectable{false}; bool scannable{false}; bool directed{false}; bool scan_response{false}; bool legacy{false}; bool continuing{false}; bool truncated{false}; }; void transform_to_extended_event_type(uint16_t* extended_event_type, ExtendedEventTypeOptions o) { ASSERT(extended_event_type != nullptr); *extended_event_type = (o.connectable ? 0x0001 << 0 : 0) | (o.scannable ? 0x0001 << 1 : 0) | (o.directed ? 0x0001 << 2 : 0) | (o.scan_response ? 0x0001 << 3 : 0) | (o.legacy ? 0x0001 << 4 : 0) | (o.continuing ? 0x0001 << 5 : 0) | (o.truncated ? 0x0001 << 6 : 0); } void handle_advertising_report(LeAdvertisingReportView event_view) { if (scanning_callbacks_ == nullptr) { LOG_INFO("Dropping advertising event (no registered handler)"); return; } Loading @@ -114,18 +126,103 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback LOG_INFO("Dropping invalid advertising event"); return; } std::vector<ReportStructType> report_vector = event_view.GetAdvertisingReports(); if (report_vector.empty()) { std::vector<LeAdvertisingReport> reports = event_view.GetAdvertisingReports(); if (reports.empty()) { LOG_INFO("Zero results in advertising event"); return; } std::vector<std::shared_ptr<LeReport>> param; param.reserve(report_vector.size()); for (const ReportStructType& report : report_vector) { param.push_back(std::shared_ptr<LeReport>(static_cast<LeReport*>(new ReportType(report)))); // TODO: handle AdvertisingCache for scan response for (LeAdvertisingReport report : reports) { uint16_t extended_event_type = 0; switch (report.event_type_) { case hci::AdvertisingEventType::ADV_IND: transform_to_extended_event_type( &extended_event_type, {.connectable = true, .scannable = true, .legacy = true}); break; case hci::AdvertisingEventType::ADV_DIRECT_IND: transform_to_extended_event_type( &extended_event_type, {.connectable = true, .directed = true, .legacy = true}); break; case hci::AdvertisingEventType::ADV_SCAN_IND: transform_to_extended_event_type(&extended_event_type, {.scannable = true, .legacy = true}); break; case hci::AdvertisingEventType::ADV_NONCONN_IND: transform_to_extended_event_type(&extended_event_type, {.legacy = true}); break; case hci::AdvertisingEventType::SCAN_RESPONSE: transform_to_extended_event_type( &extended_event_type, {.connectable = true, .scannable = true, .scan_response = true, .legacy = true}); break; default: LOG_WARN("Unsupported event type:%d", (uint16_t)report.event_type_); return; } scanning_callbacks_->OnScanResult( (uint16_t)report.event_type_, (uint8_t)report.address_type_, report.address_, (uint8_t)PrimaryPhyType::LE_1M, (uint8_t)SecondaryPhyType::NO_PACKETS, kAdvertisingDataInfoNotPresent, kTxPowerInformationNotPresent, report.rssi_, kNotPeriodicAdvertisement, report.advertising_data_); } } void handle_directed_advertising_report(LeDirectedAdvertisingReportView event_view) { if (scanning_callbacks_ == nullptr) { LOG_INFO("Dropping advertising event (no registered handler)"); return; } if (!event_view.IsValid()) { LOG_INFO("Dropping invalid advertising event"); return; } std::vector<LeDirectedAdvertisingReport> reports = event_view.GetAdvertisingReports(); if (reports.empty()) { LOG_INFO("Zero results in advertising event"); return; } uint16_t extended_event_type = 0; transform_to_extended_event_type(&extended_event_type, {.connectable = true, .directed = true, .legacy = true}); // TODO: parse report } void handle_extended_advertising_report(LeExtendedAdvertisingReportView event_view) { if (scanning_callbacks_ == nullptr) { LOG_INFO("Dropping advertising event (no registered handler)"); return; } if (!event_view.IsValid()) { LOG_INFO("Dropping invalid advertising event"); return; } std::vector<LeExtendedAdvertisingReport> reports = event_view.GetAdvertisingReports(); if (reports.empty()) { LOG_INFO("Zero results in advertising event"); return; } // TODO: handle AdvertisingCache for scan response for (LeExtendedAdvertisingReport report : reports) { uint16_t event_type = report.connectable_ | (report.scannable_ << 1) | (report.directed_ << 2) | (report.scan_response_ << 3) | (report.legacy_ << 4) | ((uint16_t)report.data_status_ << 5); scanning_callbacks_->OnScanResult( event_type, (uint8_t)report.address_type_, report.address_, (uint8_t)report.primary_phy_, (uint8_t)report.secondary_phy_, report.advertising_sid_, report.tx_power_, report.rssi_, report.periodic_advertising_interval_, report.advertising_data_); } registered_callback_->Handler()->Post(common::BindOnce(&LeScanningManagerCallbacks::on_advertisements, common::Unretained(registered_callback_), param)); } void configure_scan() { Loading Loading @@ -196,25 +293,35 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback } } void start_scan(LeScanningManagerCallbacks* le_scanning_manager_callbacks) { registered_callback_ = le_scanning_manager_callbacks; if (!address_manager_registered) { le_address_manager_->Register(this); address_manager_registered = true; void scan(bool start) { if (start) { start_scan(); } else { if (address_manager_registered_) { le_address_manager_->Unregister(this); address_manager_registered_ = false; } stop_scan(); } } // If we receive start_scan during paused, replace the cached_registered_callback_ for OnResume if (cached_registered_callback_ != nullptr) { cached_registered_callback_ = registered_callback_; void start_scan() { // If we receive start_scan during paused, set scan_on_resume_ to true if (paused_) { scan_on_resume_ = true; return; } is_scanning_ = true; if (!address_manager_registered_) { le_address_manager_->Register(this); address_manager_registered_ = true; } switch (api_type_) { case ScanApiType::EXTENDED: le_scanning_interface_->EnqueueCommand( hci::LeSetExtendedScanEnableBuilder::Create(Enable::ENABLED, FilterDuplicates::DISABLED /* filter duplicates */, 0, 0), hci::LeSetExtendedScanEnableBuilder::Create( Enable::ENABLED, FilterDuplicates::DISABLED /* filter duplicates */, 0, 0), module_handler_->BindOnce(impl::check_status)); break; case ScanApiType::ANDROID_HCI: Loading @@ -226,30 +333,21 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback } } void stop_scan(common::Callback<void()> on_stopped, bool from_on_pause) { if (address_manager_registered && !from_on_pause) { cached_registered_callback_ = nullptr; le_address_manager_->Unregister(this); address_manager_registered = false; } if (registered_callback_ == nullptr) { return; } registered_callback_->Handler()->Post(std::move(on_stopped)); void stop_scan() { is_scanning_ = false; switch (api_type_) { case ScanApiType::EXTENDED: le_scanning_interface_->EnqueueCommand( hci::LeSetExtendedScanEnableBuilder::Create(Enable::DISABLED, FilterDuplicates::DISABLED /* filter duplicates */, 0, 0), hci::LeSetExtendedScanEnableBuilder::Create( Enable::DISABLED, FilterDuplicates::DISABLED /* filter duplicates */, 0, 0), module_handler_->BindOnce(impl::check_status)); registered_callback_ = nullptr; break; case ScanApiType::ANDROID_HCI: case ScanApiType::LEGACY: le_scanning_interface_->EnqueueCommand( hci::LeSetScanEnableBuilder::Create(Enable::DISABLED, Enable::DISABLED /* filter duplicates */), module_handler_->BindOnce(impl::check_status)); registered_callback_ = nullptr; break; } } Loading @@ -259,8 +357,10 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback } void OnPause() override { cached_registered_callback_ = registered_callback_; stop_scan(common::Bind(&impl::ack_pause, common::Unretained(this)), true); paused_ = true; scan_on_resume_ = is_scanning_; stop_scan(); ack_pause(); } void ack_pause() { Loading @@ -268,27 +368,27 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback } void OnResume() override { if (cached_registered_callback_ != nullptr) { auto cached_registered_callback = cached_registered_callback_; cached_registered_callback_ = nullptr; start_scan(cached_registered_callback); paused_ = false; if (scan_on_resume_ == true) { start_scan(); } le_address_manager_->AckResume(this); } ScanApiType api_type_; LeScanningManagerCallbacks* registered_callback_ = nullptr; LeScanningManagerCallbacks* cached_registered_callback_ = nullptr; Module* module_; os::Handler* module_handler_; hci::HciLayer* hci_layer_; hci::Controller* controller_; hci::LeScanningInterface* le_scanning_interface_; hci::LeAddressManager* le_address_manager_; bool address_manager_registered = false; bool address_manager_registered_ = false; ScanningCallback* scanning_callbacks_ = nullptr; std::vector<Scanner> scanners_; bool is_scanning_ = false; bool scan_on_resume_ = false; bool paused_ = false; uint32_t interval_ms_{1000}; uint16_t window_ms_{1000}; Loading Loading @@ -359,12 +459,8 @@ void LeScanningManager::Unregister(ScannerId scanner_id) { CallOn(pimpl_.get(), &impl::unregister_scanner, scanner_id); } void LeScanningManager::StartScan(LeScanningManagerCallbacks* callbacks) { GetHandler()->Post(common::Bind(&impl::start_scan, common::Unretained(pimpl_.get()), callbacks)); } void LeScanningManager::StopScan(common::Callback<void()> on_stopped) { GetHandler()->Post(common::Bind(&impl::stop_scan, common::Unretained(pimpl_.get()), on_stopped, false)); void LeScanningManager::Scan(bool start) { CallOn(pimpl_.get(), &impl::scan, start); } void LeScanningManager::RegisterScanningCallback(ScanningCallback* scanning_callback) { Loading
system/gd/hci/le_scanning_manager.h +9 −15 Original line number Diff line number Diff line Loading @@ -26,14 +26,6 @@ namespace bluetooth { namespace hci { class LeScanningManagerCallbacks { public: virtual ~LeScanningManagerCallbacks() = default; virtual void on_advertisements(std::vector<std::shared_ptr<LeReport>>) = 0; virtual void on_timeout() = 0; virtual os::Handler* Handler() = 0; }; using ScannerId = uint8_t; class ScanningCallback { Loading @@ -49,32 +41,34 @@ class ScanningCallback { const bluetooth::hci::Uuid app_uuid, ScannerId scanner_id, ScanningStatus status) = 0; virtual void OnScanResult( uint16_t event_type, uint8_t addr_type, Address* bda, uint8_t address_type, Address address, uint8_t primary_phy, uint8_t secondary_phy, uint8_t advertising_sid, int8_t tx_power, int8_t rssi, uint16_t periodic_adv_int, std::vector<uint8_t> adv_data) = 0; uint16_t periodic_advertising_interval, std::vector<GapData> advertising_data) = 0; virtual void OnTrackAdvFoundLost() = 0; virtual void OnBatchScanReports( int client_if, int status, int report_format, int num_records, std::vector<uint8_t> data) = 0; virtual void OnTimeout() = 0; }; class LeScanningManager : public bluetooth::Module { public: static constexpr uint8_t kMaxAppNum = 32; static constexpr uint8_t kAdvertisingDataInfoNotPresent = 0xff; static constexpr uint8_t kTxPowerInformationNotPresent = 0x7f; static constexpr uint8_t kNotPeriodicAdvertisement = 0x00; LeScanningManager(); void RegisterScanner(const Uuid app_uuid); void Unregister(ScannerId scanner_id); void StartScan(LeScanningManagerCallbacks* callbacks); void StopScan(common::Callback<void()> on_stopped); void Scan(bool start); void RegisterScanningCallback(ScanningCallback* scanning_callback); Loading
system/gd/hci/le_scanning_manager_test.cc +34 −16 Original line number Diff line number Diff line Loading @@ -236,9 +236,6 @@ class LeScanningManagerTest : public ::testing::Test { fake_registry_.InjectTestModule(&HciLayer::Factory, test_hci_layer_); fake_registry_.InjectTestModule(&Controller::Factory, test_controller_); fake_registry_.InjectTestModule(&AclManager::Factory, test_acl_manager_); client_handler_ = fake_registry_.GetTestModuleHandler(&HciLayer::Factory); ASSERT_NE(client_handler_, nullptr); mock_callbacks_.handler_ = client_handler_; std::future<void> config_future = test_hci_layer_->GetCommandFuture(); fake_registry_.Start<LeScanningManager>(&thread_); le_scanning_manager = Loading @@ -246,6 +243,7 @@ class LeScanningManagerTest : public ::testing::Test { auto result = config_future.wait_for(std::chrono::duration(std::chrono::milliseconds(1000))); ASSERT_EQ(std::future_status::ready, result); HandleConfiguration(); le_scanning_manager->RegisterScanningCallback(&mock_callbacks_); } void TearDown() override { Loading @@ -266,14 +264,34 @@ class LeScanningManagerTest : public ::testing::Test { LeScanningManager* le_scanning_manager = nullptr; os::Handler* client_handler_ = nullptr; class MockLeScanningManagerCallbacks : public LeScanningManagerCallbacks { class MockCallbacks : public bluetooth::hci::ScanningCallback { public: MOCK_METHOD(void, on_advertisements, (std::vector<std::shared_ptr<LeReport>>), (override)); MOCK_METHOD(void, on_timeout, (), (override)); os::Handler* Handler() { return handler_; } os::Handler* handler_{nullptr}; MOCK_METHOD( void, OnScannerRegistered, (const bluetooth::hci::Uuid app_uuid, ScannerId scanner_id, ScanningStatus status), (override)); MOCK_METHOD( void, OnScanResult, (uint16_t event_type, uint8_t address_type, Address address, uint8_t primary_phy, uint8_t secondary_phy, uint8_t advertising_sid, int8_t tx_power, int8_t rssi, uint16_t periodic_advertising_interval, std::vector<GapData> advertising_data), (override)); MOCK_METHOD(void, OnTrackAdvFoundLost, (), (override)); MOCK_METHOD( void, OnBatchScanReports, (int client_if, int status, int report_format, int num_records, std::vector<uint8_t> data), (override)); MOCK_METHOD(void, OnTimeout, (), (override)); } mock_callbacks_; OpCode param_opcode_{OpCode::LE_SET_ADVERTISING_PARAMETERS}; Loading Loading @@ -309,7 +327,7 @@ TEST_F(LeScanningManagerTest, startup_teardown) {} TEST_F(LeScanningManagerTest, start_scan_test) { auto next_command_future = test_hci_layer_->GetCommandFuture(); le_scanning_manager->StartScan(&mock_callbacks_); le_scanning_manager->Scan(true); auto result = next_command_future.wait_for(std::chrono::duration(std::chrono::milliseconds(100))); ASSERT_EQ(std::future_status::ready, result); Loading @@ -329,14 +347,14 @@ TEST_F(LeScanningManagerTest, start_scan_test) { gap_data.push_back(data_item); report.advertising_data_ = gap_data; EXPECT_CALL(mock_callbacks_, on_advertisements); EXPECT_CALL(mock_callbacks_, OnScanResult); test_hci_layer_->IncomingLeMetaEvent(LeAdvertisingReportBuilder::Create({report})); } TEST_F(LeAndroidHciScanningManagerTest, start_scan_test) { auto next_command_future = test_hci_layer_->GetCommandFuture(); le_scanning_manager->StartScan(&mock_callbacks_); le_scanning_manager->Scan(true); auto result = next_command_future.wait_for(std::chrono::duration(std::chrono::milliseconds(100))); ASSERT_EQ(std::future_status::ready, result); Loading @@ -356,14 +374,14 @@ TEST_F(LeAndroidHciScanningManagerTest, start_scan_test) { gap_data.push_back(data_item); report.advertising_data_ = gap_data; EXPECT_CALL(mock_callbacks_, on_advertisements); EXPECT_CALL(mock_callbacks_, OnScanResult); test_hci_layer_->IncomingLeMetaEvent(LeAdvertisingReportBuilder::Create({report})); } TEST_F(LeExtendedScanningManagerTest, start_scan_test) { auto next_command_future = test_hci_layer_->GetCommandFuture(); le_scanning_manager->StartScan(&mock_callbacks_); le_scanning_manager->Scan(true); auto result = next_command_future.wait_for(std::chrono::duration(std::chrono::milliseconds(100))); ASSERT_EQ(std::future_status::ready, result); Loading @@ -386,7 +404,7 @@ TEST_F(LeExtendedScanningManagerTest, start_scan_test) { gap_data.push_back(data_item); report.advertising_data_ = gap_data; EXPECT_CALL(mock_callbacks_, on_advertisements); EXPECT_CALL(mock_callbacks_, OnScanResult); test_hci_layer_->IncomingLeMetaEvent(LeExtendedAdvertisingReportBuilder::Create({report})); } Loading