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 #pragma once 17 18 #include <functional> 19 #include <limits> 20 #include <optional> 21 #include <string> 22 #include <type_traits> 23 #include <unordered_set> 24 #include <utility> 25 26 #include "hci/address.h" 27 #include "hci/address_with_type.h" 28 #include "hci/class_of_device.h" 29 #include "hci/enum_helper.h" 30 #include "storage/config_cache.h" 31 #include "storage/config_cache_helper.h" 32 #include "storage/mutation_entry.h" 33 #include "storage/serializable.h" 34 35 namespace bluetooth { 36 namespace storage { 37 38 class LeDevice; 39 class ClassicDevice; 40 41 // Make sure our macro is used 42 #ifdef GENERATE_PROPERTY_GETTER_SETTER_REMOVER 43 static_assert(false, "GENERATE_PROPERTY_GETTER_SETTER_REMOVER() must be uniquely defined once in this file"); 44 #endif 45 46 #define GENERATE_PROPERTY_GETTER_SETTER_REMOVER(NAME, RETURN_TYPE, PROPERTY_KEY) \ 47 public: \ 48 std::optional<RETURN_TYPE> Get##NAME() const { \ 49 return ConfigCacheHelper(*config_).Get<RETURN_TYPE>(section_, PROPERTY_KEY); \ 50 } \ 51 MutationEntry Set##NAME(const RETURN_TYPE& value) { \ 52 return MutationEntry::Set<RETURN_TYPE>(MutationEntry::PropertyType::NORMAL, section_, PROPERTY_KEY, value); \ 53 } \ 54 MutationEntry Remove##NAME() { \ 55 return MutationEntry::Remove(MutationEntry::PropertyType::NORMAL, section_, PROPERTY_KEY); \ 56 } 57 58 // Make sure our macro is used 59 #ifdef GENERATE_PROPERTY_GETTER_SETTER_REMOVER_WITH_CUSTOM_SETTER 60 static_assert( 61 false, "GENERATE_PROPERTY_GETTER_SETTER_REMOVER_WITH_CUSTOM_SETTER() must be uniquely defined once in this file"); 62 #endif 63 64 // FUNC is bracketed function definition that takes a const RETURN_TYPE& value and return RETURN_TYPE 65 // e.g. { return value + 1; } 66 #define GENERATE_PROPERTY_GETTER_SETTER_REMOVER_WITH_CUSTOM_SETTER(NAME, RETURN_TYPE, PROPERTY_KEY, FUNC) \ 67 public: \ 68 std::optional<RETURN_TYPE> Get##NAME() const { \ 69 return ConfigCacheHelper(*config_).Get<RETURN_TYPE>(section_, PROPERTY_KEY); \ 70 } \ 71 MutationEntry Set##NAME(const RETURN_TYPE& value) { \ 72 auto new_value = [this](const RETURN_TYPE& value) -> RETURN_TYPE FUNC(value); \ 73 return MutationEntry::Set<RETURN_TYPE>(MutationEntry::PropertyType::NORMAL, section_, PROPERTY_KEY, new_value); \ 74 } \ 75 MutationEntry Remove##NAME() { \ 76 return MutationEntry::Remove(MutationEntry::PropertyType::NORMAL, section_, PROPERTY_KEY); \ 77 } 78 79 // Make sure our macro is used 80 #ifdef GENERATE_TEMP_PROPERTY_GETTER_SETTER_REMOVER 81 static_assert(false, "GENERATE_TEMP_PROPERTY_GETTER_SETTER_REMOVER() must be uniquely defined once in this file"); 82 #endif 83 84 // Macro to generate tempoarary property that exists in memory only 85 // It is subjected to a limit of 10,000 devices 86 // It will be cleared when the stack is restarted 87 #define GENERATE_TEMP_PROPERTY_GETTER_SETTER_REMOVER(NAME, RETURN_TYPE, PROPERTY_KEY) \ 88 public: \ 89 std::optional<RETURN_TYPE> GetTemp##NAME() const { \ 90 return ConfigCacheHelper(*memory_only_config_).Get<RETURN_TYPE>(section_, PROPERTY_KEY); \ 91 } \ 92 MutationEntry SetTemp##NAME(const RETURN_TYPE& value) { \ 93 return MutationEntry::Set<RETURN_TYPE>(MutationEntry::PropertyType::MEMORY_ONLY, section_, PROPERTY_KEY, value); \ 94 } \ 95 MutationEntry RemoveTemp##NAME() { \ 96 return MutationEntry::Remove(MutationEntry::PropertyType::MEMORY_ONLY, section_, PROPERTY_KEY); \ 97 } 98 99 // A think wrapper of device in ConfigCache, allowing easy access to various predefined properties of a Bluetooth device 100 // 101 // Device, LeDevice, and Classic device objects are fully copyable, comparable hashable 102 // 103 // A newly created device does not have any DeviceType information and user can only read or write the values in this 104 // common Device abstraction layer. 105 // 106 // As soon as a user determines the type of device, they should call SetDeviceType() to assign device to a type 107 // After that, Classic() or Le() will return interfaces that allows access to deeper layer properties 108 class Device { 109 public: 110 enum ConfigKeyAddressType { LEGACY_KEY_ADDRESS, CLASSIC_ADDRESS, LE_IDENTITY_ADDRESS, LE_LEGACY_PSEUDO_ADDRESS }; 111 112 Device( 113 ConfigCache* config, 114 ConfigCache* memory_only_config, 115 const hci::Address& key_address, 116 ConfigKeyAddressType key_address_type); 117 Device(ConfigCache* config, ConfigCache* memory_only_config, std::string section); 118 119 // for move 120 Device(Device&& other) noexcept = default; 121 Device& operator=(Device&& other) noexcept = default; 122 123 // for copy 124 Device(const Device& other) noexcept = default; 125 Device& operator=(const Device& other) noexcept = default; 126 127 // operators 128 bool operator==(const Device& other) const { 129 return config_ == other.config_ && memory_only_config_ == other.memory_only_config_ && section_ == other.section_; 130 } 131 bool operator!=(const Device& other) const { 132 return !(*this == other); 133 } 134 bool operator<(const Device& other) const { 135 return config_ < other.config_ && memory_only_config_ < other.memory_only_config_ && section_ < other.section_; 136 } 137 bool operator>(const Device& rhs) const { 138 return (rhs < *this); 139 } 140 bool operator<=(const Device& rhs) const { 141 return !(*this > rhs); 142 } 143 bool operator>=(const Device& rhs) const { 144 return !(*this < rhs); 145 } 146 147 // A newly created Device object may not be backed by any properties in the ConfigCache, where Exists() will return 148 // false. As soon as a property value is added to the device. Exists() will become true. 149 bool Exists(); 150 151 // Remove device and all its properties from config and memory-only temp config 152 MutationEntry RemoveFromConfig(); 153 // Remove device and all its properties from memory-only temp config, but keep items in normal config 154 MutationEntry RemoveFromTempConfig(); 155 156 // Only works when GetDeviceType() returns BR_EDR or DUAL, will crash otherwise 157 // For first time use, please SetDeviceType() to the right value 158 ClassicDevice Classic(); 159 160 // Only works when GetDeviceType() returns LE or DUAL, will crash otherwise 161 // For first time use, please SetDeviceType() to the right value 162 LeDevice Le(); 163 164 // For logging purpose only, you can't get a Device object from parsing a std::string 165 std::string ToLogString() const; 166 167 // Property names that correspond to a link key used in Bluetooth Classic and LE device 168 static const std::unordered_set<std::string_view> kLinkKeyProperties; 169 170 private: 171 ConfigCache* config_; 172 ConfigCache* memory_only_config_; 173 std::string section_; 174 friend std::hash<Device>; 175 176 public: 177 // Macro generate getters, setters and removers 178 GENERATE_PROPERTY_GETTER_SETTER_REMOVER(Name, std::string, "Name"); 179 GENERATE_PROPERTY_GETTER_SETTER_REMOVER(ClassOfDevice, hci::ClassOfDevice, "DevClass"); 180 GENERATE_PROPERTY_GETTER_SETTER_REMOVER_WITH_CUSTOM_SETTER(DeviceType, hci::DeviceType, "DevType", { 181 return static_cast<hci::DeviceType>(value | GetDeviceType().value_or(hci::DeviceType::UNKNOWN)); 182 }); 183 GENERATE_PROPERTY_GETTER_SETTER_REMOVER(ManufacturerCode, uint16_t, "Manufacturer"); 184 GENERATE_PROPERTY_GETTER_SETTER_REMOVER(LmpVersion, uint8_t, "LmpVer"); 185 GENERATE_PROPERTY_GETTER_SETTER_REMOVER(LmpSubVersion, uint16_t, "LmpSubVer"); 186 GENERATE_PROPERTY_GETTER_SETTER_REMOVER(MetricsId, int, "MetricsId"); 187 GENERATE_PROPERTY_GETTER_SETTER_REMOVER(PinLength, int, "PinLength"); 188 // unix timestamp in seconds from epoch 189 GENERATE_PROPERTY_GETTER_SETTER_REMOVER(CreationUnixTimestamp, int, "DevClass"); 190 }; 191 192 } // namespace storage 193 } // namespace bluetooth 194 195 namespace std { 196 template <> 197 struct hash<bluetooth::storage::Device> { 198 std::size_t operator()(const bluetooth::storage::Device& val) const noexcept { 199 std::size_t pointer_hash_1 = std::hash<bluetooth::storage::ConfigCache*>{}(val.config_); 200 std::size_t pointer_hash_2 = std::hash<bluetooth::storage::ConfigCache*>{}(val.config_); 201 std::size_t addr_hash = std::hash<std::string>{}(val.section_); 202 return addr_hash ^ (pointer_hash_1 << 1) ^ (pointer_hash_2 << 2); 203 } 204 }; 205 } // namespace std