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 #include "os/log.h"
32 
33 namespace bluetooth {
34 namespace neighbor {
35 
36 namespace {
37 struct PendingRemoteNameRead {
38   ReadRemoteNameDbCallback callback_;
39   os::Handler* handler_;
40 };
41 }  // namespace
42 
43 struct NameDbModule::impl {
44   void ReadRemoteNameRequest(
45       hci::Address address, ReadRemoteNameDbCallback callback, os::Handler* handler);
46 
47   bool IsNameCached(hci::Address address) const;
48   RemoteName ReadCachedRemoteName(hci::Address address) const;
49 
50   impl(const NameDbModule& module);
51 
52   void Start();
53   void Stop();
54 
55  private:
56   std::unordered_map<hci::Address, std::list<PendingRemoteNameRead>> address_to_pending_read_map_;
57   std::unordered_map<hci::Address, RemoteName> address_to_name_map_;
58 
59   void OnRemoteNameResponse(hci::Address address, hci::ErrorCode status, RemoteName name);
60 
61   hci::RemoteNameRequestModule* name_module_;
62 
63   const NameDbModule& module_;
64   os::Handler* handler_;
65 };
66 
67 const ModuleFactory neighbor::NameDbModule::Factory =
__anon8a0f1bbf0202() 68     ModuleFactory([]() { return new neighbor::NameDbModule(); });
69 
impl(const neighbor::NameDbModule & module)70 neighbor::NameDbModule::impl::impl(const neighbor::NameDbModule& module) : module_(module) {}
71 
ReadRemoteNameRequest(hci::Address address,ReadRemoteNameDbCallback callback,os::Handler * handler)72 void neighbor::NameDbModule::impl::ReadRemoteNameRequest(
73     hci::Address address, ReadRemoteNameDbCallback callback, 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(
91           address, page_scan_repetition_mode, clock_offset, 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(
100     hci::Address address, hci::ErrorCode status, RemoteName name) {
101   log::assert_that(
102       address_to_pending_read_map_.find(address) != address_to_pending_read_map_.end(),
103       "assert failed: address_to_pending_read_map_.find(address) != "
104       "address_to_pending_read_map_.end()");
105   if (status == hci::ErrorCode::SUCCESS) {
106     address_to_name_map_[address] = name;
107   }
108   auto& callback_list = address_to_pending_read_map_.at(address);
109   for (auto& it : callback_list) {
110     it.handler_->Call(std::move(it.callback_), address, status == hci::ErrorCode::SUCCESS);
111   }
112   address_to_pending_read_map_.erase(address);
113 }
114 
IsNameCached(hci::Address address) const115 bool neighbor::NameDbModule::impl::IsNameCached(hci::Address address) const {
116   return address_to_name_map_.count(address) == 1;
117 }
118 
ReadCachedRemoteName(hci::Address address) const119 RemoteName neighbor::NameDbModule::impl::ReadCachedRemoteName(hci::Address address) const {
120   log::assert_that(IsNameCached(address), "assert failed: IsNameCached(address)");
121   return address_to_name_map_.at(address);
122 }
123 
124 /**
125  * General API here
126  */
NameDbModule()127 neighbor::NameDbModule::NameDbModule() : pimpl_(std::make_unique<impl>(*this)) {}
128 
~NameDbModule()129 neighbor::NameDbModule::~NameDbModule() {
130   pimpl_.reset();
131 }
132 
ReadRemoteNameRequest(hci::Address address,ReadRemoteNameDbCallback callback,os::Handler * handler)133 void neighbor::NameDbModule::ReadRemoteNameRequest(
134     hci::Address address, ReadRemoteNameDbCallback callback, os::Handler* handler) {
135   GetHandler()->Post(common::BindOnce(
136       &NameDbModule::impl::ReadRemoteNameRequest,
137       common::Unretained(pimpl_.get()),
138       address,
139       std::move(callback),
140       handler));
141 }
142 
IsNameCached(hci::Address address) const143 bool neighbor::NameDbModule::IsNameCached(hci::Address address) const {
144   return pimpl_->IsNameCached(address);
145 }
146 
ReadCachedRemoteName(hci::Address address) const147 RemoteName neighbor::NameDbModule::ReadCachedRemoteName(hci::Address address) const {
148   return pimpl_->ReadCachedRemoteName(address);
149 }
150 
Start()151 void neighbor::NameDbModule::impl::Start() {
152   name_module_ = module_.GetDependency<hci::RemoteNameRequestModule>();
153   handler_ = module_.GetHandler();
154 }
155 
Stop()156 void neighbor::NameDbModule::impl::Stop() {}
157 
158 /**
159  * Module methods here
160  */
ListDependencies(ModuleList * list) const161 void neighbor::NameDbModule::ListDependencies(ModuleList* list) const {
162   list->add<hci::RemoteNameRequestModule>();
163 }
164 
Start()165 void neighbor::NameDbModule::Start() {
166   pimpl_->Start();
167 }
168 
Stop()169 void neighbor::NameDbModule::Stop() {
170   pimpl_->Stop();
171 }
172 
173 }  // namespace neighbor
174 }  // namespace bluetooth
175