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