1 #include "location/lbs/contexthub/nanoapps/nearby/tracker_filter.h"
2
3 #include <inttypes.h>
4 #include <cstddef>
5 #include <cstdint>
6 #include <cstring>
7 #include <utility>
8
9 #include "chre_api/chre.h"
10 #include "location/lbs/contexthub/nanoapps/nearby/byte_array.h"
11 #include "location/lbs/contexthub/nanoapps/nearby/hw_filter.h"
12 #include "location/lbs/contexthub/nanoapps/nearby/nearby_extension.h"
13 #include "location/lbs/contexthub/nanoapps/nearby/proto/nearby_extension.nanopb.h"
14 #include "location/lbs/contexthub/nanoapps/nearby/tracker_storage.h"
15 #include "third_party/contexthub/chre/util/include/chre/util/dynamic_vector.h"
16 #include "third_party/contexthub/chre/util/include/chre/util/nanoapp/log.h"
17 #include "third_party/nanopb/pb.h"
18 #include "third_party/nanopb/pb_encode.h"
19
20 #define LOG_TAG "[NEARBY][TRACKER_FILTER]"
21
22 namespace nearby {
23
24 const size_t kChreBleGenericFilterDataSize = 29;
25 constexpr nearby_extension_TrackerReport kEmptyTrackerReport =
26 nearby_extension_TrackerReport_init_zero;
27
Update(const chreHostEndpointInfo & host_info,const nearby_extension_ExtConfigRequest_TrackerFilterConfig & filter_config,chre::DynamicVector<chreBleGenericFilter> * generic_filters,nearby_extension_ExtConfigResponse * config_response)28 void TrackerFilter::Update(
29 const chreHostEndpointInfo &host_info,
30 const nearby_extension_ExtConfigRequest_TrackerFilterConfig &filter_config,
31 chre::DynamicVector<chreBleGenericFilter> *generic_filters,
32 nearby_extension_ExtConfigResponse *config_response) {
33 host_info_ = host_info;
34 LOGD("Update tracker filters %u from %s", filter_config.hardware_filter_count,
35 host_info_.packageName);
36 config_response->has_result = true;
37 config_response->result = CHREX_NEARBY_RESULT_OK;
38 // Sets scan filter configuration and returns hardware filters to
39 // generic_filters used in ble scanner's scan settings.
40 chre::DynamicVector<chreBleGenericFilter> hardware_filters;
41 for (int i = 0; i < filter_config.hardware_filter_count; i++) {
42 const nearby_extension_ChreBleGenericFilter &hw_filter =
43 filter_config.hardware_filter[i];
44 chreBleGenericFilter generic_filter;
45 generic_filter.type = hw_filter.type;
46 generic_filter.len = static_cast<uint8_t>(hw_filter.len);
47 memcpy(generic_filter.data, hw_filter.data, kChreBleGenericFilterDataSize);
48 memcpy(generic_filter.dataMask, hw_filter.data_mask,
49 kChreBleGenericFilterDataSize);
50 generic_filters->push_back(generic_filter);
51 hardware_filters.push_back(generic_filter);
52 }
53 scan_filter_config_.hardware_filters = std::move(hardware_filters);
54 scan_filter_config_.rssi_threshold =
55 static_cast<int8_t>(filter_config.rssi_threshold);
56 scan_filter_config_.active_interval_ms = filter_config.active_interval_ms;
57 scan_filter_config_.active_window_ms = filter_config.active_window_ms;
58 ConfigureActiveState();
59 ConfigureScanControlTimers();
60 // Sets batch configuration
61 batch_config_.sample_interval_ms = filter_config.sample_interval_ms;
62 batch_config_.max_tracker_count = filter_config.max_tracker_count;
63 batch_config_.notify_threshold_tracker_count =
64 filter_config.notify_threshold_tracker_count;
65 batch_config_.max_history_count = filter_config.max_history_count;
66 batch_config_.lost_timeout_ms = filter_config.lost_timeout_ms;
67 batch_config_.opportunistic_flush_threshold_time_ms =
68 filter_config.opportunistic_flush_threshold_time_ms;
69 }
70
ConfigureActiveState()71 void TrackerFilter::ConfigureActiveState() {
72 if (!scan_filter_config_.hardware_filters.empty()) {
73 SetActiveState();
74 } else {
75 ClearActiveState();
76 }
77 }
78
ConfigureScanControlTimers()79 void TrackerFilter::ConfigureScanControlTimers() {
80 // The timer based scan is only enabled when the hardware scan filters are not
81 // empty and the active window and interval are valid. The active interval
82 // must be greater than the active window so that the timer based scan can
83 // function properly.
84 if (!scan_filter_config_.hardware_filters.empty() &&
85 scan_filter_config_.active_window_ms > 0) {
86 if (scan_filter_config_.active_interval_ms <=
87 scan_filter_config_.active_window_ms) {
88 LOGE("Invalid active interval %" PRIu32
89 " ms, must be greater than active window %" PRIu32 " ms.",
90 scan_filter_config_.active_interval_ms,
91 scan_filter_config_.active_window_ms);
92 return;
93 }
94 // Sets active interval and window timer duration.
95 active_interval_timer_.SetDurationMs(
96 scan_filter_config_.active_interval_ms);
97 active_window_timer_.SetDurationMs(scan_filter_config_.active_window_ms);
98 // Starts active interval and window timers.
99 if (active_interval_timer_.StartTimer()) {
100 active_window_timer_.StartTimer();
101 }
102 } else if (scan_filter_config_.hardware_filters.empty()) {
103 active_interval_timer_.StopTimer();
104 }
105 }
106
MatchAndSave(const chre::DynamicVector<chreBleAdvertisingReport> & ble_adv_reports,TrackerStorage & tracker_storage)107 void TrackerFilter::MatchAndSave(
108 const chre::DynamicVector<chreBleAdvertisingReport> &ble_adv_reports,
109 TrackerStorage &tracker_storage) {
110 for (const auto &report : ble_adv_reports) {
111 if (HwFilter::CheckRssi(scan_filter_config_.rssi_threshold, report) &&
112 HwFilter::Match(scan_filter_config_.hardware_filters, report)) {
113 tracker_storage.Push(report, batch_config_);
114 }
115 }
116 }
117
EncodeTrackerReport(TrackerReport & tracker_report,ByteArray data_buf,size_t * encoded_size)118 bool TrackerFilter::EncodeTrackerReport(TrackerReport &tracker_report,
119 ByteArray data_buf,
120 size_t *encoded_size) {
121 nearby_extension_TrackerReport filter_result = kEmptyTrackerReport;
122 filter_result.has_report = true;
123 nearby_extension_ChreBleAdvertisingReport &report_proto =
124 filter_result.report;
125 report_proto.has_timestamp = true;
126 report_proto.timestamp =
127 tracker_report.header.timestamp +
128 static_cast<uint64_t>(chreGetEstimatedHostTimeOffset());
129 report_proto.has_event_type_and_data_status = true;
130 report_proto.event_type_and_data_status =
131 tracker_report.header.eventTypeAndDataStatus;
132 report_proto.has_address_type = true;
133 report_proto.address_type =
134 static_cast<nearby_extension_ChreBleAdvertisingReport_AddressType>(
135 tracker_report.header.addressType);
136 report_proto.has_address = true;
137 for (size_t i = 0; i < CHRE_BLE_ADDRESS_LEN; i++) {
138 report_proto.address[i] = tracker_report.header.address[i];
139 }
140 report_proto.has_tx_power = true;
141 report_proto.tx_power = tracker_report.header.txPower;
142 report_proto.has_rssi = true;
143 report_proto.rssi = tracker_report.header.rssi;
144 report_proto.has_data_length = true;
145 report_proto.data_length = tracker_report.header.dataLength;
146 if (tracker_report.header.dataLength > 0) {
147 report_proto.has_data = true;
148 }
149 for (size_t i = 0; i < tracker_report.header.dataLength; i++) {
150 report_proto.data[i] = tracker_report.data[i];
151 }
152 size_t idx = 0;
153 for (const auto &history : tracker_report.historian) {
154 nearby_extension_TrackerHistory &history_proto =
155 filter_result.historian[idx];
156 history_proto.has_found_count = true;
157 history_proto.found_count = history.found_count;
158 history_proto.has_first_found_time_ms = true;
159 history_proto.first_found_time_ms = history.first_found_time_ms;
160 history_proto.has_last_found_time_ms = true;
161 history_proto.last_found_time_ms = history.last_found_time_ms;
162 history_proto.has_lost_time_ms = true;
163 history_proto.lost_time_ms = history.lost_time_ms;
164 history_proto.has_state = true;
165 history_proto.state =
166 history.state == TrackerState::kPresent
167 ? nearby_extension_TrackerHistory_TrackerState_PRESENT
168 : nearby_extension_TrackerHistory_TrackerState_ABSENT;
169 ++idx;
170 }
171 filter_result.historian_count = static_cast<pb_size_t>(idx);
172 if (!pb_get_encoded_size(encoded_size, nearby_extension_TrackerReport_fields,
173 &filter_result)) {
174 LOGE("Failed to get batch filter result size.");
175 return false;
176 }
177 pb_ostream_t ostream = pb_ostream_from_buffer(data_buf.data, data_buf.length);
178 if (!pb_encode(&ostream, nearby_extension_TrackerReport_fields,
179 &filter_result)) {
180 LOGE("Unable to encode protobuf for BatchFilterResult, error %s",
181 PB_GET_ERROR(&ostream));
182 return false;
183 }
184 return true;
185 }
186
187 } // namespace nearby
188