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 <string>
19 #include <unordered_set>
20 
21 #include "hci/hci_packets.h"
22 #include "storage/config_cache.h"
23 #include "storage/config_keys.h"
24 #include "storage/device.h"
25 
26 namespace bluetooth {
27 namespace storage {
28 
29 class LeDevice {
30 public:
31   LeDevice(ConfigCache* config, ConfigCache* memory_only_config, std::string section);
32 
33   // for move
34   LeDevice(LeDevice&& other) noexcept = default;
35   LeDevice& operator=(LeDevice&& other) noexcept = default;
36 
37   // for copy
38   LeDevice(const LeDevice& other) noexcept = default;
39   LeDevice& operator=(const LeDevice& other) noexcept = default;
40 
41   // operators
42   bool operator==(const LeDevice& other) const {
43     return config_ == other.config_ && memory_only_config_ == other.memory_only_config_ &&
44            section_ == other.section_;
45   }
46   bool operator!=(const LeDevice& other) const { return !(*this == other); }
47   bool operator<(const LeDevice& other) const {
48     if (config_ != other.config_) {
49       return config_ < other.config_;
50     }
51     if (memory_only_config_ != other.memory_only_config_) {
52       return memory_only_config_ < other.memory_only_config_;
53     }
54     return section_ < other.section_;
55   }
56   bool operator>(const LeDevice& rhs) const { return rhs < *this; }
57   bool operator<=(const LeDevice& rhs) const { return !(*this > rhs); }
58   bool operator>=(const LeDevice& rhs) const { return !(*this < rhs); }
59 
60   // Get the parent device
61   Device Parent();
62 
63   // For logging purpose only, you can't get a LeDevice object from parsing a std::string
64   std::string ToLogString() const;
65 
66   // Return true if device has a link key in one of |kLinkKeyProperties|
67   bool IsPaired() const;
68 
69   // Property names that correspond to a link key used in Bluetooth LE device
70   static const std::unordered_set<std::string_view> kLinkKeyProperties;
71 
72 private:
73   ConfigCache* config_;
74   ConfigCache* memory_only_config_;
75   std::string section_;
76   friend std::hash<LeDevice>;
77 
78 public:
79   // Get LE address type of the key address
80   GENERATE_PROPERTY_GETTER_SETTER_REMOVER(AddressType, hci::AddressType,
81                                           BTIF_STORAGE_KEY_ADDR_TYPE);
82   // IRK + Identity Address Type + Identity Address
83   GENERATE_PROPERTY_GETTER_SETTER_REMOVER(PeerId, std::string, BTIF_STORAGE_KEY_LE_KEY_PID);
84   // LTK + RAND + EDIV + Security Level + Key Length
85   GENERATE_PROPERTY_GETTER_SETTER_REMOVER(PeerEncryptionKeys, std::string,
86                                           BTIF_STORAGE_KEY_LE_KEY_PENC);
87   // counter + CSRK (connection signature resolving key) + security level
88   GENERATE_PROPERTY_GETTER_SETTER_REMOVER(PeerSignatureResolvingKeys, std::string,
89                                           BTIF_STORAGE_KEY_LE_KEY_PCSRK);
90 
91   GENERATE_PROPERTY_GETTER_SETTER_REMOVER(LegacyPseudoAddress, hci::Address, "LeLegacyPseudoAddr");
92 };
93 
94 }  // namespace storage
95 }  // namespace bluetooth
96 
97 namespace std {
98 template <>
99 struct hash<bluetooth::storage::LeDevice> {
100   std::size_t operator()(const bluetooth::storage::LeDevice& val) const noexcept {
101     std::size_t pointer_hash_1 = std::hash<bluetooth::storage::ConfigCache*>{}(val.config_);
102     std::size_t pointer_hash_2 = std::hash<bluetooth::storage::ConfigCache*>{}(val.config_);
103     std::size_t addr_hash = std::hash<std::string>{}(val.section_);
104     return addr_hash ^ (pointer_hash_1 << 1) ^ (pointer_hash_2 << 2);
105   }
106 };
107 }  // namespace std
108