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