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