blob: bf790b78ebbce5a2d9c6b4664adcd4638fa23626 [file] [log] [blame]
/*
* 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 <cstdint>
#include <unordered_map>
#include <utility>
#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<LeReportMsg>* 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<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);
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_ = 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: {
LeReportMsg le_report_msg;
std::vector<LeExtendedAdvertisingReport> 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<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::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_;
}
LeScanningManager* le_scanning_manager_;
os::Handler* facade_handler_;
::bluetooth::grpc::GrpcEventQueue<LeReportMsg> pending_events_{"LeReports"};
};
void LeScanningManagerFacadeModule::ListDependencies(ModuleList* list) {
::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list);
list->add<hci::LeScanningManager>();
}
void LeScanningManagerFacadeModule::Start() {
::bluetooth::grpc::GrpcFacadeModule::Start();
service_ = new LeScanningManagerFacadeService(GetDependency<hci::LeScanningManager>(), 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