1 /******************************************************************************
2 *
3 * Copyright 2019 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18 #include "hci/device_database.h"
19
20 #include <memory>
21 #include <utility>
22
23 #include "hci/classic_device.h"
24 #include "hci/dual_device.h"
25 #include "hci/le_device.h"
26 #include "os/log.h"
27
28 using namespace bluetooth::hci;
29
CreateClassicDevice(Address address)30 std::shared_ptr<ClassicDevice> DeviceDatabase::CreateClassicDevice(Address address) {
31 ClassicDevice device(address);
32 const std::string uuid = device.GetUuid();
33 AddDeviceToMap(std::move(device));
34 return GetClassicDevice(uuid);
35 }
36
CreateLeDevice(Address address)37 std::shared_ptr<LeDevice> DeviceDatabase::CreateLeDevice(Address address) {
38 LeDevice device(address);
39 const std::string uuid = device.GetUuid();
40 AddDeviceToMap(std::move(device));
41 return GetLeDevice(uuid);
42 }
43
CreateDualDevice(Address address)44 std::shared_ptr<DualDevice> DeviceDatabase::CreateDualDevice(Address address) {
45 auto classic = CreateClassicDevice(address);
46 auto le = CreateLeDevice(address);
47 if (classic && le) {
48 DualDevice device(address, classic, le);
49 std::string uuid = device.GetUuid();
50 AddDeviceToMap(std::move(device));
51 return GetDualDevice(uuid);
52 }
53 LOG_WARN("Attempting to instert a DUAL device that already exists!");
54 return std::shared_ptr<DualDevice>();
55 }
56
RemoveDevice(const std::shared_ptr<Device> & device)57 bool DeviceDatabase::RemoveDevice(const std::shared_ptr<Device>& device) {
58 const DeviceType type = device->GetDeviceType();
59 bool success;
60 switch (type) {
61 case CLASSIC:
62 success = false;
63 {
64 std::lock_guard<std::mutex> lock(device_map_mutex_);
65 auto classic_it = classic_device_map_.find(device->GetUuid());
66 // If we have a record with the same key
67 if (classic_it != classic_device_map_.end()) {
68 classic_device_map_.erase(device->GetUuid());
69 success = true;
70 }
71 }
72 if (success) {
73 ASSERT_LOG(WriteToDisk(), "Failed to write data to disk!");
74 } else {
75 LOG_WARN("Device not in database!");
76 }
77 return success;
78 case LE:
79 success = false;
80 {
81 std::lock_guard<std::mutex> lock(device_map_mutex_);
82 auto le_it = le_device_map_.find(device->GetUuid());
83 // If we have a record with the same key
84 if (le_it != le_device_map_.end()) {
85 le_device_map_.erase(device->GetUuid());
86 success = true;
87 }
88 }
89 if (success) {
90 ASSERT_LOG(WriteToDisk(), "Failed to write data to disk!");
91 } else {
92 LOG_WARN("Device not in database!");
93 }
94 return success;
95 case DUAL:
96 std::shared_ptr<DualDevice> dual_device = nullptr;
97 {
98 std::lock_guard<std::mutex> lock(device_map_mutex_);
99 auto dual_it = dual_device_map_.find(device->GetUuid());
100 if (dual_it != dual_device_map_.end()) {
101 dual_device = GetDualDevice(device->GetUuid());
102 }
103 }
104 success = false;
105 if (dual_device != nullptr) {
106 if (RemoveDevice(dual_device->GetClassicDevice()) && RemoveDevice(dual_device->GetLeDevice())) {
107 dual_device_map_.erase(device->GetUuid());
108 success = true;
109 }
110 }
111 if (success) {
112 ASSERT_LOG(WriteToDisk(), "Failed to write data to disk!");
113 } else {
114 LOG_WARN("Device not in database!");
115 }
116 return success;
117 }
118 }
119
GetClassicDevice(const std::string & uuid)120 std::shared_ptr<ClassicDevice> DeviceDatabase::GetClassicDevice(const std::string& uuid) {
121 std::lock_guard<std::mutex> lock(device_map_mutex_);
122 auto it = classic_device_map_.find(uuid);
123 if (it != classic_device_map_.end()) {
124 return it->second;
125 }
126 LOG_WARN("Device '%s' not found!", uuid.c_str());
127 return std::shared_ptr<ClassicDevice>();
128 }
129
GetLeDevice(const std::string & uuid)130 std::shared_ptr<LeDevice> DeviceDatabase::GetLeDevice(const std::string& uuid) {
131 std::lock_guard<std::mutex> lock(device_map_mutex_);
132 auto it = le_device_map_.find(uuid);
133 if (it != le_device_map_.end()) {
134 return it->second;
135 }
136 LOG_WARN("Device '%s' not found!", uuid.c_str());
137 return std::shared_ptr<LeDevice>();
138 }
139
GetDualDevice(const std::string & uuid)140 std::shared_ptr<DualDevice> DeviceDatabase::GetDualDevice(const std::string& uuid) {
141 std::lock_guard<std::mutex> lock(device_map_mutex_);
142 auto it = dual_device_map_.find(uuid);
143 if (it != dual_device_map_.end()) {
144 return it->second;
145 }
146 LOG_WARN("Device '%s' not found!", uuid.c_str());
147 return std::shared_ptr<DualDevice>();
148 }
149
UpdateDeviceAddress(const std::shared_ptr<Device> & device,Address new_address)150 bool DeviceDatabase::UpdateDeviceAddress(const std::shared_ptr<Device>& device, Address new_address) {
151 // Hold onto device
152 const DeviceType type = device->GetDeviceType();
153 if (type == CLASSIC) {
154 auto classic_device = GetClassicDevice(device->GetUuid());
155 // This gets rid of the shared_ptr in the map
156 ASSERT_LOG(RemoveDevice(device), "Failed to remove the device!");
157 classic_device->SetAddress(new_address);
158 // Move the value located at the pointer
159 return AddDeviceToMap(std::move(*(classic_device.get())));
160 } else if (type == LE) {
161 auto le_device = GetLeDevice(device->GetUuid());
162 // This gets rid of the shared_ptr in the map
163 ASSERT_LOG(RemoveDevice(device), "Failed to remove the device!");
164 le_device->SetAddress(new_address);
165 // Move the value located at the pointer
166 return AddDeviceToMap(std::move(*(le_device.get())));
167 } else if (type == DUAL) {
168 auto dual_device = GetDualDevice(device->GetUuid());
169 // This gets rid of the shared_ptr in the map
170 ASSERT_LOG(RemoveDevice(device), "Failed to remove the device!");
171 dual_device->SetAddress(new_address);
172 // Move the value located at the pointer
173 return AddDeviceToMap(std::move(*(dual_device.get())));
174 }
175 LOG_ALWAYS_FATAL("Someone added a device type but didn't account for it here.");
176 return false;
177 }
178
AddDeviceToMap(ClassicDevice && device)179 bool DeviceDatabase::AddDeviceToMap(ClassicDevice&& device) {
180 const std::string uuid = device.GetUuid();
181 bool success = false;
182 {
183 std::lock_guard<std::mutex> lock(device_map_mutex_);
184 auto it = classic_device_map_.find(device.GetUuid());
185 // If we have a record with the same key
186 if (it != classic_device_map_.end()) {
187 // We don't want to insert and overwrite
188 return false;
189 }
190 std::shared_ptr<ClassicDevice> device_ptr = std::make_shared<ClassicDevice>(std::move(device));
191 // returning the boolean value of insert success
192 if (classic_device_map_
193 .insert(std::pair<std::string, std::shared_ptr<ClassicDevice>>(device_ptr->GetUuid(), device_ptr))
194 .second) {
195 success = true;
196 }
197 }
198 if (success) {
199 ASSERT_LOG(WriteToDisk(), "Failed to write data to disk!");
200 } else {
201 LOG_WARN("Failed to add device '%s' to map.", uuid.c_str());
202 }
203 return success;
204 }
205
AddDeviceToMap(LeDevice && device)206 bool DeviceDatabase::AddDeviceToMap(LeDevice&& device) {
207 const std::string uuid = device.GetUuid();
208 bool success = false;
209 {
210 std::lock_guard<std::mutex> lock(device_map_mutex_);
211 auto it = le_device_map_.find(device.GetUuid());
212 // If we have a record with the same key
213 if (it != le_device_map_.end()) {
214 // We don't want to insert and overwrite
215 return false;
216 }
217 std::shared_ptr<LeDevice> device_ptr = std::make_shared<LeDevice>(std::move(device));
218 // returning the boolean value of insert success
219 if (le_device_map_.insert(std::pair<std::string, std::shared_ptr<LeDevice>>(device_ptr->GetUuid(), device_ptr))
220 .second) {
221 success = true;
222 }
223 }
224 if (success) {
225 ASSERT_LOG(WriteToDisk(), "Failed to write data to disk!");
226 } else {
227 LOG_WARN("Failed to add device '%s' to map.", uuid.c_str());
228 }
229 return success;
230 }
231
AddDeviceToMap(DualDevice && device)232 bool DeviceDatabase::AddDeviceToMap(DualDevice&& device) {
233 const std::string uuid = device.GetUuid();
234 bool success = false;
235 {
236 std::lock_guard<std::mutex> lock(device_map_mutex_);
237 auto it = dual_device_map_.find(device.GetUuid());
238 // If we have a record with the same key
239 if (it != dual_device_map_.end()) {
240 // We don't want to insert and overwrite
241 return false;
242 }
243 std::shared_ptr<DualDevice> device_ptr = std::make_shared<DualDevice>(std::move(device));
244 // returning the boolean value of insert success
245 if (dual_device_map_.insert(std::pair<std::string, std::shared_ptr<DualDevice>>(device_ptr->GetUuid(), device_ptr))
246 .second) {
247 success = true;
248 }
249 }
250 if (success) {
251 ASSERT_LOG(WriteToDisk(), "Failed to write data to disk!");
252 } else {
253 LOG_WARN("Failed to add device '%s' to map.", uuid.c_str());
254 }
255 return success;
256 }
257
WriteToDisk()258 bool DeviceDatabase::WriteToDisk() {
259 // TODO(optedoblivion): Implement
260 // TODO(optedoblivion): FIX ME!
261 // If synchronous stack dies before async write, we can miss adding device
262 // post(WriteToDisk());
263 // Current Solution: Synchronous disk I/O...
264 std::lock_guard<std::mutex> lock(device_map_mutex_);
265 // Collect information to sync to database
266 // Create SQL query for insert/update
267 // submit SQL
268 return true;
269 }
270
ReadFromDisk()271 bool DeviceDatabase::ReadFromDisk() {
272 // TODO(optedoblivion): Implement
273 // Current Solution: Synchronous disk I/O...
274 std::lock_guard<std::mutex> lock(device_map_mutex_);
275 return true;
276 }
277