xref: /aosp_15_r20/system/chre/core/ble_request_manager.cc (revision 84e339476a462649f82315436d70fd732297a399)
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