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 #include "chre/core/ble_request_manager.h"
18
19 #include "chre/core/event_loop_manager.h"
20 #include "chre/platform/fatal_error.h"
21 #include "chre/platform/log.h"
22 #include "chre/util/fixed_size_vector.h"
23 #include "chre/util/nested_data_ptr.h"
24 #include "chre/util/system/ble_util.h"
25 #include "chre/util/system/event_callbacks.h"
26
27 namespace chre {
28
init()29 void BleRequestManager::init() {
30 mPlatformBle.init();
31 }
32
getCapabilities()33 uint32_t BleRequestManager::getCapabilities() {
34 return mPlatformBle.getCapabilities();
35 }
36
getFilterCapabilities()37 uint32_t BleRequestManager::getFilterCapabilities() {
38 return mPlatformBle.getFilterCapabilities();
39 }
40
handleExistingRequest(uint16_t instanceId,bool * hasExistingRequest,size_t * requestIndex)41 void BleRequestManager::handleExistingRequest(uint16_t instanceId,
42 bool *hasExistingRequest,
43 size_t *requestIndex) {
44 const BleRequest *foundRequest =
45 mRequests.findRequest(instanceId, requestIndex);
46 *hasExistingRequest = (foundRequest != nullptr);
47 if (foundRequest != nullptr &&
48 foundRequest->getRequestStatus() != RequestStatus::APPLIED) {
49 handleAsyncResult(instanceId, foundRequest->isEnabled(),
50 false /* success */, CHRE_ERROR_OBSOLETE_REQUEST,
51 foundRequest->getCookie(), true /* forceUnregister */);
52 }
53 }
54
compliesWithBleSetting(uint16_t instanceId,bool enabled,bool hasExistingRequest,size_t requestIndex,const void * cookie)55 bool BleRequestManager::compliesWithBleSetting(uint16_t instanceId,
56 bool enabled,
57 bool hasExistingRequest,
58 size_t requestIndex,
59 const void *cookie) {
60 bool success = true;
61 if (enabled && !bleSettingEnabled()) {
62 success = false;
63 handleAsyncResult(instanceId, enabled, false /* success */,
64 CHRE_ERROR_FUNCTION_DISABLED, cookie);
65 if (hasExistingRequest) {
66 bool requestChanged = false;
67 mRequests.removeRequest(requestIndex, &requestChanged);
68 }
69 }
70 return success;
71 }
72
updateRequests(BleRequest && request,bool hasExistingRequest,bool * requestChanged,size_t * requestIndex)73 bool BleRequestManager::updateRequests(BleRequest &&request,
74 bool hasExistingRequest,
75 bool *requestChanged,
76 size_t *requestIndex) {
77 bool success = true;
78 if (hasExistingRequest) {
79 mRequests.updateRequest(*requestIndex, std::move(request), requestChanged);
80 } else if (request.isEnabled()) {
81 success =
82 mRequests.addRequest(std::move(request), requestIndex, requestChanged);
83 } else {
84 // Already disabled requests shouldn't result in work for the PAL.
85 *requestChanged = false;
86 *requestIndex = mRequests.getRequests().size();
87 }
88 return success;
89 }
90
startScanAsync(Nanoapp * nanoapp,chreBleScanMode mode,uint32_t reportDelayMs,const struct chreBleScanFilterV1_9 * filter,const void * cookie)91 bool BleRequestManager::startScanAsync(
92 Nanoapp *nanoapp, chreBleScanMode mode, uint32_t reportDelayMs,
93 const struct chreBleScanFilterV1_9 *filter, const void *cookie) {
94 CHRE_ASSERT(nanoapp);
95 BleRequest request(nanoapp->getInstanceId(), true /* enable */, mode,
96 reportDelayMs, filter, cookie);
97 return configure(std::move(request));
98 }
99
stopScanAsync(Nanoapp * nanoapp,const void * cookie)100 bool BleRequestManager::stopScanAsync(Nanoapp *nanoapp, const void *cookie) {
101 CHRE_ASSERT(nanoapp);
102 BleRequest request(nanoapp->getInstanceId(), false /* enable */, cookie);
103 return configure(std::move(request));
104 }
105
disableActiveScan(const Nanoapp * nanoapp)106 uint32_t BleRequestManager::disableActiveScan(const Nanoapp *nanoapp) {
107 CHRE_ASSERT(nanoapp);
108
109 size_t requestIndex;
110 const BleRequest *foundRequest =
111 mRequests.findRequest(nanoapp->getInstanceId(), &requestIndex);
112
113 if (foundRequest == nullptr || !foundRequest->isEnabled()) {
114 // No active request found.
115 return 0;
116 }
117
118 BleRequest request(nanoapp->getInstanceId(), false /* enable */,
119 nullptr /* cookie */);
120 configure(std::move(request));
121 return 1;
122 }
123
124 #ifdef CHRE_BLE_READ_RSSI_SUPPORT_ENABLED
readRssiAsync(Nanoapp * nanoapp,uint16_t connectionHandle,const void * cookie)125 bool BleRequestManager::readRssiAsync(Nanoapp *nanoapp,
126 uint16_t connectionHandle,
127 const void *cookie) {
128 CHRE_ASSERT(nanoapp);
129 if (mPendingRssiRequests.full()) {
130 LOG_OOM();
131 return false;
132 }
133 if (mPendingRssiRequests.empty()) {
134 // no previous request existed, so issue this one immediately to get
135 // an early exit if we get a failure
136 auto status = readRssi(connectionHandle);
137 if (status != CHRE_ERROR_NONE) {
138 return false;
139 }
140 }
141 // it's pending, so report the result asynchronously
142 mPendingRssiRequests.push(
143 BleReadRssiRequest{nanoapp->getInstanceId(), connectionHandle, cookie});
144 return true;
145 }
146 #endif
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
407 #ifdef CHRE_BLE_READ_RSSI_SUPPORT_ENABLED
handleReadRssi(uint8_t errorCode,uint16_t connectionHandle,int8_t rssi)408 void BleRequestManager::handleReadRssi(uint8_t errorCode,
409 uint16_t connectionHandle, int8_t rssi) {
410 struct readRssiResponse {
411 uint8_t errorCode;
412 int8_t rssi;
413 uint16_t connectionHandle;
414 };
415
416 auto callback = [](uint16_t /* eventType */, void *eventData,
417 void * /* extraData */) {
418 readRssiResponse response = NestedDataPtr<readRssiResponse>(eventData);
419 EventLoopManagerSingleton::get()->getBleRequestManager().handleReadRssiSync(
420 response.errorCode, response.connectionHandle, response.rssi);
421 };
422
423 EventLoopManagerSingleton::get()->deferCallback(
424 SystemCallbackType::BleReadRssiEvent,
425 NestedDataPtr<readRssiResponse>(
426 readRssiResponse{errorCode, rssi, connectionHandle}),
427 callback);
428 }
429
handleReadRssiSync(uint8_t errorCode,uint16_t connectionHandle,int8_t rssi)430 void BleRequestManager::handleReadRssiSync(uint8_t errorCode,
431 uint16_t connectionHandle,
432 int8_t rssi) {
433 if (mPendingRssiRequests.empty()) {
434 FATAL_ERROR(
435 "Got unexpected handleReadRssi event without outstanding request");
436 }
437
438 if (mPendingRssiRequests.front().connectionHandle != connectionHandle) {
439 FATAL_ERROR(
440 "Got readRssi event for mismatched connection handle (%d != %d)",
441 mPendingRssiRequests.front().connectionHandle, connectionHandle);
442 }
443
444 resolvePendingRssiRequest(errorCode, rssi);
445 dispatchNextRssiRequestIfAny();
446 }
447
resolvePendingRssiRequest(uint8_t errorCode,int8_t rssi)448 void BleRequestManager::resolvePendingRssiRequest(uint8_t errorCode,
449 int8_t rssi) {
450 auto event = memoryAlloc<chreBleReadRssiEvent>();
451 if (event == nullptr) {
452 FATAL_ERROR("Failed to alloc BLE async result");
453 }
454
455 event->result.cookie = mPendingRssiRequests.front().cookie;
456 event->result.success = (errorCode == CHRE_ERROR_NONE);
457 event->result.requestType = CHRE_BLE_REQUEST_TYPE_READ_RSSI;
458 event->result.errorCode = errorCode;
459 event->result.reserved = 0;
460 event->connectionHandle = mPendingRssiRequests.front().connectionHandle;
461 event->rssi = rssi;
462
463 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
464 CHRE_EVENT_BLE_RSSI_READ, event, freeEventDataCallback,
465 mPendingRssiRequests.front().instanceId);
466
467 mPendingRssiRequests.pop();
468 }
469
dispatchNextRssiRequestIfAny()470 void BleRequestManager::dispatchNextRssiRequestIfAny() {
471 while (!mPendingRssiRequests.empty()) {
472 auto req = mPendingRssiRequests.front();
473 auto status = readRssi(req.connectionHandle);
474 if (status == CHRE_ERROR_NONE) {
475 // control flow resumes in the handleReadRssi() callback, on completion
476 return;
477 }
478 resolvePendingRssiRequest(status, 0x7F /* failure RSSI from BT spec */);
479 }
480 }
481
readRssi(uint16_t connectionHandle)482 uint8_t BleRequestManager::readRssi(uint16_t connectionHandle) {
483 if (!bleSettingEnabled()) {
484 return CHRE_ERROR_FUNCTION_DISABLED;
485 }
486 auto success = mPlatformBle.readRssiAsync(connectionHandle);
487 if (success) {
488 return CHRE_ERROR_NONE;
489 } else {
490 return CHRE_ERROR;
491 }
492 }
493 #endif
494
handleFlushComplete(uint8_t errorCode)495 void BleRequestManager::handleFlushComplete(uint8_t errorCode) {
496 if (mFlushRequestTimerHandle != CHRE_TIMER_INVALID) {
497 EventLoopManagerSingleton::get()->cancelDelayedCallback(
498 mFlushRequestTimerHandle);
499 mFlushRequestTimerHandle = CHRE_TIMER_INVALID;
500 }
501
502 handleFlushCompleteInternal(errorCode);
503 }
504
handleFlushCompleteTimeout()505 void BleRequestManager::handleFlushCompleteTimeout() {
506 mFlushRequestTimerHandle = CHRE_TIMER_INVALID;
507 handleFlushCompleteInternal(CHRE_ERROR_TIMEOUT);
508 }
509
getScanStatus(struct chreBleScanStatus *)510 bool BleRequestManager::getScanStatus(struct chreBleScanStatus * /* status */) {
511 // TODO(b/266820139): Implement this
512 return false;
513 }
514
onSettingChanged(Setting setting,bool)515 void BleRequestManager::onSettingChanged(Setting setting, bool /* state */) {
516 if (setting == Setting::BLE_AVAILABLE) {
517 if (mPlatformRequestInProgress) {
518 mSettingChangePending = true;
519 } else {
520 updatePlatformRequest();
521 }
522 }
523 }
524
updatePlatformRequest(bool forceUpdate)525 void BleRequestManager::updatePlatformRequest(bool forceUpdate) {
526 bool desiredPlatformState =
527 bleSettingEnabled() && mRequests.isMaximalRequestEnabled();
528 bool updatePlatform = (forceUpdate || (desiredPlatformState !=
529 mActivePlatformRequest.isEnabled()));
530
531 if (updatePlatform) {
532 if (controlPlatform()) {
533 addBleRequestLog(CHRE_INSTANCE_ID, desiredPlatformState,
534 mRequests.getRequests().size(),
535 true /* compliesWithBleSetting */);
536 } else {
537 FATAL_ERROR("Failed to send update BLE platform request");
538 }
539 }
540 }
541
handleFlushCompleteInternal(uint8_t errorCode)542 void BleRequestManager::handleFlushCompleteInternal(uint8_t errorCode) {
543 auto callback = [](uint16_t /* type */, void *data, void * /* extraData */) {
544 uint8_t cbErrorCode = NestedDataPtr<uint8_t>(data);
545 EventLoopManagerSingleton::get()
546 ->getBleRequestManager()
547 .handleFlushCompleteSync(cbErrorCode);
548 };
549
550 if (!EventLoopManagerSingleton::get()->deferCallback(
551 SystemCallbackType::BleFlushComplete,
552 NestedDataPtr<uint8_t>(errorCode), callback)) {
553 FATAL_ERROR("Unable to defer flush complete callback");
554 }
555 }
556
handleFlushCompleteSync(uint8_t errorCode)557 void BleRequestManager::handleFlushCompleteSync(uint8_t errorCode) {
558 if (mFlushRequestQueue.empty() || !mFlushRequestQueue.front().isActive) {
559 LOGE(
560 "handleFlushCompleteSync was called, but there is no active flush "
561 "request");
562 return;
563 }
564
565 FlushRequest &flushRequest = mFlushRequestQueue.front();
566 sendFlushCompleteEventOrDie(flushRequest, errorCode);
567 mFlushRequestQueue.pop();
568
569 processFlushRequests();
570 }
571
doFlushRequest()572 uint8_t BleRequestManager::doFlushRequest() {
573 CHRE_ASSERT(!mFlushRequestQueue.empty());
574
575 FlushRequest &flushRequest = mFlushRequestQueue.front();
576 if (flushRequest.isActive) {
577 return CHRE_ERROR_NONE;
578 }
579
580 Nanoseconds now = SystemTime::getMonotonicTime();
581 uint8_t errorCode = CHRE_ERROR_NONE;
582 if (now >= flushRequest.deadlineTimestamp) {
583 LOGE("BLE flush request for nanoapp with instance ID: %" PRIu16
584 " failed: deadline exceeded",
585 flushRequest.nanoappInstanceId);
586 errorCode = CHRE_ERROR_TIMEOUT;
587 } else {
588 auto timeoutCallback = [](uint16_t /* type */, void * /* data */,
589 void * /* extraData */) {
590 EventLoopManagerSingleton::get()
591 ->getBleRequestManager()
592 .handleFlushCompleteTimeout();
593 };
594 mFlushRequestTimerHandle =
595 EventLoopManagerSingleton::get()->setDelayedCallback(
596 SystemCallbackType::BleFlushTimeout, nullptr, timeoutCallback,
597 flushRequest.deadlineTimestamp - now);
598
599 if (!mPlatformBle.flushAsync()) {
600 LOGE("Could not request flush from BLE platform");
601 errorCode = CHRE_ERROR;
602 EventLoopManagerSingleton::get()->cancelDelayedCallback(
603 mFlushRequestTimerHandle);
604 mFlushRequestTimerHandle = CHRE_TIMER_INVALID;
605 } else {
606 flushRequest.isActive = true;
607 }
608 }
609 return errorCode;
610 }
611
sendFlushCompleteEventOrDie(const FlushRequest & flushRequest,uint8_t errorCode)612 void BleRequestManager::sendFlushCompleteEventOrDie(
613 const FlushRequest &flushRequest, uint8_t errorCode) {
614 chreAsyncResult *event = memoryAlloc<chreAsyncResult>();
615 if (event == nullptr) {
616 FATAL_ERROR("Unable to allocate chreAsyncResult");
617 }
618
619 event->requestType = CHRE_BLE_REQUEST_TYPE_FLUSH;
620 event->success = errorCode == CHRE_ERROR_NONE;
621 event->errorCode = errorCode;
622 event->reserved = 0;
623 event->cookie = flushRequest.cookie;
624 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
625 CHRE_EVENT_BLE_FLUSH_COMPLETE, event, freeEventDataCallback,
626 flushRequest.nanoappInstanceId);
627 }
628
processFlushRequests()629 bool BleRequestManager::processFlushRequests() {
630 while (!mFlushRequestQueue.empty()) {
631 uint8_t errorCode = doFlushRequest();
632 if (errorCode == CHRE_ERROR_NONE) {
633 return true;
634 }
635
636 sendFlushCompleteEventOrDie(mFlushRequestQueue.front(), errorCode);
637 mFlushRequestQueue.pop();
638 }
639 return false;
640 }
641
validateParams(const BleRequest & request)642 bool BleRequestManager::validateParams(const BleRequest &request) {
643 if (request.isEnabled()) {
644 for (const chreBleGenericFilter &filter : request.getGenericFilters()) {
645 if (!isValidAdType(filter.type)) return false;
646 if (filter.len == 0 || filter.len > CHRE_BLE_DATA_LEN_MAX) return false;
647 // Check that the filter is not matching against masked-out data.
648 for (int i = 0; i < filter.len; ++i) {
649 if (filter.data[i] & ~filter.dataMask[i]) return false;
650 }
651 }
652 }
653 return true;
654 }
655
postAsyncResultEventFatal(uint16_t instanceId,uint8_t requestType,bool success,uint8_t errorCode,const void * cookie)656 void BleRequestManager::postAsyncResultEventFatal(uint16_t instanceId,
657 uint8_t requestType,
658 bool success,
659 uint8_t errorCode,
660 const void *cookie) {
661 chreAsyncResult *event = memoryAlloc<chreAsyncResult>();
662 if (event == nullptr) {
663 FATAL_ERROR("Failed to alloc BLE async result");
664 } else {
665 event->requestType = requestType;
666 event->success = success;
667 event->errorCode = errorCode;
668 event->cookie = cookie;
669 event->reserved = 0;
670
671 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
672 CHRE_EVENT_BLE_ASYNC_RESULT, event, freeEventDataCallback, instanceId);
673 }
674 }
675
isValidAdType(uint8_t adType)676 bool BleRequestManager::isValidAdType(uint8_t adType) {
677 return adType == CHRE_BLE_AD_TYPE_SERVICE_DATA_WITH_UUID_16_LE ||
678 adType == CHRE_BLE_AD_TYPE_MANUFACTURER_DATA;
679 }
680
bleSettingEnabled()681 bool BleRequestManager::bleSettingEnabled() {
682 return EventLoopManagerSingleton::get()
683 ->getSettingManager()
684 .getSettingEnabled(Setting::BLE_AVAILABLE);
685 }
686
logStateToBuffer(DebugDumpWrapper & debugDump) const687 void BleRequestManager::logStateToBuffer(DebugDumpWrapper &debugDump) const {
688 debugDump.print("\nBLE:\n");
689 debugDump.print(" Active Platform Request:\n");
690 mActivePlatformRequest.logStateToBuffer(debugDump,
691 true /* isPlatformRequest */);
692 if (mPlatformRequestInProgress) {
693 debugDump.print(" Pending Platform Request:\n");
694 mPendingPlatformRequest.logStateToBuffer(debugDump,
695 true /* isPlatformRequest */);
696 }
697 debugDump.print(" Request Multiplexer:\n");
698 for (const BleRequest &req : mRequests.getRequests()) {
699 req.logStateToBuffer(debugDump);
700 }
701 debugDump.print(" Last %zu valid BLE requests:\n", mBleRequestLogs.size());
702 static_assert(kNumBleRequestLogs <= INT8_MAX,
703 "kNumBleRequestLogs must be less than INT8_MAX.");
704 for (int8_t i = static_cast<int8_t>(mBleRequestLogs.size()) - 1; i >= 0;
705 i--) {
706 const auto &log = mBleRequestLogs[static_cast<size_t>(i)];
707 debugDump.print(" ts=%" PRIu64 " instanceId=%" PRIu32 " %s",
708 log.timestamp.toRawNanoseconds(), log.instanceId,
709 log.enable ? "enable" : "disable\n");
710 if (log.enable && log.compliesWithBleSetting) {
711 debugDump.print(
712 " mode=%" PRIu8 " reportDelayMs=%" PRIu32 " rssiThreshold=%" PRId8
713 " scanCount=%" PRIu8 " broadcasterAddressCount=%" PRIu8 "\n",
714 static_cast<uint8_t>(log.mode), log.reportDelayMs, log.rssiThreshold,
715 log.scanFilterCount, log.broadcasterFilterCount);
716 } else if (log.enable) {
717 debugDump.print(" request did not comply with BLE setting\n");
718 }
719 }
720 }
721
722 } // namespace chre
723