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