1 /*
2 * Copyright (C) 2021 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 #ifdef CHRE_BLE_SUPPORT_ENABLED
18
19 #include "chre/core/ble_request_manager.h"
20
21 #include "chre/core/event_loop_manager.h"
22 #include "chre/platform/fatal_error.h"
23 #include "chre/platform/log.h"
24 #include "chre/util/fixed_size_vector.h"
25 #include "chre/util/nested_data_ptr.h"
26 #include "chre/util/system/ble_util.h"
27 #include "chre/util/system/event_callbacks.h"
28
29 namespace chre {
30
init()31 void BleRequestManager::init() {
32 mPlatformBle.init();
33 }
34
getCapabilities()35 uint32_t BleRequestManager::getCapabilities() {
36 return mPlatformBle.getCapabilities();
37 }
38
getFilterCapabilities()39 uint32_t BleRequestManager::getFilterCapabilities() {
40 return mPlatformBle.getFilterCapabilities();
41 }
42
handleExistingRequest(uint16_t instanceId,bool * hasExistingRequest,size_t * requestIndex)43 void BleRequestManager::handleExistingRequest(uint16_t instanceId,
44 bool *hasExistingRequest,
45 size_t *requestIndex) {
46 const BleRequest *foundRequest =
47 mRequests.findRequest(instanceId, requestIndex);
48 *hasExistingRequest = (foundRequest != nullptr);
49 if (foundRequest != nullptr &&
50 foundRequest->getRequestStatus() != RequestStatus::APPLIED) {
51 handleAsyncResult(instanceId, foundRequest->isEnabled(),
52 false /* success */, CHRE_ERROR_OBSOLETE_REQUEST,
53 foundRequest->getCookie(), true /* forceUnregister */);
54 }
55 }
56
compliesWithBleSetting(uint16_t instanceId,bool enabled,bool hasExistingRequest,size_t requestIndex,const void * cookie)57 bool BleRequestManager::compliesWithBleSetting(uint16_t instanceId,
58 bool enabled,
59 bool hasExistingRequest,
60 size_t requestIndex,
61 const void *cookie) {
62 bool success = true;
63 if (enabled && !bleSettingEnabled()) {
64 success = false;
65 handleAsyncResult(instanceId, enabled, false /* success */,
66 CHRE_ERROR_FUNCTION_DISABLED, cookie);
67 if (hasExistingRequest) {
68 bool requestChanged = false;
69 mRequests.removeRequest(requestIndex, &requestChanged);
70 }
71 }
72 return success;
73 }
74
updateRequests(BleRequest && request,bool hasExistingRequest,bool * requestChanged,size_t * requestIndex)75 bool BleRequestManager::updateRequests(BleRequest &&request,
76 bool hasExistingRequest,
77 bool *requestChanged,
78 size_t *requestIndex) {
79 bool success = true;
80 if (hasExistingRequest) {
81 mRequests.updateRequest(*requestIndex, std::move(request), requestChanged);
82 } else if (request.isEnabled()) {
83 success =
84 mRequests.addRequest(std::move(request), requestIndex, requestChanged);
85 } else {
86 // Already disabled requests shouldn't result in work for the PAL.
87 *requestChanged = false;
88 *requestIndex = mRequests.getRequests().size();
89 }
90 return success;
91 }
92
startScanAsync(Nanoapp * nanoapp,chreBleScanMode mode,uint32_t reportDelayMs,const struct chreBleScanFilterV1_9 * filter,const void * cookie)93 bool BleRequestManager::startScanAsync(
94 Nanoapp *nanoapp, chreBleScanMode mode, uint32_t reportDelayMs,
95 const struct chreBleScanFilterV1_9 *filter, const void *cookie) {
96 CHRE_ASSERT(nanoapp);
97 BleRequest request(nanoapp->getInstanceId(), true /* enable */, mode,
98 reportDelayMs, filter, cookie);
99 return configure(std::move(request));
100 }
101
stopScanAsync(Nanoapp * nanoapp,const void * cookie)102 bool BleRequestManager::stopScanAsync(Nanoapp *nanoapp, const void *cookie) {
103 CHRE_ASSERT(nanoapp);
104 BleRequest request(nanoapp->getInstanceId(), false /* enable */, cookie);
105 return configure(std::move(request));
106 }
107
disableActiveScan(const Nanoapp * nanoapp)108 uint32_t BleRequestManager::disableActiveScan(const Nanoapp *nanoapp) {
109 CHRE_ASSERT(nanoapp);
110
111 size_t requestIndex;
112 const BleRequest *foundRequest =
113 mRequests.findRequest(nanoapp->getInstanceId(), &requestIndex);
114
115 if (foundRequest == nullptr || !foundRequest->isEnabled()) {
116 // No active request found.
117 return 0;
118 }
119
120 BleRequest request(nanoapp->getInstanceId(), false /* enable */,
121 nullptr /* cookie */);
122 configure(std::move(request));
123 return 1;
124 }
125
readRssiAsync(Nanoapp * nanoapp,uint16_t connectionHandle,const void * cookie)126 bool BleRequestManager::readRssiAsync(Nanoapp *nanoapp,
127 uint16_t connectionHandle,
128 const void *cookie) {
129 CHRE_ASSERT(nanoapp);
130 if (mPendingRssiRequests.full()) {
131 LOG_OOM();
132 return false;
133 }
134 if (mPendingRssiRequests.empty()) {
135 // no previous request existed, so issue this one immediately to get
136 // an early exit if we get a failure
137 auto status = readRssi(connectionHandle);
138 if (status != CHRE_ERROR_NONE) {
139 return false;
140 }
141 }
142 // it's pending, so report the result asynchronously
143 mPendingRssiRequests.push(
144 BleReadRssiRequest{nanoapp->getInstanceId(), connectionHandle, cookie});
145 return true;
146 }
147
flushAsync(Nanoapp * nanoapp,const void * cookie)148 bool BleRequestManager::flushAsync(Nanoapp *nanoapp, const void *cookie) {
149 CHRE_ASSERT(nanoapp);
150
151 bool supportsFlush =
152 getCapabilities() & CHRE_BLE_CAPABILITIES_SCAN_RESULT_BATCHING;
153 if (!supportsFlush) {
154 return false;
155 }
156
157 bool success = false;
158 const BleRequest *foundRequest =
159 mRequests.findRequest(nanoapp->getInstanceId(), nullptr);
160 if (foundRequest == nullptr) {
161 LOGE("Nanoapp with instance ID: %" PRIu16
162 " does not have an existing BLE request and cannot flush",
163 nanoapp->getInstanceId());
164 } else if (mFlushRequestQueue.full()) {
165 LOG_OOM();
166 } else {
167 mFlushRequestQueue.emplace(nanoapp->getInstanceId(), cookie);
168 success = processFlushRequests();
169 }
170
171 return success;
172 }
173
addBleRequestLog(uint32_t instanceId,bool enabled,size_t requestIndex,bool compliesWithBleSetting)174 void BleRequestManager::addBleRequestLog(uint32_t instanceId, bool enabled,
175 size_t requestIndex,
176 bool compliesWithBleSetting) {
177 BleRequestLog log(SystemTime::getMonotonicTime(), instanceId, enabled,
178 compliesWithBleSetting);
179 if (enabled) {
180 if (instanceId == CHRE_INSTANCE_ID) {
181 log.populateRequestData(mRequests.getCurrentMaximalRequest());
182 } else if (compliesWithBleSetting) {
183 log.populateRequestData(mRequests.getRequests()[requestIndex]);
184 }
185 }
186 mBleRequestLogs.kick_push(log);
187 }
188
configure(BleRequest && request)189 bool BleRequestManager::configure(BleRequest &&request) {
190 bool success = validateParams(request);
191 if (success) {
192 bool requestChanged = false;
193 size_t requestIndex = 0;
194 bool hasExistingRequest = false;
195 uint16_t instanceId = request.getInstanceId();
196 uint8_t enabled = request.isEnabled();
197 handleExistingRequest(instanceId, &hasExistingRequest, &requestIndex);
198 bool compliant =
199 compliesWithBleSetting(instanceId, enabled, hasExistingRequest,
200 requestIndex, request.getCookie());
201 if (compliant) {
202 success = updateRequests(std::move(request), hasExistingRequest,
203 &requestChanged, &requestIndex);
204 if (success) {
205 if (!mPlatformRequestInProgress) {
206 if (!requestChanged) {
207 handleAsyncResult(instanceId, enabled, true /* success */,
208 CHRE_ERROR_NONE, request.getCookie());
209 if (requestIndex < mRequests.getRequests().size()) {
210 mRequests.getMutableRequests()[requestIndex].setRequestStatus(
211 RequestStatus::APPLIED);
212 }
213 } else {
214 success = controlPlatform();
215 if (!success) {
216 handleNanoappEventRegistration(instanceId, enabled,
217 false /* success */,
218 true /* forceUnregister */);
219 mRequests.removeRequest(requestIndex, &requestChanged);
220 }
221 }
222 }
223 }
224 }
225 if (success) {
226 addBleRequestLog(instanceId, enabled, requestIndex, compliant);
227 }
228 }
229 return success;
230 }
231
controlPlatform()232 bool BleRequestManager::controlPlatform() {
233 bool success = false;
234 const BleRequest &maxRequest = mRequests.getCurrentMaximalRequest();
235 bool enable = bleSettingEnabled() && maxRequest.isEnabled();
236
237 if (enable) {
238 chreBleScanFilterV1_9 filter = maxRequest.getScanFilter();
239 success = mPlatformBle.startScanAsync(
240 maxRequest.getMode(), maxRequest.getReportDelayMs(), &filter);
241 mPendingPlatformRequest = BleRequest(
242 0 /* instanceId */, enable, maxRequest.getMode(),
243 maxRequest.getReportDelayMs(), &filter, nullptr /* cookie */);
244 } else {
245 success = mPlatformBle.stopScanAsync();
246 mPendingPlatformRequest =
247 BleRequest(0 /* instanceId */, enable, nullptr /* cookie */);
248 }
249
250 if (success) {
251 for (BleRequest &req : mRequests.getMutableRequests()) {
252 if (req.getRequestStatus() == RequestStatus::PENDING_REQ) {
253 req.setRequestStatus(RequestStatus::PENDING_RESP);
254 }
255 }
256 mPlatformRequestInProgress = true;
257 }
258
259 return success;
260 }
261
handleFreeAdvertisingEvent(struct chreBleAdvertisementEvent * event)262 void BleRequestManager::handleFreeAdvertisingEvent(
263 struct chreBleAdvertisementEvent *event) {
264 mPlatformBle.releaseAdvertisingEvent(event);
265 }
266
freeAdvertisingEventCallback(uint16_t,void * eventData)267 void BleRequestManager::freeAdvertisingEventCallback(uint16_t /* eventType */,
268 void *eventData) {
269 auto event = static_cast<chreBleAdvertisementEvent *>(eventData);
270 EventLoopManagerSingleton::get()
271 ->getBleRequestManager()
272 .handleFreeAdvertisingEvent(event);
273 }
274
handleAdvertisementEvent(struct chreBleAdvertisementEvent * event)275 void BleRequestManager::handleAdvertisementEvent(
276 struct chreBleAdvertisementEvent *event) {
277 for (uint16_t i = 0; i < event->numReports; i++) {
278 populateLegacyAdvertisingReportFields(
279 const_cast<chreBleAdvertisingReport &>(event->reports[i]));
280 }
281 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
282 CHRE_EVENT_BLE_ADVERTISEMENT, event, freeAdvertisingEventCallback);
283 }
284
handlePlatformChange(bool enable,uint8_t errorCode)285 void BleRequestManager::handlePlatformChange(bool enable, uint8_t errorCode) {
286 auto callback = [](uint16_t /*type*/, void *data, void *extraData) {
287 bool enableCb = NestedDataPtr<bool>(data);
288 uint8_t errorCodeCb = NestedDataPtr<uint8_t>(extraData);
289 EventLoopManagerSingleton::get()
290 ->getBleRequestManager()
291 .handlePlatformChangeSync(enableCb, errorCodeCb);
292 };
293
294 EventLoopManagerSingleton::get()->deferCallback(
295 SystemCallbackType::BleScanResponse, NestedDataPtr<bool>(enable),
296 callback, NestedDataPtr<uint8_t>(errorCode));
297 }
298
handlePlatformChangeSync(bool enable,uint8_t errorCode)299 void BleRequestManager::handlePlatformChangeSync(bool enable,
300 uint8_t errorCode) {
301 bool success = (errorCode == CHRE_ERROR_NONE);
302 // Requests to disable BLE scans should always succeed
303 if (!mPendingPlatformRequest.isEnabled() && enable) {
304 errorCode = CHRE_ERROR;
305 success = false;
306 CHRE_ASSERT_LOG(false, "Unable to stop BLE scan");
307 }
308
309 mPlatformRequestInProgress = false;
310 for (BleRequest &req : mRequests.getMutableRequests()) {
311 if (req.getRequestStatus() == RequestStatus::PENDING_RESP) {
312 handleAsyncResult(req.getInstanceId(), req.isEnabled(), success,
313 errorCode, req.getCookie());
314 if (success) {
315 req.setRequestStatus(RequestStatus::APPLIED);
316 }
317 }
318 }
319
320 if (!success) {
321 mRequests.removeRequests(RequestStatus::PENDING_RESP);
322 } else {
323 // No need to waste memory for requests that have no effect on the overall
324 // maximal request.
325 mRequests.removeDisabledRequests();
326 mActivePlatformRequest = std::move(mPendingPlatformRequest);
327 }
328
329 if (mRequests.hasRequests(RequestStatus::PENDING_REQ)) {
330 dispatchPendingRequests();
331 } else if (!success && mResyncPending) {
332 updatePlatformRequest(true /* forceUpdate */);
333 }
334
335 if (!mPlatformRequestInProgress && mSettingChangePending) {
336 updatePlatformRequest();
337 }
338
339 mResyncPending = false;
340 mSettingChangePending = false;
341 }
342
dispatchPendingRequests()343 void BleRequestManager::dispatchPendingRequests() {
344 uint8_t errorCode = CHRE_ERROR_NONE;
345 if (!bleSettingEnabled() && mRequests.isMaximalRequestEnabled()) {
346 errorCode = CHRE_ERROR_FUNCTION_DISABLED;
347 } else if (!controlPlatform()) {
348 errorCode = CHRE_ERROR;
349 }
350 if (errorCode != CHRE_ERROR_NONE) {
351 for (const BleRequest &req : mRequests.getRequests()) {
352 if (req.getRequestStatus() == RequestStatus::PENDING_REQ) {
353 handleAsyncResult(req.getInstanceId(), req.isEnabled(),
354 false /* success */, errorCode, req.getCookie());
355 }
356 }
357 mRequests.removeRequests(RequestStatus::PENDING_REQ);
358 }
359 }
360
handleAsyncResult(uint16_t instanceId,bool enabled,bool success,uint8_t errorCode,const void * cookie,bool forceUnregister)361 void BleRequestManager::handleAsyncResult(uint16_t instanceId, bool enabled,
362 bool success, uint8_t errorCode,
363 const void *cookie,
364 bool forceUnregister) {
365 uint8_t requestType = enabled ? CHRE_BLE_REQUEST_TYPE_START_SCAN
366 : CHRE_BLE_REQUEST_TYPE_STOP_SCAN;
367 postAsyncResultEventFatal(instanceId, requestType, success, errorCode,
368 cookie);
369 handleNanoappEventRegistration(instanceId, enabled, success, forceUnregister);
370 }
371
handleNanoappEventRegistration(uint16_t instanceId,bool enabled,bool success,bool forceUnregister)372 void BleRequestManager::handleNanoappEventRegistration(uint16_t instanceId,
373 bool enabled,
374 bool success,
375 bool forceUnregister) {
376 Nanoapp *nanoapp =
377 EventLoopManagerSingleton::get()->getEventLoop().findNanoappByInstanceId(
378 instanceId);
379 if (nanoapp != nullptr) {
380 if (success && enabled) {
381 nanoapp->registerForBroadcastEvent(CHRE_EVENT_BLE_ADVERTISEMENT);
382 } else if (!enabled || forceUnregister) {
383 nanoapp->unregisterForBroadcastEvent(CHRE_EVENT_BLE_ADVERTISEMENT);
384 }
385 }
386 }
387
handleRequestStateResyncCallback()388 void BleRequestManager::handleRequestStateResyncCallback() {
389 auto callback = [](uint16_t /* eventType */, void * /* eventData */,
390 void * /* extraData */) {
391 EventLoopManagerSingleton::get()
392 ->getBleRequestManager()
393 .handleRequestStateResyncCallbackSync();
394 };
395 EventLoopManagerSingleton::get()->deferCallback(
396 SystemCallbackType::BleRequestResyncEvent, nullptr /* data */, callback);
397 }
398
handleRequestStateResyncCallbackSync()399 void BleRequestManager::handleRequestStateResyncCallbackSync() {
400 if (mPlatformRequestInProgress) {
401 mResyncPending = true;
402 } else {
403 updatePlatformRequest(true /* forceUpdate */);
404 }
405 }
406
handleReadRssi(uint8_t errorCode,uint16_t connectionHandle,int8_t rssi)407 void BleRequestManager::handleReadRssi(uint8_t errorCode,
408 uint16_t connectionHandle, int8_t rssi) {
409 struct readRssiResponse {
410 uint8_t errorCode;
411 int8_t rssi;
412 uint16_t connectionHandle;
413 };
414
415 auto callback = [](uint16_t /* eventType */, void *eventData,
416 void * /* extraData */) {
417 readRssiResponse response = NestedDataPtr<readRssiResponse>(eventData);
418 EventLoopManagerSingleton::get()->getBleRequestManager().handleReadRssiSync(
419 response.errorCode, response.connectionHandle, response.rssi);
420 };
421
422 EventLoopManagerSingleton::get()->deferCallback(
423 SystemCallbackType::BleReadRssiEvent,
424 NestedDataPtr<readRssiResponse>(
425 readRssiResponse{errorCode, rssi, connectionHandle}),
426 callback);
427 }
428
handleReadRssiSync(uint8_t errorCode,uint16_t connectionHandle,int8_t rssi)429 void BleRequestManager::handleReadRssiSync(uint8_t errorCode,
430 uint16_t connectionHandle,
431 int8_t rssi) {
432 if (mPendingRssiRequests.empty()) {
433 FATAL_ERROR(
434 "Got unexpected handleReadRssi event without outstanding request");
435 }
436
437 if (mPendingRssiRequests.front().connectionHandle != connectionHandle) {
438 FATAL_ERROR(
439 "Got readRssi event for mismatched connection handle (%d != %d)",
440 mPendingRssiRequests.front().connectionHandle, connectionHandle);
441 }
442
443 resolvePendingRssiRequest(errorCode, rssi);
444 dispatchNextRssiRequestIfAny();
445 }
446
resolvePendingRssiRequest(uint8_t errorCode,int8_t rssi)447 void BleRequestManager::resolvePendingRssiRequest(uint8_t errorCode,
448 int8_t rssi) {
449 auto event = memoryAlloc<chreBleReadRssiEvent>();
450 if (event == nullptr) {
451 FATAL_ERROR("Failed to alloc BLE async result");
452 }
453
454 event->result.cookie = mPendingRssiRequests.front().cookie;
455 event->result.success = (errorCode == CHRE_ERROR_NONE);
456 event->result.requestType = CHRE_BLE_REQUEST_TYPE_READ_RSSI;
457 event->result.errorCode = errorCode;
458 event->result.reserved = 0;
459 event->connectionHandle = mPendingRssiRequests.front().connectionHandle;
460 event->rssi = rssi;
461
462 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
463 CHRE_EVENT_BLE_RSSI_READ, event, freeEventDataCallback,
464 mPendingRssiRequests.front().instanceId);
465
466 mPendingRssiRequests.pop();
467 }
468
dispatchNextRssiRequestIfAny()469 void BleRequestManager::dispatchNextRssiRequestIfAny() {
470 while (!mPendingRssiRequests.empty()) {
471 auto req = mPendingRssiRequests.front();
472 auto status = readRssi(req.connectionHandle);
473 if (status == CHRE_ERROR_NONE) {
474 // control flow resumes in the handleReadRssi() callback, on completion
475 return;
476 }
477 resolvePendingRssiRequest(status, 0x7F /* failure RSSI from BT spec */);
478 }
479 }
480
readRssi(uint16_t connectionHandle)481 uint8_t BleRequestManager::readRssi(uint16_t connectionHandle) {
482 if (!bleSettingEnabled()) {
483 return CHRE_ERROR_FUNCTION_DISABLED;
484 }
485 auto success = mPlatformBle.readRssiAsync(connectionHandle);
486 if (success) {
487 return CHRE_ERROR_NONE;
488 } else {
489 return CHRE_ERROR;
490 }
491 }
492
handleFlushComplete(uint8_t errorCode)493 void BleRequestManager::handleFlushComplete(uint8_t errorCode) {
494 if (mFlushRequestTimerHandle != CHRE_TIMER_INVALID) {
495 EventLoopManagerSingleton::get()->cancelDelayedCallback(
496 mFlushRequestTimerHandle);
497 mFlushRequestTimerHandle = CHRE_TIMER_INVALID;
498 }
499
500 handleFlushCompleteInternal(errorCode);
501 }
502
handleFlushCompleteTimeout()503 void BleRequestManager::handleFlushCompleteTimeout() {
504 mFlushRequestTimerHandle = CHRE_TIMER_INVALID;
505 handleFlushCompleteInternal(CHRE_ERROR_TIMEOUT);
506 }
507
getScanStatus(struct chreBleScanStatus *)508 bool BleRequestManager::getScanStatus(struct chreBleScanStatus * /* status */) {
509 // TODO(b/266820139): Implement this
510 return false;
511 }
512
onSettingChanged(Setting setting,bool)513 void BleRequestManager::onSettingChanged(Setting setting, bool /* state */) {
514 if (setting == Setting::BLE_AVAILABLE) {
515 if (mPlatformRequestInProgress) {
516 mSettingChangePending = true;
517 } else {
518 updatePlatformRequest();
519 }
520 }
521 }
522
updatePlatformRequest(bool forceUpdate)523 void BleRequestManager::updatePlatformRequest(bool forceUpdate) {
524 bool desiredPlatformState =
525 bleSettingEnabled() && mRequests.isMaximalRequestEnabled();
526 bool updatePlatform = (forceUpdate || (desiredPlatformState !=
527 mActivePlatformRequest.isEnabled()));
528
529 if (updatePlatform) {
530 if (controlPlatform()) {
531 addBleRequestLog(CHRE_INSTANCE_ID, desiredPlatformState,
532 mRequests.getRequests().size(),
533 true /* compliesWithBleSetting */);
534 } else {
535 FATAL_ERROR("Failed to send update BLE platform request");
536 }
537 }
538 }
539
handleFlushCompleteInternal(uint8_t errorCode)540 void BleRequestManager::handleFlushCompleteInternal(uint8_t errorCode) {
541 auto callback = [](uint16_t /* type */, void *data, void * /* extraData */) {
542 uint8_t cbErrorCode = NestedDataPtr<uint8_t>(data);
543 EventLoopManagerSingleton::get()
544 ->getBleRequestManager()
545 .handleFlushCompleteSync(cbErrorCode);
546 };
547
548 if (!EventLoopManagerSingleton::get()->deferCallback(
549 SystemCallbackType::BleFlushComplete,
550 NestedDataPtr<uint8_t>(errorCode), callback)) {
551 FATAL_ERROR("Unable to defer flush complete callback");
552 }
553 }
554
handleFlushCompleteSync(uint8_t errorCode)555 void BleRequestManager::handleFlushCompleteSync(uint8_t errorCode) {
556 if (mFlushRequestQueue.empty() || !mFlushRequestQueue.front().isActive) {
557 LOGE(
558 "handleFlushCompleteSync was called, but there is no active flush "
559 "request");
560 return;
561 }
562
563 FlushRequest &flushRequest = mFlushRequestQueue.front();
564 sendFlushCompleteEventOrDie(flushRequest, errorCode);
565 mFlushRequestQueue.pop();
566
567 processFlushRequests();
568 }
569
doFlushRequest()570 uint8_t BleRequestManager::doFlushRequest() {
571 CHRE_ASSERT(!mFlushRequestQueue.empty());
572
573 FlushRequest &flushRequest = mFlushRequestQueue.front();
574 if (flushRequest.isActive) {
575 return CHRE_ERROR_NONE;
576 }
577
578 Nanoseconds now = SystemTime::getMonotonicTime();
579 uint8_t errorCode = CHRE_ERROR_NONE;
580 if (now >= flushRequest.deadlineTimestamp) {
581 LOGE("BLE flush request for nanoapp with instance ID: %" PRIu16
582 " failed: deadline exceeded",
583 flushRequest.nanoappInstanceId);
584 errorCode = CHRE_ERROR_TIMEOUT;
585 } else {
586 auto timeoutCallback = [](uint16_t /* type */, void * /* data */,
587 void * /* extraData */) {
588 EventLoopManagerSingleton::get()
589 ->getBleRequestManager()
590 .handleFlushCompleteTimeout();
591 };
592 mFlushRequestTimerHandle =
593 EventLoopManagerSingleton::get()->setDelayedCallback(
594 SystemCallbackType::BleFlushTimeout, nullptr, timeoutCallback,
595 flushRequest.deadlineTimestamp - now);
596
597 if (!mPlatformBle.flushAsync()) {
598 LOGE("Could not request flush from BLE platform");
599 errorCode = CHRE_ERROR;
600 EventLoopManagerSingleton::get()->cancelDelayedCallback(
601 mFlushRequestTimerHandle);
602 mFlushRequestTimerHandle = CHRE_TIMER_INVALID;
603 } else {
604 flushRequest.isActive = true;
605 }
606 }
607 return errorCode;
608 }
609
sendFlushCompleteEventOrDie(const FlushRequest & flushRequest,uint8_t errorCode)610 void BleRequestManager::sendFlushCompleteEventOrDie(
611 const FlushRequest &flushRequest, uint8_t errorCode) {
612 chreAsyncResult *event = memoryAlloc<chreAsyncResult>();
613 if (event == nullptr) {
614 FATAL_ERROR("Unable to allocate chreAsyncResult");
615 }
616
617 event->requestType = CHRE_BLE_REQUEST_TYPE_FLUSH;
618 event->success = errorCode == CHRE_ERROR_NONE;
619 event->errorCode = errorCode;
620 event->reserved = 0;
621 event->cookie = flushRequest.cookie;
622 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
623 CHRE_EVENT_BLE_FLUSH_COMPLETE, event, freeEventDataCallback,
624 flushRequest.nanoappInstanceId);
625 }
626
processFlushRequests()627 bool BleRequestManager::processFlushRequests() {
628 while (!mFlushRequestQueue.empty()) {
629 uint8_t errorCode = doFlushRequest();
630 if (errorCode == CHRE_ERROR_NONE) {
631 return true;
632 }
633
634 sendFlushCompleteEventOrDie(mFlushRequestQueue.front(), errorCode);
635 mFlushRequestQueue.pop();
636 }
637 return false;
638 }
639
validateParams(const BleRequest & request)640 bool BleRequestManager::validateParams(const BleRequest &request) {
641 if (request.isEnabled()) {
642 for (const chreBleGenericFilter &filter : request.getGenericFilters()) {
643 if (!isValidAdType(filter.type)) return false;
644 if (filter.len == 0 || filter.len > CHRE_BLE_DATA_LEN_MAX) return false;
645 // Check that the filter is not matching against masked-out data.
646 for (int i = 0; i < filter.len; ++i) {
647 if (filter.data[i] & ~filter.dataMask[i]) return false;
648 }
649 }
650 }
651 return true;
652 }
653
postAsyncResultEventFatal(uint16_t instanceId,uint8_t requestType,bool success,uint8_t errorCode,const void * cookie)654 void BleRequestManager::postAsyncResultEventFatal(uint16_t instanceId,
655 uint8_t requestType,
656 bool success,
657 uint8_t errorCode,
658 const void *cookie) {
659 chreAsyncResult *event = memoryAlloc<chreAsyncResult>();
660 if (event == nullptr) {
661 FATAL_ERROR("Failed to alloc BLE async result");
662 } else {
663 event->requestType = requestType;
664 event->success = success;
665 event->errorCode = errorCode;
666 event->cookie = cookie;
667 event->reserved = 0;
668
669 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
670 CHRE_EVENT_BLE_ASYNC_RESULT, event, freeEventDataCallback, instanceId);
671 }
672 }
673
isValidAdType(uint8_t adType)674 bool BleRequestManager::isValidAdType(uint8_t adType) {
675 return adType == CHRE_BLE_AD_TYPE_SERVICE_DATA_WITH_UUID_16_LE ||
676 adType == CHRE_BLE_AD_TYPE_MANUFACTURER_DATA;
677 }
678
bleSettingEnabled()679 bool BleRequestManager::bleSettingEnabled() {
680 return EventLoopManagerSingleton::get()
681 ->getSettingManager()
682 .getSettingEnabled(Setting::BLE_AVAILABLE);
683 }
684
logStateToBuffer(DebugDumpWrapper & debugDump) const685 void BleRequestManager::logStateToBuffer(DebugDumpWrapper &debugDump) const {
686 debugDump.print("\nBLE:\n");
687 debugDump.print(" Active Platform Request:\n");
688 mActivePlatformRequest.logStateToBuffer(debugDump,
689 true /* isPlatformRequest */);
690 if (mPlatformRequestInProgress) {
691 debugDump.print(" Pending Platform Request:\n");
692 mPendingPlatformRequest.logStateToBuffer(debugDump,
693 true /* isPlatformRequest */);
694 }
695 debugDump.print(" Request Multiplexer:\n");
696 for (const BleRequest &req : mRequests.getRequests()) {
697 req.logStateToBuffer(debugDump);
698 }
699 debugDump.print(" Last %zu valid BLE requests:\n", mBleRequestLogs.size());
700 static_assert(kNumBleRequestLogs <= INT8_MAX,
701 "kNumBleRequestLogs must be less than INT8_MAX.");
702 for (int8_t i = static_cast<int8_t>(mBleRequestLogs.size()) - 1; i >= 0;
703 i--) {
704 const auto &log = mBleRequestLogs[static_cast<size_t>(i)];
705 debugDump.print(" ts=%" PRIu64 " instanceId=%" PRIu32 " %s",
706 log.timestamp.toRawNanoseconds(), log.instanceId,
707 log.enable ? "enable" : "disable\n");
708 if (log.enable && log.compliesWithBleSetting) {
709 debugDump.print(
710 " mode=%" PRIu8 " reportDelayMs=%" PRIu32 " rssiThreshold=%" PRId8
711 " scanCount=%" PRIu8 " broadcasterAddressCount=%" PRIu8 "\n",
712 static_cast<uint8_t>(log.mode), log.reportDelayMs, log.rssiThreshold,
713 log.scanFilterCount, log.broadcasterFilterCount);
714 } else if (log.enable) {
715 debugDump.print(" request did not comply with BLE setting\n");
716 }
717 }
718 }
719
720 } // namespace chre
721
722 #endif // CHRE_BLE_SUPPORT_ENABLED
723