• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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