xref: /aosp_15_r20/system/chre/apps/nearby/location/lbs/contexthub/nanoapps/nearby/filter_extension.cc (revision 84e339476a462649f82315436d70fd732297a399)
1 #include "location/lbs/contexthub/nanoapps/nearby/filter_extension.h"
2 
3 #include <inttypes.h>
4 #include <pb_decode.h>
5 #include <pb_encode.h>
6 
7 #include <cstddef>
8 #include <cstdint>
9 #include <utility>
10 
11 #include "chre_api/chre.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 "third_party/contexthub/chre/util/include/chre/util/nanoapp/log.h"
15 
16 #define LOG_TAG "[NEARBY][FILTER_EXTENSION]"
17 
18 namespace nearby {
19 
20 const size_t kChreBleGenericFilterDataSize = 29;
21 
22 constexpr nearby_extension_FilterResult kEmptyFilterResult =
23     nearby_extension_FilterResult_init_zero;
24 
Update(const chreHostEndpointInfo & host_info,const nearby_extension_ExtConfigRequest_FilterConfig & filter_config,chre::DynamicVector<chreBleGenericFilter> * generic_filters,nearby_extension_ExtConfigResponse * config_response)25 void FilterExtension::Update(
26     const chreHostEndpointInfo &host_info,
27     const nearby_extension_ExtConfigRequest_FilterConfig &filter_config,
28     chre::DynamicVector<chreBleGenericFilter> *generic_filters,
29     nearby_extension_ExtConfigResponse *config_response) {
30   LOGD("Update extension filter");
31   const int32_t host_index = FindOrCreateHostIndex(host_info);
32   if (host_index < 0) {
33     LOGE("Failed to find or create the host.");
34     return;
35   }
36   HostEndpointInfo &host = host_list_[static_cast<size_t>(host_index)];
37   config_response->has_result = true;
38   config_response->has_vendor_status = true;
39 
40   // Returns 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   }
52   chreBleScanFilter scan_filter;
53   scan_filter.rssiThreshold = CHRE_BLE_RSSI_THRESHOLD_NONE;
54   scan_filter.scanFilterCount = static_cast<uint8_t>(generic_filters->size());
55   scan_filter.scanFilters = generic_filters->data();
56 
57   chrexNearbyExtendedFilterConfig config;
58   config.data = filter_config.oem_filter;
59   config.data_length = filter_config.oem_filter_length;
60   host.cache_expire_ms = filter_config.cache_expire_ms;
61 
62   config_response->result = static_cast<int32_t>(
63       chrexNearbySetExtendedFilterConfig(&host.host_info, &scan_filter, &config,
64                                          &config_response->vendor_status));
65   if (config_response->result != CHREX_NEARBY_RESULT_OK) {
66     LOGE("Failed to config filters, result %" PRId32, config_response->result);
67     host_list_.erase(static_cast<size_t>(host_index));
68     return;
69   }
70   // Removes the host if both hardware and oem filters are empty.
71   if (filter_config.hardware_filter_count == 0 &&
72       filter_config.oem_filter_length == 0) {
73     LOGD("Remove host: id (%d), package name (%s)",
74          host.host_info.hostEndpointId,
75          host.host_info.isNameValid ? host.host_info.packageName : "unknown");
76     host_list_.erase(static_cast<size_t>(host_index));
77   }
78 }
79 
ConfigureService(const chreHostEndpointInfo & host_info,const nearby_extension_ExtConfigRequest_ServiceConfig & service_config,nearby_extension_ExtConfigResponse * config_response)80 void FilterExtension::ConfigureService(
81     const chreHostEndpointInfo &host_info,
82     const nearby_extension_ExtConfigRequest_ServiceConfig &service_config,
83     nearby_extension_ExtConfigResponse *config_response) {
84   LOGD("Configure extension service");
85   config_response->has_result = true;
86   config_response->has_vendor_status = true;
87 
88   chrexNearbyExtendedServiceConfig config;
89   config.data = service_config.data;
90   config.data_length = service_config.data_length;
91 
92   config_response->result =
93       static_cast<int32_t>(chrexNearbySetExtendedServiceConfig(
94           &host_info, &config, &config_response->vendor_status));
95 }
96 
FindOrCreateHostIndex(const chreHostEndpointInfo & host_info)97 int32_t FilterExtension::FindOrCreateHostIndex(
98     const chreHostEndpointInfo &host_info) {
99   for (size_t index = 0; index < host_list_.size(); index++) {
100     if (host_info.hostEndpointId ==
101         host_list_[index].host_info.hostEndpointId) {
102       return static_cast<int32_t>(index);
103     }
104   }
105   if (!host_list_.push_back(HostEndpointInfo(host_info))) {
106     LOGE("Failed to add new host info.");
107     return -1;
108   }
109   return static_cast<int32_t>(host_list_.size() - 1);
110 }
111 
112 /* Adds a FilterExtensionResult (initialized by endpoint_id) to filter_results
113  * if it has not been included in filter_results.
114  * Returns the index of the entry.
115  */
AddToFilterResults(const HostEndpointInfo & host,chre::DynamicVector<FilterExtensionResult> * filter_results)116 size_t AddToFilterResults(
117     const HostEndpointInfo &host,
118     chre::DynamicVector<FilterExtensionResult> *filter_results) {
119   FilterExtensionResult result(host.host_info.hostEndpointId,
120                                host.cache_expire_ms);
121   size_t idx = filter_results->find(result);
122   if (filter_results->size() == idx) {
123     filter_results->push_back(std::move(result));
124   }
125   return idx;
126 }
127 
Match(const chre::DynamicVector<chreBleAdvertisingReport> & ble_adv_list,chre::DynamicVector<FilterExtensionResult> * filter_results,chre::DynamicVector<FilterExtensionResult> * screen_on_filter_results)128 void FilterExtension::Match(
129     const chre::DynamicVector<chreBleAdvertisingReport> &ble_adv_list,
130     chre::DynamicVector<FilterExtensionResult> *filter_results,
131     chre::DynamicVector<FilterExtensionResult> *screen_on_filter_results) {
132   for (const HostEndpointInfo &host : host_list_) {
133     size_t idx = AddToFilterResults(host, filter_results);
134     size_t screen_on_idx = AddToFilterResults(host, screen_on_filter_results);
135     for (const auto &ble_adv_report : ble_adv_list) {
136       switch (
137           chrexNearbyMatchExtendedFilter(&host.host_info, &ble_adv_report)) {
138         case CHREX_NEARBY_FILTER_ACTION_IGNORE:
139           continue;
140         case CHREX_NEARBY_FILTER_ACTION_DELIVER_ON_WAKE:
141           LOGD("Include BLE report to screen on list.");
142           (*screen_on_filter_results)[screen_on_idx].reports.Push(
143               ble_adv_report);
144           continue;
145         case CHREX_NEARBY_FILTER_ACTION_DELIVER_IMMEDIATELY:
146           LOGD("Include BLE report to immediate delivery list.");
147           (*filter_results)[idx].reports.Push(ble_adv_report);
148           continue;
149       }
150     }
151   }
152 }
153 
EncodeConfigResponse(const nearby_extension_ExtConfigResponse & config_response,ByteArray data_buf,size_t * encoded_size)154 bool FilterExtension::EncodeConfigResponse(
155     const nearby_extension_ExtConfigResponse &config_response,
156     ByteArray data_buf, size_t *encoded_size) {
157   if (!pb_get_encoded_size(encoded_size,
158                            nearby_extension_ExtConfigResponse_fields,
159                            &config_response)) {
160     LOGE("Failed to get extended config response size.");
161     return false;
162   }
163   pb_ostream_t ostream = pb_ostream_from_buffer(data_buf.data, data_buf.length);
164 
165   if (!pb_encode(&ostream, nearby_extension_ExtConfigResponse_fields,
166                  &config_response)) {
167     LOGE("Unable to encode protobuf for ExtConfigResponse, error %s",
168          PB_GET_ERROR(&ostream));
169     return false;
170   }
171   return true;
172 }
173 
Encode(const chre::DynamicVector<chreBleAdvertisingReport> & reports,ByteArray data_buf,size_t * encoded_size)174 bool FilterExtension::Encode(
175     const chre::DynamicVector<chreBleAdvertisingReport> &reports,
176     ByteArray data_buf, size_t *encoded_size) {
177   nearby_extension_FilterResult filter_result = kEmptyFilterResult;
178   size_t idx = 0;
179   for (const auto &report : reports) {
180     nearby_extension_ChreBleAdvertisingReport &report_proto =
181         filter_result.report[idx];
182     report_proto.has_timestamp = true;
183     report_proto.timestamp = report.timestamp;
184     report_proto.has_event_type_and_data_status = true;
185     report_proto.event_type_and_data_status = report.eventTypeAndDataStatus;
186     report_proto.has_address_type = true;
187     report_proto.address_type =
188         static_cast<nearby_extension_ChreBleAdvertisingReport_AddressType>(
189             report.addressType);
190     report_proto.has_address = true;
191     for (size_t i = 0; i < 6; i++) {
192       report_proto.address[i] = report.address[i];
193     }
194     report_proto.has_tx_power = true;
195     report_proto.tx_power = report.txPower;
196     report_proto.has_rssi = true;
197     report_proto.rssi = report.rssi;
198     report_proto.has_data_length = true;
199     report_proto.data_length = report.dataLength;
200     if (report.dataLength > 0) {
201       report_proto.has_data = true;
202     }
203     for (size_t i = 0; i < report.dataLength; i++) {
204       report_proto.data[i] = report.data[i];
205     }
206     idx++;
207   }
208   filter_result.report_count = static_cast<pb_size_t>(idx);
209   filter_result.has_error_code = true;
210   filter_result.error_code = nearby_extension_FilterResult_ErrorCode_SUCCESS;
211 
212   if (!pb_get_encoded_size(encoded_size, nearby_extension_FilterResult_fields,
213                            &filter_result)) {
214     LOGE("Failed to get filter extension result size.");
215     return false;
216   }
217   pb_ostream_t ostream = pb_ostream_from_buffer(data_buf.data, data_buf.length);
218 
219   if (!pb_encode(&ostream, nearby_extension_FilterResult_fields,
220                  &filter_result)) {
221     LOGE("Unable to encode protobuf for FilterExtensionResults, error %s",
222          PB_GET_ERROR(&ostream));
223     return false;
224   }
225   return true;
226 }
227 
EncodeAdvReport(chreBleAdvertisingReport & report,ByteArray data_buf,size_t * encoded_size)228 bool FilterExtension::EncodeAdvReport(chreBleAdvertisingReport &report,
229                                       ByteArray data_buf,
230                                       size_t *encoded_size) {
231   nearby_extension_FilterResult filter_result = kEmptyFilterResult;
232   nearby_extension_ChreBleAdvertisingReport &report_proto =
233       filter_result.report[0];
234   report_proto.has_timestamp = true;
235   report_proto.timestamp =
236       report.timestamp +
237       static_cast<uint64_t>(chreGetEstimatedHostTimeOffset());
238   report_proto.has_event_type_and_data_status = true;
239   report_proto.event_type_and_data_status = report.eventTypeAndDataStatus;
240   report_proto.has_address_type = true;
241   report_proto.address_type =
242       static_cast<nearby_extension_ChreBleAdvertisingReport_AddressType>(
243           report.addressType);
244   report_proto.has_address = true;
245   for (size_t i = 0; i < 6; i++) {
246     report_proto.address[i] = report.address[i];
247   }
248   report_proto.has_tx_power = true;
249   report_proto.tx_power = report.txPower;
250   report_proto.has_rssi = true;
251   report_proto.rssi = report.rssi;
252   report_proto.has_data_length = true;
253   report_proto.data_length = report.dataLength;
254   if (report.dataLength > 0) {
255     report_proto.has_data = true;
256   }
257   for (size_t i = 0; i < report.dataLength; i++) {
258     report_proto.data[i] = report.data[i];
259   }
260   filter_result.report_count = 1;
261   filter_result.has_error_code = true;
262   filter_result.error_code = nearby_extension_FilterResult_ErrorCode_SUCCESS;
263 
264   if (!pb_get_encoded_size(encoded_size, nearby_extension_FilterResult_fields,
265                            &filter_result)) {
266     LOGE("Failed to get filter extension result size.");
267     return false;
268   }
269   pb_ostream_t ostream = pb_ostream_from_buffer(data_buf.data, data_buf.length);
270 
271   if (!pb_encode(&ostream, nearby_extension_FilterResult_fields,
272                  &filter_result)) {
273     LOGE("Unable to encode protobuf for FilterExtensionResults, error %s",
274          PB_GET_ERROR(&ostream));
275     return false;
276   }
277   return true;
278 }
279 
280 }  // namespace nearby
281