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