277 lines
9.5 KiB
C++
277 lines
9.5 KiB
C++
/******************************************************************************
|
|
*
|
|
* Copyright 2019 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at:
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
******************************************************************************/
|
|
#include "hci/device_database.h"
|
|
|
|
#include <memory>
|
|
#include <utility>
|
|
|
|
#include "hci/classic_device.h"
|
|
#include "hci/dual_device.h"
|
|
#include "hci/le_device.h"
|
|
#include "os/log.h"
|
|
|
|
using namespace bluetooth::hci;
|
|
|
|
std::shared_ptr<ClassicDevice> DeviceDatabase::CreateClassicDevice(Address address) {
|
|
ClassicDevice device(address);
|
|
const std::string uuid = device.GetUuid();
|
|
AddDeviceToMap(std::move(device));
|
|
return GetClassicDevice(uuid);
|
|
}
|
|
|
|
std::shared_ptr<LeDevice> DeviceDatabase::CreateLeDevice(Address address) {
|
|
LeDevice device(address);
|
|
const std::string uuid = device.GetUuid();
|
|
AddDeviceToMap(std::move(device));
|
|
return GetLeDevice(uuid);
|
|
}
|
|
|
|
std::shared_ptr<DualDevice> DeviceDatabase::CreateDualDevice(Address address) {
|
|
auto classic = CreateClassicDevice(address);
|
|
auto le = CreateLeDevice(address);
|
|
if (classic && le) {
|
|
DualDevice device(address, classic, le);
|
|
std::string uuid = device.GetUuid();
|
|
AddDeviceToMap(std::move(device));
|
|
return GetDualDevice(uuid);
|
|
}
|
|
LOG_WARN("Attempting to instert a DUAL device that already exists!");
|
|
return std::shared_ptr<DualDevice>();
|
|
}
|
|
|
|
bool DeviceDatabase::RemoveDevice(const std::shared_ptr<Device>& device) {
|
|
const DeviceType type = device->GetDeviceType();
|
|
bool success;
|
|
switch (type) {
|
|
case CLASSIC:
|
|
success = false;
|
|
{
|
|
std::lock_guard<std::mutex> lock(device_map_mutex_);
|
|
auto classic_it = classic_device_map_.find(device->GetUuid());
|
|
// If we have a record with the same key
|
|
if (classic_it != classic_device_map_.end()) {
|
|
classic_device_map_.erase(device->GetUuid());
|
|
success = true;
|
|
}
|
|
}
|
|
if (success) {
|
|
ASSERT_LOG(WriteToDisk(), "Failed to write data to disk!");
|
|
} else {
|
|
LOG_WARN("Device not in database!");
|
|
}
|
|
return success;
|
|
case LE:
|
|
success = false;
|
|
{
|
|
std::lock_guard<std::mutex> lock(device_map_mutex_);
|
|
auto le_it = le_device_map_.find(device->GetUuid());
|
|
// If we have a record with the same key
|
|
if (le_it != le_device_map_.end()) {
|
|
le_device_map_.erase(device->GetUuid());
|
|
success = true;
|
|
}
|
|
}
|
|
if (success) {
|
|
ASSERT_LOG(WriteToDisk(), "Failed to write data to disk!");
|
|
} else {
|
|
LOG_WARN("Device not in database!");
|
|
}
|
|
return success;
|
|
case DUAL:
|
|
std::shared_ptr<DualDevice> dual_device = nullptr;
|
|
{
|
|
std::lock_guard<std::mutex> lock(device_map_mutex_);
|
|
auto dual_it = dual_device_map_.find(device->GetUuid());
|
|
if (dual_it != dual_device_map_.end()) {
|
|
dual_device = GetDualDevice(device->GetUuid());
|
|
}
|
|
}
|
|
success = false;
|
|
if (dual_device != nullptr) {
|
|
if (RemoveDevice(dual_device->GetClassicDevice()) && RemoveDevice(dual_device->GetLeDevice())) {
|
|
dual_device_map_.erase(device->GetUuid());
|
|
success = true;
|
|
}
|
|
}
|
|
if (success) {
|
|
ASSERT_LOG(WriteToDisk(), "Failed to write data to disk!");
|
|
} else {
|
|
LOG_WARN("Device not in database!");
|
|
}
|
|
return success;
|
|
}
|
|
}
|
|
|
|
std::shared_ptr<ClassicDevice> DeviceDatabase::GetClassicDevice(const std::string& uuid) {
|
|
std::lock_guard<std::mutex> lock(device_map_mutex_);
|
|
auto it = classic_device_map_.find(uuid);
|
|
if (it != classic_device_map_.end()) {
|
|
return it->second;
|
|
}
|
|
LOG_WARN("Device '%s' not found!", uuid.c_str());
|
|
return std::shared_ptr<ClassicDevice>();
|
|
}
|
|
|
|
std::shared_ptr<LeDevice> DeviceDatabase::GetLeDevice(const std::string& uuid) {
|
|
std::lock_guard<std::mutex> lock(device_map_mutex_);
|
|
auto it = le_device_map_.find(uuid);
|
|
if (it != le_device_map_.end()) {
|
|
return it->second;
|
|
}
|
|
LOG_WARN("Device '%s' not found!", uuid.c_str());
|
|
return std::shared_ptr<LeDevice>();
|
|
}
|
|
|
|
std::shared_ptr<DualDevice> DeviceDatabase::GetDualDevice(const std::string& uuid) {
|
|
std::lock_guard<std::mutex> lock(device_map_mutex_);
|
|
auto it = dual_device_map_.find(uuid);
|
|
if (it != dual_device_map_.end()) {
|
|
return it->second;
|
|
}
|
|
LOG_WARN("Device '%s' not found!", uuid.c_str());
|
|
return std::shared_ptr<DualDevice>();
|
|
}
|
|
|
|
bool DeviceDatabase::UpdateDeviceAddress(const std::shared_ptr<Device>& device, Address new_address) {
|
|
// Hold onto device
|
|
const DeviceType type = device->GetDeviceType();
|
|
if (type == CLASSIC) {
|
|
auto classic_device = GetClassicDevice(device->GetUuid());
|
|
// This gets rid of the shared_ptr in the map
|
|
ASSERT_LOG(RemoveDevice(device), "Failed to remove the device!");
|
|
classic_device->SetAddress(new_address);
|
|
// Move the value located at the pointer
|
|
return AddDeviceToMap(std::move(*(classic_device.get())));
|
|
} else if (type == LE) {
|
|
auto le_device = GetLeDevice(device->GetUuid());
|
|
// This gets rid of the shared_ptr in the map
|
|
ASSERT_LOG(RemoveDevice(device), "Failed to remove the device!");
|
|
le_device->SetAddress(new_address);
|
|
// Move the value located at the pointer
|
|
return AddDeviceToMap(std::move(*(le_device.get())));
|
|
} else if (type == DUAL) {
|
|
auto dual_device = GetDualDevice(device->GetUuid());
|
|
// This gets rid of the shared_ptr in the map
|
|
ASSERT_LOG(RemoveDevice(device), "Failed to remove the device!");
|
|
dual_device->SetAddress(new_address);
|
|
// Move the value located at the pointer
|
|
return AddDeviceToMap(std::move(*(dual_device.get())));
|
|
}
|
|
LOG_ALWAYS_FATAL("Someone added a device type but didn't account for it here.");
|
|
return false;
|
|
}
|
|
|
|
bool DeviceDatabase::AddDeviceToMap(ClassicDevice&& device) {
|
|
const std::string uuid = device.GetUuid();
|
|
bool success = false;
|
|
{
|
|
std::lock_guard<std::mutex> lock(device_map_mutex_);
|
|
auto it = classic_device_map_.find(device.GetUuid());
|
|
// If we have a record with the same key
|
|
if (it != classic_device_map_.end()) {
|
|
// We don't want to insert and overwrite
|
|
return false;
|
|
}
|
|
std::shared_ptr<ClassicDevice> device_ptr = std::make_shared<ClassicDevice>(std::move(device));
|
|
// returning the boolean value of insert success
|
|
if (classic_device_map_
|
|
.insert(std::pair<std::string, std::shared_ptr<ClassicDevice>>(device_ptr->GetUuid(), device_ptr))
|
|
.second) {
|
|
success = true;
|
|
}
|
|
}
|
|
if (success) {
|
|
ASSERT_LOG(WriteToDisk(), "Failed to write data to disk!");
|
|
} else {
|
|
LOG_WARN("Failed to add device '%s' to map.", uuid.c_str());
|
|
}
|
|
return success;
|
|
}
|
|
|
|
bool DeviceDatabase::AddDeviceToMap(LeDevice&& device) {
|
|
const std::string uuid = device.GetUuid();
|
|
bool success = false;
|
|
{
|
|
std::lock_guard<std::mutex> lock(device_map_mutex_);
|
|
auto it = le_device_map_.find(device.GetUuid());
|
|
// If we have a record with the same key
|
|
if (it != le_device_map_.end()) {
|
|
// We don't want to insert and overwrite
|
|
return false;
|
|
}
|
|
std::shared_ptr<LeDevice> device_ptr = std::make_shared<LeDevice>(std::move(device));
|
|
// returning the boolean value of insert success
|
|
if (le_device_map_.insert(std::pair<std::string, std::shared_ptr<LeDevice>>(device_ptr->GetUuid(), device_ptr))
|
|
.second) {
|
|
success = true;
|
|
}
|
|
}
|
|
if (success) {
|
|
ASSERT_LOG(WriteToDisk(), "Failed to write data to disk!");
|
|
} else {
|
|
LOG_WARN("Failed to add device '%s' to map.", uuid.c_str());
|
|
}
|
|
return success;
|
|
}
|
|
|
|
bool DeviceDatabase::AddDeviceToMap(DualDevice&& device) {
|
|
const std::string uuid = device.GetUuid();
|
|
bool success = false;
|
|
{
|
|
std::lock_guard<std::mutex> lock(device_map_mutex_);
|
|
auto it = dual_device_map_.find(device.GetUuid());
|
|
// If we have a record with the same key
|
|
if (it != dual_device_map_.end()) {
|
|
// We don't want to insert and overwrite
|
|
return false;
|
|
}
|
|
std::shared_ptr<DualDevice> device_ptr = std::make_shared<DualDevice>(std::move(device));
|
|
// returning the boolean value of insert success
|
|
if (dual_device_map_.insert(std::pair<std::string, std::shared_ptr<DualDevice>>(device_ptr->GetUuid(), device_ptr))
|
|
.second) {
|
|
success = true;
|
|
}
|
|
}
|
|
if (success) {
|
|
ASSERT_LOG(WriteToDisk(), "Failed to write data to disk!");
|
|
} else {
|
|
LOG_WARN("Failed to add device '%s' to map.", uuid.c_str());
|
|
}
|
|
return success;
|
|
}
|
|
|
|
bool DeviceDatabase::WriteToDisk() {
|
|
// TODO(optedoblivion): Implement
|
|
// TODO(optedoblivion): FIX ME!
|
|
// If synchronous stack dies before async write, we can miss adding device
|
|
// post(WriteToDisk());
|
|
// Current Solution: Synchronous disk I/O...
|
|
std::lock_guard<std::mutex> lock(device_map_mutex_);
|
|
// Collect information to sync to database
|
|
// Create SQL query for insert/update
|
|
// submit SQL
|
|
return true;
|
|
}
|
|
|
|
bool DeviceDatabase::ReadFromDisk() {
|
|
// TODO(optedoblivion): Implement
|
|
// Current Solution: Synchronous disk I/O...
|
|
std::lock_guard<std::mutex> lock(device_map_mutex_);
|
|
return true;
|
|
}
|