• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2023 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 #include "hci/le_scanning_reassembler.h"
17 
18 #include <memory>
19 #include <unordered_map>
20 
21 #include "hci/acl_manager.h"
22 #include "hci/controller.h"
23 #include "hci/hci_layer.h"
24 #include "hci/hci_packets.h"
25 #include "hci/le_periodic_sync_manager.h"
26 #include "hci/le_scanning_interface.h"
27 #include "hci/vendor_specific_event_manager.h"
28 #include "module.h"
29 #include "os/handler.h"
30 #include "os/log.h"
31 #include "storage/storage_module.h"
32 
33 namespace bluetooth::hci {
34 
ProcessAdvertisingReport(uint16_t event_type,uint8_t address_type,Address address,uint8_t advertising_sid,const std::vector<uint8_t> & advertising_data)35 std::optional<std::vector<uint8_t>> LeScanningReassembler::ProcessAdvertisingReport(
36     uint16_t event_type,
37     uint8_t address_type,
38     Address address,
39     uint8_t advertising_sid,
40     const std::vector<uint8_t>& advertising_data) {
41   bool is_scannable = event_type & (1 << kScannableBit);
42   bool is_scan_response = event_type & (1 << kScanResponseBit);
43   bool is_legacy = event_type & (1 << kLegacyBit);
44   DataStatus data_status = DataStatus((event_type >> kDataStatusBits) & 0x3);
45 
46   if (address_type != (uint8_t)DirectAdvertisingAddressType::NO_ADDRESS_PROVIDED &&
47       address == Address::kEmpty) {
48     LOG_WARN("Ignoring non-anonymous advertising report with empty address");
49     return {};
50   }
51 
52   AdvertisingKey key(address, DirectAdvertisingAddressType(address_type), advertising_sid);
53 
54   // Ignore scan responses received without a matching advertising event.
55   if (is_scan_response && (ignore_scan_responses_ || !ContainsFragment(key))) {
56     LOG_INFO("Ignoring scan response received without advertising event");
57     return {};
58   }
59 
60   // Legacy advertising is always complete, we can drop
61   // the previous data as safety measure if the report is not a scan
62   // response.
63   if (is_legacy && !is_scan_response) {
64     LOG_DEBUG("Dropping repeated legacy advertising data");
65     RemoveFragment(key);
66   }
67 
68   // Concatenate the data with existing fragments.
69   std::list<AdvertisingFragment>::iterator advertising_fragment =
70       AppendFragment(key, advertising_data);
71 
72   // Trim the advertising data when the complete payload is received.
73   if (data_status != DataStatus::CONTINUING) {
74     advertising_fragment->data = TrimAdvertisingData(advertising_fragment->data);
75   }
76 
77   // TODO(b/272120114) waiting for a scan response here is prone to failure as the
78   // SCAN_REQ PDUs can be rejected by the advertiser according to the
79   // advertising filter parameter.
80   bool expect_scan_response = is_scannable && !is_scan_response && !ignore_scan_responses_;
81 
82   // Check if we should wait for additional fragments:
83   // - For legacy advertising, when a scan response is expected.
84   // - For extended advertising, when the current data is marked
85   //   incomplete OR when a scan response is expected.
86   if (data_status == DataStatus::CONTINUING || expect_scan_response) {
87     return {};
88   }
89 
90   // Otherwise the full advertising report has been reassembled,
91   // removed the cache entry and return the complete advertising data.
92   std::vector<uint8_t> complete_advertising_data = std::move(advertising_fragment->data);
93   cache_.erase(advertising_fragment);
94   return complete_advertising_data;
95 }
96 
97 /// Trim the advertising data by removing empty or overflowing
98 /// GAP Data entries.
TrimAdvertisingData(const std::vector<uint8_t> & advertising_data)99 std::vector<uint8_t> LeScanningReassembler::TrimAdvertisingData(
100     const std::vector<uint8_t>& advertising_data) {
101   // Remove empty and overflowing entries from the advertising data.
102   std::vector<uint8_t> significant_advertising_data;
103   for (size_t offset = 0; offset < advertising_data.size();) {
104     size_t remaining_size = advertising_data.size() - offset;
105     uint8_t entry_size = advertising_data[offset];
106 
107     if (entry_size != 0 && entry_size < remaining_size) {
108       significant_advertising_data.push_back(entry_size);
109       significant_advertising_data.insert(
110           significant_advertising_data.end(),
111           advertising_data.begin() + offset + 1,
112           advertising_data.begin() + offset + 1 + entry_size);
113     }
114 
115     offset += entry_size + 1;
116   }
117 
118   return significant_advertising_data;
119 }
120 
AdvertisingKey(Address address,DirectAdvertisingAddressType address_type,uint8_t sid)121 LeScanningReassembler::AdvertisingKey::AdvertisingKey(
122     Address address, DirectAdvertisingAddressType address_type, uint8_t sid)
123     : address(), sid() {
124   // The address type is NO_ADDRESS_PROVIDED for anonymous advertising.
125   if (address_type != DirectAdvertisingAddressType::NO_ADDRESS_PROVIDED) {
126     this->address = AddressWithType(address, AddressType(address_type));
127   }
128   // 0xff is reserved to indicate that the ADI field was not present
129   // in the ADV_EXT_IND PDU.
130   if (sid != 0xff) {
131     this->sid = sid;
132   }
133 }
134 
operator ==(const AdvertisingKey & other)135 bool LeScanningReassembler::AdvertisingKey::operator==(const AdvertisingKey& other) {
136   return address == other.address && sid == other.sid;
137 }
138 
139 /// Append to the current advertising data of the selected advertiser.
140 /// If the advertiser is unknown a new entry is added, optionally by
141 /// dropping the oldest advertiser.
142 std::list<LeScanningReassembler::AdvertisingFragment>::iterator
AppendFragment(const AdvertisingKey & key,const std::vector<uint8_t> & data)143 LeScanningReassembler::AppendFragment(const AdvertisingKey& key, const std::vector<uint8_t>& data) {
144   auto it = FindFragment(key);
145   if (it != cache_.end()) {
146     it->data.insert(it->data.end(), data.cbegin(), data.cend());
147     return it;
148   }
149 
150   if (cache_.size() > kMaximumCacheSize) {
151     cache_.pop_back();
152   }
153 
154   cache_.emplace_front(key, data);
155   return cache_.begin();
156 }
157 
RemoveFragment(const AdvertisingKey & key)158 void LeScanningReassembler::RemoveFragment(const AdvertisingKey& key) {
159   auto it = FindFragment(key);
160   if (it != cache_.end()) {
161     cache_.erase(it);
162   }
163 }
164 
ContainsFragment(const AdvertisingKey & key)165 bool LeScanningReassembler::ContainsFragment(const AdvertisingKey& key) {
166   return FindFragment(key) != cache_.end();
167 }
168 
FindFragment(const AdvertisingKey & key)169 std::list<LeScanningReassembler::AdvertisingFragment>::iterator LeScanningReassembler::FindFragment(
170     const AdvertisingKey& key) {
171   for (auto it = cache_.begin(); it != cache_.end(); it++) {
172     if (it->key == key) {
173       return it;
174     }
175   }
176   return cache_.end();
177 }
178 
179 }  // namespace bluetooth::hci
180