/* * Copyright 2020 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. */ #define LOG_TAG "bt_gd_neigh" #include "neighbor/name_db.h" #include #include #include #include "common/bind.h" #include "module.h" #include "neighbor/name.h" #include "os/handler.h" #include "os/log.h" namespace bluetooth { namespace neighbor { namespace { struct PendingRemoteNameRead { ReadRemoteNameDbCallback callback_; os::Handler* handler_; }; } // namespace struct NameDbModule::impl { void ReadRemoteNameRequest(hci::Address address, ReadRemoteNameDbCallback callback, os::Handler* handler); bool IsNameCached(hci::Address address) const; RemoteName ReadCachedRemoteName(hci::Address address) const; impl(const NameDbModule& module); void Start(); void Stop(); private: std::unordered_map> address_to_pending_read_map_; std::unordered_map address_to_name_map_; void OnRemoteNameResponse(hci::ErrorCode status, hci::Address address, RemoteName name); neighbor::NameModule* name_module_; const NameDbModule& module_; os::Handler* handler_; }; const ModuleFactory neighbor::NameDbModule::Factory = ModuleFactory([]() { return new neighbor::NameDbModule(); }); neighbor::NameDbModule::impl::impl(const neighbor::NameDbModule& module) : module_(module) {} void neighbor::NameDbModule::impl::ReadRemoteNameRequest( hci::Address address, ReadRemoteNameDbCallback callback, os::Handler* handler) { if (address_to_pending_read_map_.find(address) != address_to_pending_read_map_.end()) { LOG_WARN("Already have remote read db in progress; adding callback to callback list"); address_to_pending_read_map_[address].push_back({std::move(callback), handler}); return; } std::list tmp; address_to_pending_read_map_[address] = std::move(tmp); address_to_pending_read_map_[address].push_back({std::move(callback), handler}); // TODO(cmanton) Use remote name request defaults for now hci::PageScanRepetitionMode page_scan_repetition_mode = hci::PageScanRepetitionMode::R1; uint16_t clock_offset = 0; hci::ClockOffsetValid clock_offset_valid = hci::ClockOffsetValid::INVALID; name_module_->ReadRemoteNameRequest( address, page_scan_repetition_mode, clock_offset, clock_offset_valid, common::BindOnce(&NameDbModule::impl::OnRemoteNameResponse, common::Unretained(this)), handler_); } void neighbor::NameDbModule::impl::OnRemoteNameResponse(hci::ErrorCode status, hci::Address address, RemoteName name) { ASSERT(address_to_pending_read_map_.find(address) != address_to_pending_read_map_.end()); if (status == hci::ErrorCode::SUCCESS) { address_to_name_map_[address] = name; } auto& callback_list = address_to_pending_read_map_.at(address); for (auto& it : callback_list) { it.handler_->Call(std::move(it.callback_), address, status == hci::ErrorCode::SUCCESS); } address_to_pending_read_map_.erase(address); } bool neighbor::NameDbModule::impl::IsNameCached(hci::Address address) const { return address_to_name_map_.count(address) == 1; } RemoteName neighbor::NameDbModule::impl::ReadCachedRemoteName(hci::Address address) const { ASSERT(IsNameCached(address)); return address_to_name_map_.at(address); } /** * General API here */ neighbor::NameDbModule::NameDbModule() : pimpl_(std::make_unique(*this)) {} neighbor::NameDbModule::~NameDbModule() { pimpl_.reset(); } void neighbor::NameDbModule::ReadRemoteNameRequest( hci::Address address, ReadRemoteNameDbCallback callback, os::Handler* handler) { GetHandler()->Post(common::BindOnce( &NameDbModule::impl::ReadRemoteNameRequest, common::Unretained(pimpl_.get()), address, std::move(callback), handler)); } bool neighbor::NameDbModule::IsNameCached(hci::Address address) const { return pimpl_->IsNameCached(address); } RemoteName neighbor::NameDbModule::ReadCachedRemoteName(hci::Address address) const { return pimpl_->ReadCachedRemoteName(address); } void neighbor::NameDbModule::impl::Start() { name_module_ = module_.GetDependency(); handler_ = module_.GetHandler(); } void neighbor::NameDbModule::impl::Stop() {} /** * Module methods here */ void neighbor::NameDbModule::ListDependencies(ModuleList* list) { list->add(); } void neighbor::NameDbModule::Start() { pimpl_->Start(); } void neighbor::NameDbModule::Stop() { pimpl_->Stop(); } } // namespace neighbor } // namespace bluetooth