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 = filter_config.rssi_threshold;
55 scan_filter_config_.active_interval_ms = filter_config.active_interval_ms;
56 scan_filter_config_.active_window_ms = filter_config.active_window_ms;
57 ConfigureActiveState();
58 ConfigureScanControlTimers();
59 // Sets batch configuration
60 batch_config_.sample_interval_ms = filter_config.sample_interval_ms;
61 batch_config_.max_tracker_count = filter_config.max_tracker_count;
62 batch_config_.notify_threshold_tracker_count =
63 filter_config.notify_threshold_tracker_count;
64 batch_config_.max_history_count = filter_config.max_history_count;
65 batch_config_.lost_timeout_ms = filter_config.lost_timeout_ms;
66 batch_config_.opportunistic_flush_threshold_time_ms =
67 filter_config.opportunistic_flush_threshold_time_ms;
68 }
69
ConfigureActiveState()70 void TrackerFilter::ConfigureActiveState() {
71 if (!scan_filter_config_.hardware_filters.empty()) {
72 SetActiveState();
73 } else {
74 ClearActiveState();
75 }
76 }
77
ConfigureScanControlTimers()78 void TrackerFilter::ConfigureScanControlTimers() {
79 // The timer based scan is only enabled when the hardware scan filters are not
80 // empty and the active window and interval are valid. The active interval
81 // must be greater than the active window so that the timer based scan can
82 // function properly.
83 if (!scan_filter_config_.hardware_filters.empty() &&
84 scan_filter_config_.active_window_ms > 0) {
85 if (scan_filter_config_.active_interval_ms <=
86 scan_filter_config_.active_window_ms) {
87 LOGE("Invalid active interval %" PRIu32
88 " ms, must be greater than active window %" PRIu32 " ms.",
89 scan_filter_config_.active_interval_ms,
90 scan_filter_config_.active_window_ms);
91 return;
92 }
93 // Sets active interval and window timer duration.
94 active_interval_timer_.SetDurationMs(
95 scan_filter_config_.active_interval_ms);
96 active_window_timer_.SetDurationMs(scan_filter_config_.active_window_ms);
97 // Starts active interval and window timers.
98 if (active_interval_timer_.StartTimer()) {
99 active_window_timer_.StartTimer();
100 }
101 } else if (scan_filter_config_.hardware_filters.empty()) {
102 active_interval_timer_.StopTimer();
103 }
104 }
105
MatchAndSave(const chre::DynamicVector<chreBleAdvertisingReport> & ble_adv_reports,TrackerStorage & tracker_storage)106 void TrackerFilter::MatchAndSave(
107 const chre::DynamicVector<chreBleAdvertisingReport> &ble_adv_reports,
108 TrackerStorage &tracker_storage) {
109 for (const auto &report : ble_adv_reports) {
110 if (HwFilter::CheckRssi(scan_filter_config_.rssi_threshold, report) &&
111 HwFilter::Match(scan_filter_config_.hardware_filters, report)) {
112 tracker_storage.Push(report, batch_config_);
113 }
114 }
115 }
116
EncodeTrackerReport(TrackerReport & tracker_report,ByteArray data_buf,size_t * encoded_size)117 bool TrackerFilter::EncodeTrackerReport(TrackerReport &tracker_report,
118 ByteArray data_buf,
119 size_t *encoded_size) {
120 nearby_extension_TrackerReport filter_result = kEmptyTrackerReport;
121 filter_result.has_report = true;
122 nearby_extension_ChreBleAdvertisingReport &report_proto =
123 filter_result.report;
124 report_proto.has_timestamp = true;
125 report_proto.timestamp =
126 tracker_report.header.timestamp +
127 static_cast<uint64_t>(chreGetEstimatedHostTimeOffset());
128 report_proto.has_event_type_and_data_status = true;
129 report_proto.event_type_and_data_status =
130 tracker_report.header.eventTypeAndDataStatus;
131 report_proto.has_address_type = true;
132 report_proto.address_type =
133 static_cast<nearby_extension_ChreBleAdvertisingReport_AddressType>(
134 tracker_report.header.addressType);
135 report_proto.has_address = true;
136 for (size_t i = 0; i < CHRE_BLE_ADDRESS_LEN; i++) {
137 report_proto.address[i] = tracker_report.header.address[i];
138 }
139 report_proto.has_tx_power = true;
140 report_proto.tx_power = tracker_report.header.txPower;
141 report_proto.has_rssi = true;
142 report_proto.rssi = tracker_report.header.rssi;
143 report_proto.has_data_length = true;
144 report_proto.data_length = tracker_report.header.dataLength;
145 if (tracker_report.header.dataLength > 0) {
146 report_proto.has_data = true;
147 }
148 for (size_t i = 0; i < tracker_report.header.dataLength; i++) {
149 report_proto.data[i] = tracker_report.data[i];
150 }
151 size_t idx = 0;
152 for (const auto &history : tracker_report.historian) {
153 nearby_extension_TrackerHistory &history_proto =
154 filter_result.historian[idx];
155 history_proto.has_found_count = true;
156 history_proto.found_count = history.found_count;
157 history_proto.has_first_found_time_ms = true;
158 history_proto.first_found_time_ms = history.first_found_time_ms;
159 history_proto.has_last_found_time_ms = true;
160 history_proto.last_found_time_ms = history.last_found_time_ms;
161 history_proto.has_lost_time_ms = true;
162 history_proto.lost_time_ms = history.lost_time_ms;
163 history_proto.has_state = true;
164 history_proto.state =
165 history.state == TrackerState::kPresent
166 ? nearby_extension_TrackerHistory_TrackerState_PRESENT
167 : nearby_extension_TrackerHistory_TrackerState_ABSENT;
168 ++idx;
169 }
170 filter_result.historian_count = static_cast<pb_size_t>(idx);
171 if (!pb_get_encoded_size(encoded_size, nearby_extension_TrackerReport_fields,
172 &filter_result)) {
173 LOGE("Failed to get batch filter result size.");
174 return false;
175 }
176 pb_ostream_t ostream = pb_ostream_from_buffer(data_buf.data, data_buf.length);
177 if (!pb_encode(&ostream, nearby_extension_TrackerReport_fields,
178 &filter_result)) {
179 LOGE("Unable to encode protobuf for BatchFilterResult, error %s",
180 PB_GET_ERROR(&ostream));
181 return false;
182 }
183 return true;
184 }
185
186 } // namespace nearby
187