blob: e7f9d56ee28f9236c0c477f9781520d1629e6246 [file] [log] [blame]
/*
* 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 <memory>
#include <unordered_map>
#include <utility>
#include "common/bind.h"
#include "hci/hci_packets.h"
#include "hci/remote_name_request.h"
#include "module.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<hci::Address, std::list<PendingRemoteNameRead>> address_to_pending_read_map_;
std::unordered_map<hci::Address, RemoteName> address_to_name_map_;
void OnRemoteNameResponse(hci::Address address, hci::ErrorCode status, RemoteName name);
hci::RemoteNameRequestModule* 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<PendingRemoteNameRead> 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_->StartRemoteNameRequest(
address,
hci::RemoteNameRequestBuilder::Create(
address, page_scan_repetition_mode, clock_offset, clock_offset_valid),
handler_->BindOnce([](hci::ErrorCode /* status */) {}),
handler_->BindOnce([&](uint64_t /* features */) {
LOG_WARN("UNIMPLEMENTED: ignoring host supported features");
}),
handler_->BindOnceOn(this, &NameDbModule::impl::OnRemoteNameResponse, address));
}
void neighbor::NameDbModule::impl::OnRemoteNameResponse(
hci::Address address, hci::ErrorCode status, 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<impl>(*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<hci::RemoteNameRequestModule>();
handler_ = module_.GetHandler();
}
void neighbor::NameDbModule::impl::Stop() {}
/**
* Module methods here
*/
void neighbor::NameDbModule::ListDependencies(ModuleList* list) const {
list->add<hci::RemoteNameRequestModule>();
}
void neighbor::NameDbModule::Start() {
pimpl_->Start();
}
void neighbor::NameDbModule::Stop() {
pimpl_->Stop();
}
} // namespace neighbor
} // namespace bluetooth