/* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "hci/le_scanning_manager.h" #include #include #include #include "common/bidi_queue.h" #include "common/bind.h" #include "grpc/grpc_event_queue.h" #include "hci/facade/le_scanning_manager_facade.grpc.pb.h" #include "hci/facade/le_scanning_manager_facade.h" #include "hci/facade/le_scanning_manager_facade.pb.h" #include "hci/le_report.h" #include "os/log.h" #include "packet/raw_builder.h" namespace bluetooth { namespace hci { namespace facade { using ::grpc::ServerAsyncResponseWriter; using ::grpc::ServerAsyncWriter; using ::grpc::ServerContext; using ::grpc::ServerWriter; using ::grpc::Status; class LeScanningManagerFacadeService : public LeScanningManagerFacade::Service, public LeScanningManagerCallbacks { 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); } ::grpc::Status StartScan(::grpc::ServerContext* context, const ::google::protobuf::Empty*, ::grpc::ServerWriter* writer) override { le_scanning_manager_->StartScan(this); return pending_events_.RunLoop(context, writer); } ::grpc::Status StopScan(::grpc::ServerContext* context, const ::google::protobuf::Empty*, ScanStoppedMsg* response) override { std::shared_ptr> on_stopped = std::make_shared>(); auto future = on_stopped->get_future(); le_scanning_manager_->StopScan( common::Bind([](std::shared_ptr> p) { p->set_value(); }, on_stopped)); auto result = future.wait_for(std::chrono::milliseconds(1000)); ASSERT(result == std::future_status::ready); return ::grpc::Status::OK; } void on_advertisements(std::vector> reports) override { for (const auto report : reports) { switch (report->report_type_) { case hci::LeReport::ReportType::ADVERTISING_EVENT: { LeReportMsg le_report_msg; std::vector advertisements; LeAdvertisingReport le_advertising_report; le_advertising_report.address_type_ = 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 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: { LeReportMsg le_report_msg; std::vector advertisements; LeExtendedAdvertisingReport le_extended_advertising_report; le_extended_advertising_report.address_ = report->address_; le_extended_advertising_report.advertising_data_ = report->gap_data_; le_extended_advertising_report.rssi_ = report->rssi_; advertisements.push_back(le_extended_advertising_report); auto builder = LeExtendedAdvertisingReportBuilder::Create(advertisements); std::vector 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::DIRECTED_ADVERTISING_EVENT: { LeReportMsg le_report_msg; std::vector 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 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(report->report_type_)); } } } void on_timeout() override { LeReportMsg le_report_msg; auto builder = LeScanTimeoutBuilder::Create(); std::vector 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_; } LeScanningManager* le_scanning_manager_; os::Handler* facade_handler_; ::bluetooth::grpc::GrpcEventQueue pending_events_{"LeReports"}; }; void LeScanningManagerFacadeModule::ListDependencies(ModuleList* list) { ::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list); list->add(); } void LeScanningManagerFacadeModule::Start() { ::bluetooth::grpc::GrpcFacadeModule::Start(); service_ = new LeScanningManagerFacadeService(GetDependency(), GetHandler()); } void LeScanningManagerFacadeModule::Stop() { delete service_; ::bluetooth::grpc::GrpcFacadeModule::Stop(); } ::grpc::Service* LeScanningManagerFacadeModule::GetService() const { return service_; } const ModuleFactory LeScanningManagerFacadeModule::Factory = ::bluetooth::ModuleFactory([]() { return new LeScanningManagerFacadeModule(); }); } // namespace facade } // namespace hci } // namespace bluetooth