• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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