1 /*
2 * Copyright 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #define LOG_TAG "bt_gd_neigh"
17
18 #include "neighbor/name_db.h"
19
20 #include <bluetooth/log.h>
21
22 #include <memory>
23 #include <unordered_map>
24 #include <utility>
25
26 #include "common/bind.h"
27 #include "hci/hci_packets.h"
28 #include "hci/remote_name_request.h"
29 #include "module.h"
30 #include "os/handler.h"
31
32 namespace bluetooth {
33 namespace neighbor {
34
35 namespace {
36 struct PendingRemoteNameRead {
37 ReadRemoteNameDbCallback callback_;
38 os::Handler* handler_;
39 };
40 } // namespace
41
42 struct NameDbModule::impl {
43 void ReadRemoteNameRequest(hci::Address address, ReadRemoteNameDbCallback callback,
44 os::Handler* handler);
45
46 bool IsNameCached(hci::Address address) const;
47 RemoteName ReadCachedRemoteName(hci::Address address) const;
48
49 impl(const NameDbModule& module);
50
51 void Start();
52 void Stop();
53
54 private:
55 std::unordered_map<hci::Address, std::list<PendingRemoteNameRead>> address_to_pending_read_map_;
56 std::unordered_map<hci::Address, RemoteName> address_to_name_map_;
57
58 void OnRemoteNameResponse(hci::Address address, hci::ErrorCode status, RemoteName name);
59
60 hci::RemoteNameRequestModule* name_module_;
61
62 const NameDbModule& module_;
63 os::Handler* handler_;
64 };
65
66 const ModuleFactory neighbor::NameDbModule::Factory =
__anon003dd0f50202() 67 ModuleFactory([]() { return new neighbor::NameDbModule(); });
68
impl(const neighbor::NameDbModule & module)69 neighbor::NameDbModule::impl::impl(const neighbor::NameDbModule& module) : module_(module) {}
70
ReadRemoteNameRequest(hci::Address address,ReadRemoteNameDbCallback callback,os::Handler * handler)71 void neighbor::NameDbModule::impl::ReadRemoteNameRequest(hci::Address address,
72 ReadRemoteNameDbCallback callback,
73 os::Handler* handler) {
74 if (address_to_pending_read_map_.find(address) != address_to_pending_read_map_.end()) {
75 log::warn("Already have remote read db in progress; adding callback to callback list");
76 address_to_pending_read_map_[address].push_back({std::move(callback), handler});
77 return;
78 }
79
80 std::list<PendingRemoteNameRead> tmp;
81 address_to_pending_read_map_[address] = std::move(tmp);
82 address_to_pending_read_map_[address].push_back({std::move(callback), handler});
83
84 // TODO(cmanton) Use remote name request defaults for now
85 hci::PageScanRepetitionMode page_scan_repetition_mode = hci::PageScanRepetitionMode::R1;
86 uint16_t clock_offset = 0;
87 hci::ClockOffsetValid clock_offset_valid = hci::ClockOffsetValid::INVALID;
88 name_module_->StartRemoteNameRequest(
89 address,
90 hci::RemoteNameRequestBuilder::Create(address, page_scan_repetition_mode, clock_offset,
91 clock_offset_valid),
92 handler_->BindOnce([](hci::ErrorCode /* status */) {}),
93 handler_->BindOnce([&](uint64_t /* features */) {
94 log::warn("UNIMPLEMENTED: ignoring host supported features");
95 }),
96 handler_->BindOnceOn(this, &NameDbModule::impl::OnRemoteNameResponse, address));
97 }
98
OnRemoteNameResponse(hci::Address address,hci::ErrorCode status,RemoteName name)99 void neighbor::NameDbModule::impl::OnRemoteNameResponse(hci::Address address, hci::ErrorCode status,
100 RemoteName name) {
101 log::assert_that(address_to_pending_read_map_.find(address) != address_to_pending_read_map_.end(),
102 "assert failed: address_to_pending_read_map_.find(address) != "
103 "address_to_pending_read_map_.end()");
104 if (status == hci::ErrorCode::SUCCESS) {
105 address_to_name_map_[address] = name;
106 }
107 auto& callback_list = address_to_pending_read_map_.at(address);
108 for (auto& it : callback_list) {
109 it.handler_->Call(std::move(it.callback_), address, status == hci::ErrorCode::SUCCESS);
110 }
111 address_to_pending_read_map_.erase(address);
112 }
113
IsNameCached(hci::Address address) const114 bool neighbor::NameDbModule::impl::IsNameCached(hci::Address address) const {
115 return address_to_name_map_.count(address) == 1;
116 }
117
ReadCachedRemoteName(hci::Address address) const118 RemoteName neighbor::NameDbModule::impl::ReadCachedRemoteName(hci::Address address) const {
119 log::assert_that(IsNameCached(address), "assert failed: IsNameCached(address)");
120 return address_to_name_map_.at(address);
121 }
122
123 /**
124 * General API here
125 */
NameDbModule()126 neighbor::NameDbModule::NameDbModule() : pimpl_(std::make_unique<impl>(*this)) {}
127
~NameDbModule()128 neighbor::NameDbModule::~NameDbModule() { pimpl_.reset(); }
129
ReadRemoteNameRequest(hci::Address address,ReadRemoteNameDbCallback callback,os::Handler * handler)130 void neighbor::NameDbModule::ReadRemoteNameRequest(hci::Address address,
131 ReadRemoteNameDbCallback callback,
132 os::Handler* handler) {
133 GetHandler()->Post(common::BindOnce(&NameDbModule::impl::ReadRemoteNameRequest,
134 common::Unretained(pimpl_.get()), address,
135 std::move(callback), handler));
136 }
137
IsNameCached(hci::Address address) const138 bool neighbor::NameDbModule::IsNameCached(hci::Address address) const {
139 return pimpl_->IsNameCached(address);
140 }
141
ReadCachedRemoteName(hci::Address address) const142 RemoteName neighbor::NameDbModule::ReadCachedRemoteName(hci::Address address) const {
143 return pimpl_->ReadCachedRemoteName(address);
144 }
145
Start()146 void neighbor::NameDbModule::impl::Start() {
147 name_module_ = module_.GetDependency<hci::RemoteNameRequestModule>();
148 handler_ = module_.GetHandler();
149 }
150
Stop()151 void neighbor::NameDbModule::impl::Stop() {}
152
153 /**
154 * Module methods here
155 */
ListDependencies(ModuleList * list) const156 void neighbor::NameDbModule::ListDependencies(ModuleList* list) const {
157 list->add<hci::RemoteNameRequestModule>();
158 }
159
Start()160 void neighbor::NameDbModule::Start() { pimpl_->Start(); }
161
Stop()162 void neighbor::NameDbModule::Stop() { pimpl_->Stop(); }
163
164 } // namespace neighbor
165 } // namespace bluetooth
166