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