• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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