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 <memory>
21 #include <unordered_map>
22 #include <utility>
23 
24 #include "common/bind.h"
25 #include "module.h"
26 #include "neighbor/name.h"
27 #include "os/handler.h"
28 #include "os/log.h"
29 
30 namespace bluetooth {
31 namespace neighbor {
32 
33 namespace {
34 struct PendingRemoteNameRead {
35   ReadRemoteNameDbCallback callback_;
36   os::Handler* handler_;
37 };
38 }  // namespace
39 
40 struct NameDbModule::impl {
41   void ReadRemoteNameRequest(hci::Address address, ReadRemoteNameDbCallback callback, os::Handler* handler);
42 
43   bool IsNameCached(hci::Address address) const;
44   RemoteName ReadCachedRemoteName(hci::Address address) const;
45 
46   impl(const NameDbModule& module);
47 
48   void Start();
49   void Stop();
50 
51  private:
52   std::unordered_map<hci::Address, PendingRemoteNameRead> address_to_pending_read_map_;
53   std::unordered_map<hci::Address, RemoteName> address_to_name_map_;
54 
55   void OnRemoteNameResponse(hci::ErrorCode status, hci::Address address, RemoteName name);
56 
57   neighbor::NameModule* name_module_;
58 
59   const NameDbModule& module_;
60   os::Handler* handler_;
61 };
62 
63 const ModuleFactory neighbor::NameDbModule::Factory = ModuleFactory([]() { return new neighbor::NameDbModule(); });
64 
65 neighbor::NameDbModule::impl::impl(const neighbor::NameDbModule& module) : module_(module) {}
66 
67 void neighbor::NameDbModule::impl::ReadRemoteNameRequest(hci::Address address, ReadRemoteNameDbCallback callback,
68                                                          os::Handler* handler) {
69   if (address_to_pending_read_map_.find(address) != address_to_pending_read_map_.end()) {
70     LOG_WARN("Already have remote read db in progress and currently can only have one outstanding");
71     return;
72   }
73 
74   address_to_pending_read_map_[address] = {std::move(callback), std::move(handler)};
75 
76   // TODO(cmanton) Use remote name request defaults for now
77   hci::PageScanRepetitionMode page_scan_repetition_mode = hci::PageScanRepetitionMode::R1;
78   uint16_t clock_offset = 0;
79   hci::ClockOffsetValid clock_offset_valid = hci::ClockOffsetValid::INVALID;
80   name_module_->ReadRemoteNameRequest(
81       address, page_scan_repetition_mode, clock_offset, clock_offset_valid,
82       common::BindOnce(&NameDbModule::impl::OnRemoteNameResponse, common::Unretained(this)), handler_);
83 }
84 
85 void neighbor::NameDbModule::impl::OnRemoteNameResponse(hci::ErrorCode status, hci::Address address, RemoteName name) {
86   ASSERT(address_to_pending_read_map_.find(address) != address_to_pending_read_map_.end());
87   PendingRemoteNameRead callback_handler = std::move(address_to_pending_read_map_.at(address));
88 
89   if (status == hci::ErrorCode::SUCCESS) {
90     address_to_name_map_[address] = name;
91   }
92   callback_handler.handler_->Post(
93       common::BindOnce(std::move(callback_handler.callback_), address, status == hci::ErrorCode::SUCCESS));
94 }
95 
96 bool neighbor::NameDbModule::impl::IsNameCached(hci::Address address) const {
97   return address_to_name_map_.count(address) == 1;
98 }
99 
100 RemoteName neighbor::NameDbModule::impl::ReadCachedRemoteName(hci::Address address) const {
101   ASSERT(IsNameCached(address));
102   return address_to_name_map_.at(address);
103 }
104 
105 /**
106  * General API here
107  */
108 neighbor::NameDbModule::NameDbModule() : pimpl_(std::make_unique<impl>(*this)) {}
109 
110 neighbor::NameDbModule::~NameDbModule() {
111   pimpl_.reset();
112 }
113 
114 void neighbor::NameDbModule::ReadRemoteNameRequest(hci::Address address, ReadRemoteNameDbCallback callback,
115                                                    os::Handler* handler) {
116   GetHandler()->Post(common::BindOnce(&NameDbModule::impl::ReadRemoteNameRequest, common::Unretained(pimpl_.get()),
117                                       address, std::move(callback), handler));
118 }
119 
120 bool neighbor::NameDbModule::IsNameCached(hci::Address address) const {
121   return pimpl_->IsNameCached(address);
122 }
123 
124 RemoteName neighbor::NameDbModule::ReadCachedRemoteName(hci::Address address) const {
125   return pimpl_->ReadCachedRemoteName(address);
126 }
127 
128 void neighbor::NameDbModule::impl::Start() {
129   name_module_ = module_.GetDependency<neighbor::NameModule>();
130   handler_ = module_.GetHandler();
131 }
132 
133 void neighbor::NameDbModule::impl::Stop() {}
134 
135 /**
136  * Module methods here
137  */
138 void neighbor::NameDbModule::ListDependencies(ModuleList* list) {
139   list->add<neighbor::NameModule>();
140 }
141 
142 void neighbor::NameDbModule::Start() {
143   pimpl_->Start();
144 }
145 
146 void neighbor::NameDbModule::Stop() {
147   pimpl_->Stop();
148 }
149 
150 }  // namespace neighbor
151 }  // namespace bluetooth
152