xref: /aosp_15_r20/system/chre/apps/nearby/location/lbs/contexthub/nanoapps/nearby/app_manager.cc (revision 84e339476a462649f82315436d70fd732297a399)
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/app_manager.h"
18 
19 #include <inttypes.h>
20 #include <pb_decode.h>
21 #include <pb_encode.h>
22 
23 #include <cstdint>
24 #include <utility>
25 
26 #include "chre_api/chre.h"
27 #include "location/lbs/contexthub/nanoapps/common/math/macros.h"
28 #include "location/lbs/contexthub/nanoapps/nearby/nearby_extension.h"
29 #include "location/lbs/contexthub/nanoapps/nearby/proto/nearby_extension.nanopb.h"
30 #include "location/lbs/contexthub/nanoapps/nearby/tracker_storage.h"
31 #include "location/lbs/contexthub/nanoapps/proto/filter.nanopb.h"
32 #include "third_party/contexthub/chre/util/include/chre/util/macros.h"
33 #include "third_party/contexthub/chre/util/include/chre/util/nanoapp/log.h"
34 #include "third_party/contexthub/chre/util/include/chre/util/time.h"
35 
36 #define LOG_TAG "[NEARBY][APP_MANAGER]"
37 
38 extern uint32_t ble_scan_keep_alive_timer_id;
39 
40 namespace nearby {
41 
42 using ::chre::Nanoseconds;
43 
AppManager()44 AppManager::AppManager() {
45   fp_filter_cache_time_nanosec_ = chreGetTime();
46   last_tracker_report_flush_time_nanosec_ = chreGetTime();
47   tracker_storage_.SetCallback(this);
48   // Enable host awake and sleep state events to opportunistically flush the
49   // tracker reports to the host.
50   chreConfigureHostSleepStateEvents(true /* enable */);
51 #ifdef NEARBY_PROFILE
52   ashProfileInit(
53       &profile_data_, "[NEARBY_MATCH_ADV_PERF]", 1000 /* print_interval_ms */,
54       false /* report_total_thread_cycles */, true /* printCsvFormat */);
55 #endif
56 }
57 
IsInitialized()58 bool AppManager::IsInitialized() {
59   // AppManager initialized successfully only when BLE scan is available.
60   return ble_scanner_.isAvailable();
61 }
62 
HandleEvent(uint32_t sender_instance_id,uint16_t event_type,const void * event_data)63 void AppManager::HandleEvent(uint32_t sender_instance_id, uint16_t event_type,
64                              const void *event_data) {
65   Nanoseconds wakeup_start_ns = Nanoseconds(chreGetTime());
66   LOGD("NanoApp wakeup starts by event %" PRIu16, event_type);
67   UNUSED_VAR(sender_instance_id);
68   const chreBleAdvertisementEvent *event;
69   switch (event_type) {
70     case CHRE_EVENT_MESSAGE_FROM_HOST:
71       HandleMessageFromHost(
72           static_cast<const chreMessageFromHostData *>(event_data));
73       break;
74     case CHRE_EVENT_BLE_ADVERTISEMENT:
75       event = static_cast<const chreBleAdvertisementEvent *>(event_data);
76       LOGD("Received %" PRIu16 "BLE reports", event->numReports);
77       // Print BLE advertisements for debug only.
78       for (uint16_t i = 0; i < event->numReports; i++) {
79         LOGD_SENSITIVE_INFO("Report %" PRIu16 " has %" PRIu16
80                             " bytes service data",
81                             i, event->reports[i].dataLength);
82         LOGD_SENSITIVE_INFO("timestamp msec: %" PRIu64,
83                             event->reports[i].timestamp / MSEC_TO_NANOS(1));
84         LOGD_SENSITIVE_INFO("service data byte: ");
85         LOGD_SENSITIVE_INFO("Tx power: %d", event->reports[i].txPower);
86         LOGD_SENSITIVE_INFO("RSSI: %d", event->reports[i].rssi);
87         for (int j = 0; j < 6; j++) {
88           LOGD_SENSITIVE_INFO("direct address %d: %d", j,
89                               event->reports[i].directAddress[j]);
90           LOGD_SENSITIVE_INFO("address %d: %d", j,
91                               event->reports[i].address[j]);
92         }
93         for (int j = 0; j < event->reports[i].dataLength; j++) {
94           LOGD_SENSITIVE_INFO("%d", event->reports[i].data[j]);
95         }
96         // Adds advertise report to advertise report cache with deduplicating.
97         adv_reports_cache_.Push(event->reports[i]);
98       }
99 
100       // If batch scan is not supported, requests the match process here.
101       // Otherwise, the match process is postponed to the batch complete event.
102       if (!ble_scanner_.IsBatchSupported()) {
103         HandleMatchAdvReports(adv_reports_cache_);
104       }
105       break;
106     case CHRE_EVENT_BLE_FLUSH_COMPLETE:
107       ble_scanner_.HandleEvent(event_type, event_data);
108       break;
109     case CHRE_EVENT_BLE_ASYNC_RESULT:
110       ble_scanner_.HandleEvent(event_type, event_data);
111       break;
112     case CHRE_EVENT_BLE_BATCH_COMPLETE:
113       LOGD("Received batch complete event");
114       HandleMatchAdvReports(adv_reports_cache_);
115       break;
116     case CHRE_EVENT_TIMER:
117       HandleTimerEvent(event_data);
118       break;
119     case CHRE_EVENT_HOST_AWAKE:
120       HandleHostAwakeEvent();
121       break;
122     default:
123       LOGD("Unknown event type: %" PRIu16, event_type);
124   }
125   Nanoseconds wakeup_duration_ns = Nanoseconds(chreGetTime()) - wakeup_start_ns;
126   LOGD("NanoApp wakeup ends after %" PRIu64 " ns by event %" PRIu16,
127        wakeup_duration_ns.toRawNanoseconds(), event_type);
128 }
129 
HandleMatchAdvReports(AdvReportCache & adv_reports_cache)130 void AppManager::HandleMatchAdvReports(AdvReportCache &adv_reports_cache) {
131 #ifdef NEARBY_PROFILE
132   ashProfileBegin(&profile_data_);
133 #endif
134   chre::DynamicVector<nearby_BleFilterResult> filter_results;
135   chre::DynamicVector<nearby_BleFilterResult> fp_filter_results;
136   for (const auto &report : adv_reports_cache.GetAdvReports()) {
137     if (report.dataLength == 0) {
138       continue;
139     }
140     filter_.MatchBle(report, &filter_results, &fp_filter_results);
141   }
142   if (!filter_results.empty()) {
143     LOGD("Send filter results back");
144     SendBulkFilterResultsToHost(filter_results);
145   }
146   if (!fp_filter_results.empty()) {
147     // FP host requires to receive scan results once during screen on
148     if (screen_on_ && !fp_screen_on_sent_) {
149       LOGD("Send FP filter results back");
150       SendBulkFilterResultsToHost(fp_filter_results);
151       fp_screen_on_sent_ = true;
152     }
153     LOGD("update FP filter cache");
154     fp_filter_cache_results_ = std::move(fp_filter_results);
155     fp_filter_cache_time_nanosec_ = chreGetTime();
156   }
157   // Matches tracker filters.
158   tracker_filter_.MatchAndSave(adv_reports_cache.GetAdvReports(),
159                                tracker_storage_);
160   // Matches extended filters.
161   chre::DynamicVector<FilterExtensionResult> filter_extension_results;
162   filter_extension_.Match(adv_reports_cache.GetAdvReports(),
163                           &filter_extension_results,
164                           &screen_on_filter_extension_results_);
165   if (!filter_extension_results.empty()) {
166     SendFilterExtensionResultToHost(filter_extension_results);
167   }
168   if (!screen_on_filter_extension_results_.empty()) {
169     if (screen_on_) {
170       LOGD("Send screen on filter extension results back");
171       SendFilterExtensionResultToHost(screen_on_filter_extension_results_);
172       screen_on_filter_extension_results_.clear();
173     } else {
174       for (auto &filter_result : screen_on_filter_extension_results_) {
175         filter_result.RefreshIfNeeded();
176       }
177       LOGD("Updated filter extension result cache");
178     }
179   }
180   adv_reports_cache.Clear();
181 #ifdef NEARBY_PROFILE
182   ashProfileEnd(&profile_data_, nullptr /* output */);
183 #endif
184 }
185 
HandleMessageFromHost(const chreMessageFromHostData * event)186 void AppManager::HandleMessageFromHost(const chreMessageFromHostData *event) {
187   LOGD("Got message from host with type %" PRIu32 " size %" PRIu32
188        " hostEndpoint 0x%" PRIx16,
189        event->messageType, event->messageSize, event->hostEndpoint);
190   switch (event->messageType) {
191     case lbs_FilterMessageType_MESSAGE_FILTERS:
192       host_endpoint_ = event->hostEndpoint;
193       RespondHostSetFilterRequest(filter_.Update(
194           static_cast<const uint8_t *>(event->message), event->messageSize));
195       fp_screen_on_sent_ = false;
196       if (filter_.IsEmpty()) {
197         ble_scanner_.ClearDefaultFilters();
198       } else {
199         ble_scanner_.SetDefaultFilters();
200       }
201       UpdateBleScanState();
202       break;
203     case lbs_FilterMessageType_MESSAGE_CONFIG:
204       HandleHostConfigRequest(static_cast<const uint8_t *>(event->message),
205                               event->messageSize);
206       break;
207     case lbs_FilterMessageType_MESSAGE_EXT_CONFIG_REQUEST:
208       HandleHostExtConfigRequest(event);
209       break;
210   }
211 }
212 
UpdateBleScanState()213 void AppManager::UpdateBleScanState() {
214   if (!filter_.IsEmpty() ||
215       (!tracker_filter_.IsEmpty() && tracker_filter_.IsActive()) ||
216       !filter_extension_.IsEmpty()) {
217     ble_scanner_.Restart();
218   } else {
219     ble_scanner_.Stop();
220   }
221 }
222 
RespondHostSetFilterRequest(const bool success)223 void AppManager::RespondHostSetFilterRequest(const bool success) {
224   auto resp_type = (success ? lbs_FilterMessageType_MESSAGE_SUCCESS
225                             : lbs_FilterMessageType_MESSAGE_FAILURE);
226   // TODO(b/238708594): change back to zero size response.
227   void *msg_buf = chreHeapAlloc(3);
228   LOGI("Acknowledge filter config.");
229   if (chreSendMessageWithPermissions(
230           msg_buf, 3, resp_type, host_endpoint_, CHRE_MESSAGE_PERMISSION_BLE,
231           [](void *msg, size_t /*size*/) { chreHeapFree(msg); })) {
232     LOGI("Succeeded to acknowledge Filter update");
233   } else {
234     LOGI("Failed to acknowledge Filter update");
235   }
236 }
237 
HandleHostConfigRequest(const uint8_t * message,uint32_t message_size)238 void AppManager::HandleHostConfigRequest(const uint8_t *message,
239                                          uint32_t message_size) {
240   nearby_BleConfig config = nearby_BleConfig_init_zero;
241   pb_istream_t stream = pb_istream_from_buffer(message, message_size);
242   if (!pb_decode(&stream, nearby_BleConfig_fields, &config)) {
243     LOGE("failed to decode config message");
244     return;
245   }
246   if (config.has_screen_on) {
247     screen_on_ = config.screen_on;
248     LOGD("received screen config %d", screen_on_);
249     if (screen_on_) {
250       fp_screen_on_sent_ = false;
251       if (ble_scanner_.isScanning()) {
252         ble_scanner_.Flush();
253       }
254       // TODO(b/255338604): used the default report delay value only because
255       // FP offload scan doesn't use low latency report delay.
256       // when the flushed packet droping issue is resolved, try to reconfigure
257       // report delay for Nearby Presence.
258       if (!fp_filter_cache_results_.empty()) {
259         LOGD("send FP filter result from cache");
260         uint64_t current_time = chreGetTime();
261         if (current_time - fp_filter_cache_time_nanosec_ <
262             fp_filter_cache_expire_nanosec_) {
263           SendBulkFilterResultsToHost(fp_filter_cache_results_);
264         } else {
265           // nanoapp receives screen_on message for both screen_on and unlock
266           // events. To send FP cache results on both events, keeps FP cache
267           // results until cache timeout.
268           fp_filter_cache_results_.clear();
269         }
270       }
271       if (!screen_on_filter_extension_results_.empty()) {
272         LOGD("try to send filter extension result from cache");
273         SendFilterExtensionResultToHost(screen_on_filter_extension_results_);
274         screen_on_filter_extension_results_.clear();
275       }
276     }
277   }
278   if (config.has_fast_pair_cache_expire_time_sec) {
279     fp_filter_cache_expire_nanosec_ = config.fast_pair_cache_expire_time_sec;
280   }
281 }
282 
SendBulkFilterResultsToHost(const chre::DynamicVector<nearby_BleFilterResult> & filter_results)283 void AppManager::SendBulkFilterResultsToHost(
284     const chre::DynamicVector<nearby_BleFilterResult> &filter_results) {
285   size_t encoded_size = 0;
286   if (!GetEncodedSizeFromFilterResults(filter_results, encoded_size)) {
287     return;
288   }
289   if (encoded_size <= kFilterResultsBufSize) {
290     SendFilterResultsToHost(filter_results);
291     return;
292   }
293   LOGD("Encoded size %zu is larger than buffer size %zu. Sends each one",
294        encoded_size, kFilterResultsBufSize);
295   for (const auto &filter_result : filter_results) {
296     SendFilterResultToHost(filter_result);
297   }
298 }
299 
SendFilterResultsToHost(const chre::DynamicVector<nearby_BleFilterResult> & filter_results)300 void AppManager::SendFilterResultsToHost(
301     const chre::DynamicVector<nearby_BleFilterResult> &filter_results) {
302   void *msg_buf = chreHeapAlloc(kFilterResultsBufSize);
303   if (msg_buf == nullptr) {
304     LOGE("Failed to allocate message buffer of size %zu for dispatch.",
305          kFilterResultsBufSize);
306     return;
307   }
308   auto stream = pb_ostream_from_buffer(static_cast<pb_byte_t *>(msg_buf),
309                                        kFilterResultsBufSize);
310   size_t msg_size = 0;
311   if (!EncodeFilterResults(filter_results, &stream, &msg_size)) {
312     LOGE("Unable to encode protobuf for BleFilterResults, error %s",
313          PB_GET_ERROR(&stream));
314     chreHeapFree(msg_buf);
315     return;
316   }
317   if (!chreSendMessageWithPermissions(
318           msg_buf, msg_size, lbs_FilterMessageType_MESSAGE_FILTER_RESULTS,
319           host_endpoint_, CHRE_MESSAGE_PERMISSION_BLE,
320           [](void *msg, size_t size) {
321             UNUSED_VAR(size);
322             chreHeapFree(msg);
323           })) {
324     LOGE("Failed to send FilterResults");
325   } else {
326     LOGD("Successfully sent the filter result.");
327   }
328 }
329 
SendFilterResultToHost(const nearby_BleFilterResult & filter_result)330 void AppManager::SendFilterResultToHost(
331     const nearby_BleFilterResult &filter_result) {
332   void *msg_buf = chreHeapAlloc(kFilterResultsBufSize);
333   if (msg_buf == nullptr) {
334     LOGE("Failed to allocate message buffer of size %zu for dispatch.",
335          kFilterResultsBufSize);
336     return;
337   }
338   size_t encoded_size = 0;
339   if (!pb_get_encoded_size(&encoded_size, nearby_BleFilterResult_fields,
340                            &filter_result)) {
341     LOGE("Failed to get encoded size for BleFilterResult");
342     return;
343   }
344   LOGD("BleFilterResult encoded size %zu", encoded_size);
345   auto stream = pb_ostream_from_buffer(static_cast<pb_byte_t *>(msg_buf),
346                                        kFilterResultsBufSize);
347   size_t msg_size = 0;
348   if (!EncodeFilterResult(filter_result, &stream, &msg_size)) {
349     LOGE("Unable to encode protobuf for BleFilterResult, error %s",
350          PB_GET_ERROR(&stream));
351     chreHeapFree(msg_buf);
352     return;
353   }
354   if (!chreSendMessageWithPermissions(
355           msg_buf, msg_size, lbs_FilterMessageType_MESSAGE_FILTER_RESULTS,
356           host_endpoint_, CHRE_MESSAGE_PERMISSION_BLE,
357           [](void *msg, size_t size) {
358             UNUSED_VAR(size);
359             chreHeapFree(msg);
360           })) {
361     LOGE("Failed to send FilterResults");
362   } else {
363     LOGD("Successfully sent the filter result.");
364   }
365 }
366 
367 // Struct to pass into EncodeFilterResult as *arg.
368 struct EncodeFieldResultsArg {
369   size_t *msg_size;
370   const chre::DynamicVector<nearby_BleFilterResult> *results;
371 };
372 
373 // Callback to encode repeated result in nearby_BleFilterResults.
EncodeFilterResultCallback(pb_ostream_t * stream,const pb_field_t * field,void * const * arg)374 static bool EncodeFilterResultCallback(pb_ostream_t *stream,
375                                        const pb_field_t *field,
376                                        void *const *arg) {
377   UNUSED_VAR(field);
378   bool success = true;
379   auto *encode_arg = static_cast<EncodeFieldResultsArg *>(*arg);
380 
381   for (const auto &result : *encode_arg->results) {
382     if (!pb_encode_tag_for_field(
383             stream,
384             &nearby_BleFilterResults_fields[nearby_BleFilterResults_result_tag -
385                                             1])) {
386       return false;
387     }
388     success =
389         pb_encode_submessage(stream, nearby_BleFilterResult_fields, &result);
390   }
391   if (success) {
392     *encode_arg->msg_size = stream->bytes_written;
393   }
394   return success;
395 }
396 
GetEncodedSizeFromFilterResults(const chre::DynamicVector<nearby_BleFilterResult> & filter_results,size_t & encoded_size)397 bool AppManager::GetEncodedSizeFromFilterResults(
398     const chre::DynamicVector<nearby_BleFilterResult> &filter_results,
399     size_t &encoded_size) {
400   size_t total_encoded_size = 0;
401   for (const auto &filter_result : filter_results) {
402     constexpr size_t kHeaderSize = 2;
403     size_t single_encoded_size = 0;
404     if (!pb_get_encoded_size(&single_encoded_size,
405                              nearby_BleFilterResult_fields, &filter_result)) {
406       LOGE("Failed to get encoded size for BleFilterResult");
407       return false;
408     }
409     total_encoded_size += single_encoded_size + kHeaderSize;
410   }
411   encoded_size = total_encoded_size;
412   return true;
413 }
414 
EncodeFilterResults(const chre::DynamicVector<nearby_BleFilterResult> & filter_results,pb_ostream_t * stream,size_t * msg_size)415 bool AppManager::EncodeFilterResults(
416     const chre::DynamicVector<nearby_BleFilterResult> &filter_results,
417     pb_ostream_t *stream, size_t *msg_size) {
418   // Ensure stream is properly initialized before encoding.
419   CHRE_ASSERT(stream->bytes_written == 0);
420   *msg_size = 0;
421 
422   EncodeFieldResultsArg arg = {
423       .msg_size = msg_size,
424       .results = &filter_results,
425   };
426   nearby_BleFilterResults pb_results = {
427       .result =
428           {
429               .funcs =
430                   {
431                       .encode = EncodeFilterResultCallback,
432                   },
433               .arg = &arg,
434           },
435   };
436   return pb_encode(stream, nearby_BleFilterResults_fields, &pb_results);
437 }
438 
EncodeFilterResult(const nearby_BleFilterResult & filter_result,pb_ostream_t * stream,size_t * msg_size)439 bool AppManager::EncodeFilterResult(const nearby_BleFilterResult &filter_result,
440                                     pb_ostream_t *stream, size_t *msg_size) {
441   // Ensure stream is properly initialized before encoding.
442   CHRE_ASSERT(stream->bytes_written == 0);
443   if (!pb_encode_tag_for_field(
444           stream,
445           &nearby_BleFilterResults_fields[nearby_BleFilterResults_result_tag -
446                                           1])) {
447     return false;
448   }
449   if (!pb_encode_submessage(stream, nearby_BleFilterResult_fields,
450                             &filter_result)) {
451     return false;
452   }
453   *msg_size = stream->bytes_written;
454   return true;
455 }
456 
HandleHostExtConfigRequest(const chreMessageFromHostData * event)457 void AppManager::HandleHostExtConfigRequest(
458     const chreMessageFromHostData *event) {
459   chreHostEndpointInfo host_info;
460   pb_istream_t stream =
461       pb_istream_from_buffer(static_cast<const uint8_t *>(event->message),
462                              static_cast<size_t>(event->messageSize));
463   nearby_extension_ExtConfigRequest config =
464       nearby_extension_ExtConfigRequest_init_default;
465   nearby_extension_ExtConfigResponse config_response =
466       nearby_extension_ExtConfigResponse_init_zero;
467 
468   if (!pb_decode(&stream, nearby_extension_ExtConfigRequest_fields, &config)) {
469     LOGE("Failed to decode extended config msg: %s", PB_GET_ERROR(&stream));
470   } else if (!chreGetHostEndpointInfo(event->hostEndpoint, &host_info)) {
471     LOGE("Failed to get host info.");
472     config_response.result = CHREX_NEARBY_RESULT_INTERNAL_ERROR;
473   } else if (!host_info.isNameValid) {
474     LOGE("Failed to get package name");
475     config_response.result = CHREX_NEARBY_RESULT_UNKNOWN_PACKAGE;
476   } else {
477     LOGD("*** Receiving %s extended config ***",
478          GetExtConfigNameFromTag(config.which_config));
479 
480     switch (config.which_config) {
481       case nearby_extension_ExtConfigRequest_filter_config_tag:
482         if (!HandleExtFilterConfig(host_info, config.config.filter_config,
483                                    &config_response)) {
484           LOGE("Failed to handle extended filter config");
485         }
486         break;
487       case nearby_extension_ExtConfigRequest_service_config_tag:
488         if (!HandleExtServiceConfig(host_info, config.config.service_config,
489                                     &config_response)) {
490           LOGE("Failed to handle extended service config");
491         }
492         break;
493       case nearby_extension_ExtConfigRequest_tracker_filter_config_tag:
494         if (!HandleExtTrackerFilterConfig(host_info,
495                                           config.config.tracker_filter_config,
496                                           &config_response)) {
497           LOGE("Failed to handle tracker filter config");
498         }
499         break;
500       case nearby_extension_ExtConfigRequest_flush_tracker_reports_tag:
501         HandleExtFlushTrackerReports(
502             host_info, config.config.flush_tracker_reports, &config_response);
503         break;
504       default:
505         LOGE("Unknown extended config %d", config.which_config);
506         config_response.result = CHREX_NEARBY_RESULT_FEATURE_NOT_SUPPORTED;
507         break;
508     }
509   }
510   SendExtConfigResponseToHost(config.request_id, event->hostEndpoint,
511                               config_response);
512 }
513 
HandleExtFilterConfig(const chreHostEndpointInfo & host_info,const nearby_extension_ExtConfigRequest_FilterConfig & config,nearby_extension_ExtConfigResponse * config_response)514 bool AppManager::HandleExtFilterConfig(
515     const chreHostEndpointInfo &host_info,
516     const nearby_extension_ExtConfigRequest_FilterConfig &config,
517     nearby_extension_ExtConfigResponse *config_response) {
518   chre::DynamicVector<chreBleGenericFilter> generic_filters;
519 
520   filter_extension_.Update(host_info, config, &generic_filters,
521                            config_response);
522   if (config_response->result != CHREX_NEARBY_RESULT_OK) {
523     return false;
524   }
525   if (!ble_scanner_.UpdateFilters(host_info.hostEndpointId, &generic_filters)) {
526     config_response->result = CHREX_NEARBY_RESULT_INTERNAL_ERROR;
527     return false;
528   }
529   UpdateBleScanState();
530   return true;
531 }
532 
HandleExtServiceConfig(const chreHostEndpointInfo & host_info,const nearby_extension_ExtConfigRequest_ServiceConfig & config,nearby_extension_ExtConfigResponse * config_response)533 bool AppManager::HandleExtServiceConfig(
534     const chreHostEndpointInfo &host_info,
535     const nearby_extension_ExtConfigRequest_ServiceConfig &config,
536     nearby_extension_ExtConfigResponse *config_response) {
537   filter_extension_.ConfigureService(host_info, config, config_response);
538   if (config_response->result != CHREX_NEARBY_RESULT_OK) {
539     return false;
540   }
541   return true;
542 }
543 
SendExtConfigResponseToHost(uint32_t request_id,uint16_t host_end_point,nearby_extension_ExtConfigResponse & config_response)544 void AppManager::SendExtConfigResponseToHost(
545     uint32_t request_id, uint16_t host_end_point,
546     nearby_extension_ExtConfigResponse &config_response) {
547   config_response.has_request_id = true;
548   config_response.request_id = request_id;
549   uint8_t *msg_buf = (uint8_t *)chreHeapAlloc(kFilterResultsBufSize);
550   if (msg_buf == nullptr) {
551     LOGE("Failed to allocate message buffer of size %zu for dispatch.",
552          kFilterResultsBufSize);
553     return;
554   }
555   size_t encoded_size;
556   if (!FilterExtension::EncodeConfigResponse(
557           config_response, ByteArray(msg_buf, kFilterResultsBufSize),
558           &encoded_size)) {
559     chreHeapFree(msg_buf);
560     return;
561   }
562   if (chreSendMessageWithPermissions(
563           msg_buf, encoded_size,
564           lbs_FilterMessageType_MESSAGE_EXT_CONFIG_RESPONSE, host_end_point,
565           CHRE_MESSAGE_PERMISSION_BLE,
566           [](void *msg, size_t /*size*/) { chreHeapFree(msg); })) {
567     LOGD("Successfully sent the extended config response for request %" PRIu32
568          ".",
569          request_id);
570   } else {
571     LOGE("Failed to send extended config response for request %" PRIu32 ".",
572          request_id);
573   }
574 }
575 
SendFilterExtensionResultToHost(chre::DynamicVector<FilterExtensionResult> & filter_results)576 void AppManager::SendFilterExtensionResultToHost(
577     chre::DynamicVector<FilterExtensionResult> &filter_results) {
578   for (auto &result : filter_results) {
579     auto &reports = result.GetAdvReports();
580     if (reports.empty()) {
581       continue;
582     }
583     for (auto &report : reports) {
584       size_t encoded_size;
585       uint8_t *msg_buf = (uint8_t *)chreHeapAlloc(kFilterResultsBufSize);
586       if (msg_buf == nullptr) {
587         LOGE("Failed to allocate message buffer of size %zu for dispatch.",
588              kFilterResultsBufSize);
589         return;
590       }
591       if (!FilterExtension::EncodeAdvReport(
592               report, ByteArray(msg_buf, kFilterResultsBufSize),
593               &encoded_size)) {
594         chreHeapFree(msg_buf);
595         return;
596       }
597       if (chreSendMessageWithPermissions(
598               msg_buf, encoded_size,
599               lbs_FilterMessageType_MESSAGE_FILTER_RESULTS, result.end_point,
600               CHRE_MESSAGE_PERMISSION_BLE,
601               [](void *msg, size_t /*size*/) { chreHeapFree(msg); })) {
602         LOGD("Successfully sent the filter extension result.");
603       } else {
604         LOGE("Failed to send filter extension result.");
605       }
606     }
607   }
608 }
609 
GetExtConfigNameFromTag(pb_size_t config_tag)610 const char *AppManager::GetExtConfigNameFromTag(pb_size_t config_tag) {
611   switch (config_tag) {
612     case nearby_extension_ExtConfigRequest_filter_config_tag:
613       return "FilterConfig";
614     case nearby_extension_ExtConfigRequest_service_config_tag:
615       return "ServiceConfig";
616     case nearby_extension_ExtConfigRequest_tracker_filter_config_tag:
617       return "TrackerFilterConfig";
618     case nearby_extension_ExtConfigRequest_flush_tracker_reports_tag:
619       return "FlushTrackerReports";
620     default:
621       return "Unknown";
622   }
623 }
624 
HandleHostAwakeEvent()625 void AppManager::HandleHostAwakeEvent() {
626   // Send tracker reports to host when receive host awake event.
627   uint64_t current_time = chreGetTime();
628   uint64_t flush_threshold_nanosec =
629       tracker_filter_.GetBatchConfig().opportunistic_flush_threshold_time_ms *
630       chre::kOneMillisecondInNanoseconds;
631   if (current_time - last_tracker_report_flush_time_nanosec_ >=
632       flush_threshold_nanosec) {
633     LOGD("Flush tracker reports by host awake event.");
634     SendTrackerReportsToHost(tracker_storage_.GetBatchReports());
635     tracker_storage_.Clear();
636   }
637 }
638 
HandleTimerEvent(const void * event_data)639 void AppManager::HandleTimerEvent(const void *event_data) {
640   if (event_data == &ble_scan_keep_alive_timer_id) {
641     tracker_storage_.Refresh(tracker_filter_.GetBatchConfig());
642   } else if (event_data ==
643              tracker_filter_.GetActiveIntervalTimer().GetTimerId()) {
644     // When receive the active interval timer event, set the active state for
645     // tracker scan filter, start the oneshot active window timer, and set the
646     // tracker scan filters from the BLE scanner. Then update the BLE scan state
647     // so that the tracker scan can start properly. The tracker scan will stop
648     // when receive the oneshot active window timer event.
649     tracker_filter_.SetActiveState();
650     tracker_filter_.GetActiveWindowTimer().StartTimer();
651     ble_scanner_.SetTrackerFilters();
652     UpdateBleScanState();
653   } else if (event_data ==
654              tracker_filter_.GetActiveWindowTimer().GetTimerId()) {
655     // When receive the active window timer event, clear the active state for
656     // tracker scan filter, clear the tracker scan filters from the BLE scanner,
657     // and update the BLE scan state so that the tracker scan can stop properly.
658     // The tracker scan will restart when receive the next active interval timer
659     // event. If the tracker filter is empty, no action is needed as the tracker
660     // scan has completely stopped at this point.
661     if (!tracker_filter_.IsEmpty()) {
662       tracker_filter_.ClearActiveState();
663       ble_scanner_.ClearTrackerFilters();
664       UpdateBleScanState();
665     }
666   }
667 }
668 
OnTrackerStorageFullEvent()669 void AppManager::OnTrackerStorageFullEvent() {
670   SendTrackerStorageFullEventToHost();
671 }
672 
HandleExtTrackerFilterConfig(const chreHostEndpointInfo & host_info,const nearby_extension_ExtConfigRequest_TrackerFilterConfig & config,nearby_extension_ExtConfigResponse * config_response)673 bool AppManager::HandleExtTrackerFilterConfig(
674     const chreHostEndpointInfo &host_info,
675     const nearby_extension_ExtConfigRequest_TrackerFilterConfig &config,
676     nearby_extension_ExtConfigResponse *config_response) {
677   chre::DynamicVector<chreBleGenericFilter> generic_filters;
678   tracker_filter_.Update(host_info, config, &generic_filters, config_response);
679   if (config_response->result != CHREX_NEARBY_RESULT_OK) {
680     return false;
681   }
682   ble_scanner_.UpdateTrackerFilters(generic_filters);
683   // Set or clear tracker scan filter state before updating BLE scan state.
684   if (tracker_filter_.IsEmpty()) {
685     ble_scanner_.ClearTrackerFilters();
686   } else {
687     ble_scanner_.SetTrackerFilters();
688   }
689   UpdateBleScanState();
690   // Send tracker reports to host before clearing the tracker storage if the
691   // host stops the tracker filter.
692   if (tracker_filter_.IsEmpty()) {
693     SendTrackerReportsToHost(tracker_storage_.GetBatchReports());
694     tracker_storage_.Clear();
695   }
696   return true;
697 }
698 
HandleExtFlushTrackerReports(const chreHostEndpointInfo & host_info,const nearby_extension_ExtConfigRequest_FlushTrackerReports &,nearby_extension_ExtConfigResponse * config_response)699 void AppManager::HandleExtFlushTrackerReports(
700     const chreHostEndpointInfo &host_info,
701     const nearby_extension_ExtConfigRequest_FlushTrackerReports & /*config*/,
702     nearby_extension_ExtConfigResponse *config_response) {
703   LOGD("Flush tracker reports by host: id (%" PRIu16 "), package name (%s)",
704        host_info.hostEndpointId,
705        host_info.isNameValid ? host_info.packageName : "unknown");
706   SendTrackerReportsToHost(tracker_storage_.GetBatchReports());
707   tracker_storage_.Clear();
708   config_response->has_result = true;
709   config_response->result = CHREX_NEARBY_RESULT_OK;
710 }
711 
SendTrackerStorageFullEventToHost()712 void AppManager::SendTrackerStorageFullEventToHost() {
713   uint16_t host_end_point = tracker_filter_.GetHostEndPoint();
714   LOGI("Send tracker storage full event.");
715   if (chreSendMessageWithPermissions(
716           /*message=*/nullptr, /*messageSize=*/0,
717           lbs_FilterMessageType_MESSAGE_EXT_STORAGE_FULL_EVENT, host_end_point,
718           CHRE_MESSAGE_PERMISSION_BLE,
719           [](void *msg, size_t /*size*/) { chreHeapFree(msg); })) {
720     LOGI("Succeeded to send tracker storage full event");
721   } else {
722     LOGI("Failed to send tracker storage full event");
723   }
724 }
725 
SendTrackerReportsToHost(chre::DynamicVector<TrackerReport> & tracker_reports)726 void AppManager::SendTrackerReportsToHost(
727     chre::DynamicVector<TrackerReport> &tracker_reports) {
728   last_tracker_report_flush_time_nanosec_ = chreGetTime();
729   uint16_t host_end_point = tracker_filter_.GetHostEndPoint();
730   for (auto &tracker_report : tracker_reports) {
731     size_t encoded_size;
732     uint8_t *msg_buf = (uint8_t *)chreHeapAlloc(kTrackerReportsBufSize);
733     if (msg_buf == nullptr) {
734       LOGE("Failed to allocate message buffer of size %zu for dispatch.",
735            kTrackerReportsBufSize);
736       return;
737     }
738     if (!TrackerFilter::EncodeTrackerReport(
739             tracker_report, ByteArray(msg_buf, kTrackerReportsBufSize),
740             &encoded_size)) {
741       chreHeapFree(msg_buf);
742       return;
743     }
744     if (chreSendMessageWithPermissions(
745             msg_buf, encoded_size, lbs_FilterMessageType_MESSAGE_TRACKER_REPORT,
746             host_end_point, CHRE_MESSAGE_PERMISSION_BLE,
747             [](void *msg, size_t /*size*/) { chreHeapFree(msg); })) {
748       LOGD("Successfully sent the tracker report.");
749     } else {
750       LOGE("Failed to send tracker report.");
751     }
752   }
753 }
754 
755 }  // namespace nearby
756