1 /*
2 * Copyright (C) 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
17 #include "location/lbs/contexthub/nanoapps/nearby/filter.h"
18
19 #include <chre/util/macros.h>
20 #include <inttypes.h>
21 #include <pb_decode.h>
22
23 #include <cstdint>
24 #include <iterator>
25
26 #include "chre_api/chre.h"
27 #include "location/lbs/contexthub/nanoapps/nearby/ble_scan_record.h"
28 #include "location/lbs/contexthub/nanoapps/nearby/fast_pair_filter.h"
29 #ifdef ENABLE_PRESENCE
30 #include "location/lbs/contexthub/nanoapps/nearby/presence_crypto_mic.h"
31 #include "location/lbs/contexthub/nanoapps/nearby/presence_filter.h"
32 #endif
33 #include "third_party/contexthub/chre/util/include/chre/util/nanoapp/log.h"
34
35 #define LOG_TAG "[NEARBY][FILTER]"
36
37 namespace nearby {
38
39 constexpr nearby_BleFilters kDefaultBleFilters = nearby_BleFilters_init_zero;
40
Update(const uint8_t * message,uint32_t message_size)41 bool Filter::Update(const uint8_t *message, uint32_t message_size) {
42 LOGD("Decode a Filters message with size %" PRIu32, message_size);
43 ble_filters_ = kDefaultBleFilters;
44 pb_istream_t stream = pb_istream_from_buffer(message, message_size);
45 if (!pb_decode(&stream, nearby_BleFilters_fields, &ble_filters_)) {
46 LOGE("Failed to decode a Filters message.");
47 return false;
48 }
49 // Print filters for debug.
50 LOGD_SENSITIVE_INFO("BLE filters counter %d", ble_filters_.filter_count);
51 if (ble_filters_.filter_count > 0) {
52 LOGD_SENSITIVE_INFO("BLE filter 0 data element count %d",
53 ble_filters_.filter[0].data_element_count);
54 if (ble_filters_.filter[0].data_element_count > 0) {
55 LOGD_SENSITIVE_INFO(
56 "Data Element 0, key: %" PRIi32
57 " value[0]: %d,"
58 " has key: %d, has value: %d, has value length %d,"
59 " value length %" PRIu32,
60 ble_filters_.filter[0].data_element[0].key,
61 ble_filters_.filter[0].data_element[0].value[0],
62 ble_filters_.filter[0].data_element[0].has_key,
63 ble_filters_.filter[0].data_element[0].has_value,
64 ble_filters_.filter[0].data_element[0].has_value_length,
65 ble_filters_.filter[0].data_element[0].value_length);
66 }
67 }
68 for (int i = 0; i < ble_filters_.filter_count; i++) {
69 const nearby_BleFilter *filter = &ble_filters_.filter[i];
70 // Sets the scan interval to satisfy the minimal latency requirement.
71 if (filter->has_latency_ms && filter->latency_ms < scan_interval_ms_) {
72 scan_interval_ms_ = filter->latency_ms;
73 }
74 }
75 return true;
76 }
77
MatchBle(const chreBleAdvertisingReport & report,chre::DynamicVector<nearby_BleFilterResult> * filter_results,chre::DynamicVector<nearby_BleFilterResult> * fp_filter_results)78 void Filter::MatchBle(
79 const chreBleAdvertisingReport &report,
80 chre::DynamicVector<nearby_BleFilterResult> *filter_results,
81 chre::DynamicVector<nearby_BleFilterResult> *fp_filter_results) {
82 #ifndef ENABLE_PRESENCE
83 UNUSED_VAR(filter_results);
84 #endif
85 LOGD("MatchBle");
86
87 nearby_BleFilterResult result;
88 auto record = BleScanRecord::Parse(report.data, report.dataLength);
89 // Log the service data for debug only.
90 for (const auto &ble_service_data : record.service_data) {
91 LOGD_SENSITIVE_INFO("Receive service data with uuid %" PRIX16,
92 ble_service_data.uuid);
93 for (int i = 0; i < ble_service_data.length; i++) {
94 LOGD_SENSITIVE_INFO("%" PRIx8, ble_service_data.data[i]);
95 }
96 LOGD_SENSITIVE_INFO("Service data end.");
97 }
98 for (int filter_index = 0; filter_index < ble_filters_.filter_count;
99 filter_index++) {
100 LOGD("MatchPresence advertisements.");
101 // TODO(b/193756395): multiple matched results can share the same BLE
102 // event. Optimize the memory usage by avoiding duplicated BLE events
103 // across multiple results.
104 result = nearby_BleFilterResult_init_zero;
105 result.has_id = true;
106 result.id = static_cast<uint32_t>(filter_index);
107 result.has_tx_power = true;
108 result.tx_power = static_cast<int32_t>(report.txPower);
109 result.has_rssi = true;
110 result.rssi = static_cast<int32_t>(report.rssi);
111 result.has_bluetooth_address = true;
112 // The buffer size has already been checked.
113 static_assert(std::size(result.bluetooth_address) == CHRE_BLE_ADDRESS_LEN);
114 memcpy(result.bluetooth_address, report.address, std::size(report.address));
115 result.has_timestamp_ns = true;
116 result.timestamp_ns =
117 report.timestamp +
118 static_cast<uint64_t>(chreGetEstimatedHostTimeOffset());
119 if (MatchFastPair(ble_filters_.filter[filter_index], record, &result)) {
120 LOGD("Add a matched Fast Pair filter result");
121 fp_filter_results->push_back(result);
122 return;
123 }
124 #ifdef ENABLE_PRESENCE
125 if (MatchPresenceV0(ble_filters_.filter[filter_index], record, &result) ||
126 MatchPresenceV1(ble_filters_.filter[filter_index], record,
127 PresenceCryptoMicImpl(), &result)) {
128 LOGD("Filter result TX power %" PRId32 ", RSSI %" PRId32, result.tx_power,
129 result.rssi);
130
131 LOGD("Add a matched Presence filter result");
132 filter_results->push_back(result);
133 }
134 #endif
135 }
136 }
137
138 } // namespace nearby
139