1 /*
2  * Copyright (C) 2016 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/sensor_request_manager.h"
18 
19 #include "chre_api/chre/version.h"
20 #include "chre/core/event_loop_manager.h"
21 #include "chre/platform/fatal_error.h"
22 #include "chre/platform/shared/platform_sensor_util.h"
23 #include "chre/util/nested_data_ptr.h"
24 #include "chre/util/system/debug_dump.h"
25 
26 #define LOG_INVALID_SENSOR(x) \
27     LOGE("Invalid sensor type %" PRIu8 ": line %d", \
28          static_cast<uint8_t>(x), __LINE__)
29 
30 namespace chre {
31 namespace {
32 
isSensorRequestValid(const Sensor & sensor,const SensorRequest & sensorRequest)33 bool isSensorRequestValid(const Sensor& sensor,
34                           const SensorRequest& sensorRequest) {
35   bool isRequestContinuous = sensorModeIsContinuous(
36       sensorRequest.getMode());
37   bool isRequestOneShot = sensorModeIsOneShot(sensorRequest.getMode());
38   uint64_t requestedInterval = sensorRequest.getInterval().toRawNanoseconds();
39   SensorType sensorType = sensor.getSensorType();
40 
41   bool success = true;
42   if (requestedInterval < sensor.getMinInterval()) {
43     success = false;
44     LOGE("Requested interval %" PRIu64 " < sensor's minInterval %" PRIu64,
45          requestedInterval, sensor.getMinInterval());
46   } else if (isRequestContinuous) {
47     if (sensorTypeIsOneShot(sensorType)) {
48       success = false;
49       LOGE("Invalid continuous request for a one-shot sensor.");
50     }
51   } else if (isRequestOneShot) {
52     if (!sensorTypeIsOneShot(sensorType)) {
53       success = false;
54       LOGE("Invalid one-shot request for a continuous sensor.");
55     }
56   }
57   return success;
58 }
59 
60 }  // namespace
61 
SensorRequestManager()62 SensorRequestManager::SensorRequestManager() {
63   mSensorRequests.resize(mSensorRequests.capacity());
64 }
65 
~SensorRequestManager()66 SensorRequestManager::~SensorRequestManager() {
67   for (size_t i = 0; i < mSensorRequests.size(); i++) {
68     // Disable sensors that have been enabled previously.
69     if (mSensorRequests[i].isSensorSupported()) {
70       mSensorRequests[i].removeAll();
71     }
72   }
73 
74   PlatformSensor::deinit();
75 }
76 
init()77 void SensorRequestManager::init() {
78   // The Platform sensor must be initialized prior to interacting with any
79   // sensors.
80   PlatformSensor::init();
81 
82   DynamicVector<Sensor> sensors;
83   sensors.reserve(8);  // Avoid some initial reallocation churn
84   if (!PlatformSensor::getSensors(&sensors)) {
85     LOGE("Failed to query the platform for sensors");
86   } else if (sensors.empty()) {
87     LOGW("Platform returned zero sensors");
88   } else {
89     for (size_t i = 0; i < sensors.size(); i++) {
90       SensorType sensorType = sensors[i].getSensorType();
91       size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
92 
93       if (!isValidSensorType(sensorType)) {
94         LOG_INVALID_SENSOR(sensorType);
95       } else if (sensors[i].getMinInterval() == 0) {
96         LOGE("Invalid sensor minInterval: %s", getSensorTypeName(sensorType));
97       } else {
98         mSensorRequests[sensorIndex].setSensor(std::move(sensors[i]));
99         LOGD("Found sensor: %s", getSensorTypeName(sensorType));
100       }
101     }
102   }
103 }
104 
getSensorHandle(SensorType sensorType,uint32_t * sensorHandle) const105 bool SensorRequestManager::getSensorHandle(SensorType sensorType,
106                                            uint32_t *sensorHandle) const {
107   CHRE_ASSERT(sensorHandle);
108 
109   bool sensorHandleIsValid = false;
110   if (!isValidSensorType(sensorType)) {
111     LOG_INVALID_SENSOR(sensorType);
112   } else {
113     size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
114     sensorHandleIsValid = mSensorRequests[sensorIndex].isSensorSupported();
115     if (sensorHandleIsValid) {
116       *sensorHandle = getSensorHandleFromSensorType(sensorType);
117     }
118   }
119 
120   return sensorHandleIsValid;
121 }
122 
setSensorRequest(Nanoapp * nanoapp,uint32_t sensorHandle,const SensorRequest & sensorRequest)123 bool SensorRequestManager::setSensorRequest(Nanoapp *nanoapp,
124     uint32_t sensorHandle, const SensorRequest& sensorRequest) {
125   CHRE_ASSERT(nanoapp);
126 
127   // Validate the input to ensure that a valid handle has been provided.
128   SensorType sensorType = getSensorTypeFromSensorHandle(sensorHandle);
129   if (!isValidSensorType(sensorType)) {
130     LOG_INVALID_SENSOR(sensorType);
131     return false;
132   }
133 
134   // Ensure that the runtime is aware of this sensor type.
135   size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
136   SensorRequests& requests = mSensorRequests[sensorIndex];
137   if (!requests.isSensorSupported()) {
138     LOGW("Attempting to configure non-existent sensor");
139     return false;
140   }
141 
142   const Sensor& sensor = requests.getSensor();
143   if (!isSensorRequestValid(sensor, sensorRequest)) {
144     return false;
145   }
146 
147   size_t requestIndex;
148   uint16_t eventType = getSampleEventTypeForSensorType(sensorType);
149   bool nanoappHasRequest = (requests.find(nanoapp->getInstanceId(),
150                                           &requestIndex) != nullptr);
151 
152   bool success;
153   bool requestChanged;
154   if (sensorRequest.getMode() == SensorMode::Off) {
155     if (nanoappHasRequest) {
156       // The request changes the mode to off and there was an existing request.
157       // The existing request is removed from the multiplexer. The nanoapp is
158       // unregistered from events of this type if this request was successful.
159       success = requests.remove(requestIndex, &requestChanged);
160       if (success) {
161         cancelFlushRequests(sensorType, nanoapp->getInstanceId());
162 
163         nanoapp->unregisterForBroadcastEvent(eventType);
164 
165         uint16_t biasEventType;
166         if (getSensorBiasEventType(sensorType, &biasEventType)) {
167           // Per API requirements, turn off bias reporting when unsubscribing
168           // from the sensor.
169           nanoapp->unregisterForBroadcastEvent(biasEventType);
170         }
171       }
172     } else {
173       // The sensor is being configured to Off, but is already Off (there is no
174       // existing request). We assign to success to be true and no other
175       // operation is required.
176       requestChanged = false;
177       success = true;
178     }
179   } else if (!nanoappHasRequest) {
180     // The request changes the mode to the enabled state and there was no
181     // existing request. The request is newly created and added to the
182     // multiplexer. The nanoapp is registered for events if this request was
183     // successful.
184     success = requests.add(sensorRequest, &requestChanged);
185     if (success) {
186       nanoapp->registerForBroadcastEvent(eventType);
187 
188       // Per API requirements, turn on bias reporting for calibrated sensors
189       // by default when subscribed.
190       uint16_t biasEventType;
191       if (getSensorBiasEventType(sensorType, &biasEventType)
192           && sensorTypeIsCalibrated(sensorType)) {
193         nanoapp->registerForBroadcastEvent(biasEventType);
194       }
195 
196       // Deliver last valid event to new clients of on-change sensors
197       if (sensorTypeIsOnChange(sensor.getSensorType()) &&
198           sensor.getLastEvent() != nullptr) {
199         EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
200             getSampleEventTypeForSensorType(sensorType), sensor.getLastEvent(),
201             nullptr, nanoapp->getInstanceId());
202       }
203     }
204   } else {
205     // The request changes the mode to the enabled state and there was an
206     // existing request. The existing request is updated.
207     success = requests.update(requestIndex, sensorRequest, &requestChanged);
208   }
209 
210   if (requestChanged) {
211     // TODO: Send an event to nanoapps to indicate the rate change.
212   }
213 
214   return success;
215 }
216 
getSensorInfo(uint32_t sensorHandle,const Nanoapp & nanoapp,struct chreSensorInfo * info) const217 bool SensorRequestManager::getSensorInfo(uint32_t sensorHandle,
218                                          const Nanoapp& nanoapp,
219                                          struct chreSensorInfo *info) const {
220   CHRE_ASSERT(info);
221 
222   bool success = false;
223 
224   // Validate the input to ensure that a valid handle has been provided.
225   SensorType sensorType = getSensorTypeFromSensorHandle(sensorHandle);
226   if (!isValidSensorType(sensorType)) {
227     LOG_INVALID_SENSOR(sensorType);
228   } else {
229     size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
230     if (!mSensorRequests[sensorIndex].isSensorSupported()) {
231       LOGW("Attempting to get sensor info for unsupported sensor handle %"
232            PRIu32, sensorHandle);
233     } else {
234       // Platform-independent properties.
235       info->sensorType = getUnsignedIntFromSensorType(sensorType);
236       info->isOnChange = sensorTypeIsOnChange(sensorType);
237       info->isOneShot  = sensorTypeIsOneShot(sensorType);
238       info->reportsBiasEvents = sensorTypeReportsBias(sensorType);
239       info->unusedFlags = 0;
240 
241       // Platform-specific properties.
242       const Sensor& sensor = mSensorRequests[sensorIndex].getSensor();
243       info->sensorName = sensor.getSensorName();
244 
245       // minInterval was added in CHRE API v1.1 - do not attempt to populate for
246       // nanoapps targeting v1.0 as their struct will not be large enough
247       if (nanoapp.getTargetApiVersion() >= CHRE_API_VERSION_1_1) {
248         info->minInterval = sensor.getMinInterval();
249       }
250 
251       success = true;
252     }
253   }
254 
255   return success;
256 }
257 
removeAllRequests(SensorType sensorType)258 bool SensorRequestManager::removeAllRequests(SensorType sensorType) {
259   bool success = false;
260   if (!isValidSensorType(sensorType)) {
261     LOG_INVALID_SENSOR(sensorType);
262   } else {
263     size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
264     SensorRequests& requests = mSensorRequests[sensorIndex];
265     uint16_t eventType = getSampleEventTypeForSensorType(sensorType);
266 
267     for (const SensorRequest& request : requests.getRequests()) {
268       Nanoapp *nanoapp = EventLoopManagerSingleton::get()->getEventLoop()
269           .findNanoappByInstanceId(request.getInstanceId());
270       if (nanoapp != nullptr) {
271         nanoapp->unregisterForBroadcastEvent(eventType);
272       }
273     }
274 
275     cancelFlushRequests(sensorType);
276     success = requests.removeAll();
277   }
278   return success;
279 }
280 
getSensor(SensorType sensorType)281 Sensor *SensorRequestManager::getSensor(SensorType sensorType) {
282   Sensor *sensorPtr = nullptr;
283   if (!isValidSensorType(sensorType)) {
284     LOG_INVALID_SENSOR(sensorType);
285   } else {
286     size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
287     if (mSensorRequests[sensorIndex].isSensorSupported()) {
288       sensorPtr = &mSensorRequests[sensorIndex].getSensor();
289     }
290   }
291   return sensorPtr;
292 }
293 
getSensorSamplingStatus(uint32_t sensorHandle,struct chreSensorSamplingStatus * status) const294 bool SensorRequestManager::getSensorSamplingStatus(
295     uint32_t sensorHandle, struct chreSensorSamplingStatus *status) const {
296   CHRE_ASSERT(status);
297 
298   bool success = false;
299   SensorType sensorType = getSensorTypeFromSensorHandle(sensorHandle);
300   if (!isValidSensorType(sensorType)) {
301     LOG_INVALID_SENSOR(sensorType);
302   } else {
303     size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
304     if (mSensorRequests[sensorIndex].isSensorSupported()) {
305       success = mSensorRequests[sensorIndex].getSamplingStatus(status);
306     }
307   }
308   return success;
309 }
310 
getRequests(SensorType sensorType) const311 const DynamicVector<SensorRequest>& SensorRequestManager::getRequests(
312     SensorType sensorType) const {
313   size_t sensorIndex = 0;
314   if (!isValidSensorType(sensorType)) {
315     LOG_INVALID_SENSOR(sensorType);
316   } else {
317     sensorIndex = getSensorTypeArrayIndex(sensorType);
318   }
319   return mSensorRequests[sensorIndex].getRequests();
320 }
321 
configureBiasEvents(Nanoapp * nanoapp,uint32_t sensorHandle,bool enable)322 bool SensorRequestManager::configureBiasEvents(
323       Nanoapp *nanoapp, uint32_t sensorHandle, bool enable) {
324   bool success = false;
325   uint16_t eventType;
326   SensorType sensorType = getSensorTypeFromSensorHandle(sensorHandle);
327   if (getSensorBiasEventType(sensorType, &eventType)) {
328     if (enable) {
329       nanoapp->registerForBroadcastEvent(eventType);
330     } else {
331       nanoapp->unregisterForBroadcastEvent(eventType);
332     }
333 
334     success = true;
335   }
336 
337   return success;
338 }
339 
getThreeAxisBias(uint32_t sensorHandle,struct chreSensorThreeAxisData * bias) const340 bool SensorRequestManager::getThreeAxisBias(
341     uint32_t sensorHandle, struct chreSensorThreeAxisData *bias) const {
342   CHRE_ASSERT(bias != nullptr);
343 
344   bool success = false;
345   if (bias != nullptr) {
346     SensorType sensorType = getSensorTypeFromSensorHandle(sensorHandle);
347     if (!isValidSensorType(sensorType)) {
348       LOG_INVALID_SENSOR(sensorType);
349     } else {
350       size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
351       if (mSensorRequests[sensorIndex].isSensorSupported()) {
352         success = mSensorRequests[sensorIndex].getThreeAxisBias(bias);
353       }
354     }
355   }
356 
357   return success;
358 }
359 
flushAsync(Nanoapp * nanoapp,uint32_t sensorHandle,const void * cookie)360 bool SensorRequestManager::flushAsync(
361     Nanoapp *nanoapp, uint32_t sensorHandle, const void *cookie) {
362   bool success = false;
363 
364   uint32_t nanoappInstanceId = nanoapp->getInstanceId();
365   SensorType sensorType = getSensorTypeFromSensorHandle(sensorHandle);
366   // NOTE: One-shot sensors do not support flush per API
367   if (!isValidSensorType(sensorType) || sensorTypeIsOneShot(sensorType)) {
368     LOGE("Cannot flush for sensor type %" PRIu32,
369          static_cast<uint32_t>(sensorType));
370   } else if (mFlushRequestQueue.full()) {
371     LOG_OOM();
372   } else {
373     mFlushRequestQueue.emplace_back(sensorType, nanoappInstanceId, cookie);
374     size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
375     success = (mSensorRequests[sensorIndex].makeFlushRequest(
376         mFlushRequestQueue.back()) == CHRE_ERROR_NONE);
377     if (!success) {
378       mFlushRequestQueue.pop_back();
379     }
380   }
381 
382   return success;
383 }
384 
handleFlushCompleteEvent(uint8_t errorCode,SensorType sensorType)385 void SensorRequestManager::handleFlushCompleteEvent(
386     uint8_t errorCode, SensorType sensorType) {
387   size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
388   if (isValidSensorType(sensorType)
389       && mSensorRequests[sensorIndex].isFlushRequestPending()) {
390 
391     // Cancel flush request timer before posting to the event queue to ensure
392     // a timeout event isn't processed by CHRE now that the complete event
393     // has been received.
394     mSensorRequests[sensorIndex].cancelPendingFlushRequestTimer();
395 
396     struct CallbackState {
397       uint8_t errorCode;
398       SensorType sensorType;
399     };
400 
401     NestedDataPtr<CallbackState> state = {};
402     state.data.errorCode = errorCode;
403     state.data.sensorType = sensorType;
404 
405     auto callback = [](uint16_t /* eventType */, void *eventData) {
406       NestedDataPtr<CallbackState> nestedState;
407       nestedState.dataPtr = eventData;
408       EventLoopManagerSingleton::get()->getSensorRequestManager()
409           .handleFlushCompleteEventSync(nestedState.data.errorCode,
410                                         nestedState.data.sensorType);
411     };
412 
413     EventLoopManagerSingleton::get()->deferCallback(
414         SystemCallbackType::SensorFlushComplete, state.dataPtr, callback);
415   }
416 }
417 
handleSensorEvent(SensorType sensorType,void * event)418 void SensorRequestManager::handleSensorEvent(SensorType sensorType,
419                                              void *event) {
420   uint16_t eventType = getSampleEventTypeForSensorType(sensorType);
421   // Only allow dropping continuous sensor events since losing one-shot or
422   // on-change events could result in nanoapps stuck in a bad state.
423   if (sensorTypeIsContinuous(sensorType)) {
424     EventLoopManagerSingleton::get()->getEventLoop().postLowPriorityEventOrFree(
425         eventType, event, sensorDataEventFree);
426   } else {
427     EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
428         eventType, event, sensorDataEventFree);
429   }
430 }
431 
logStateToBuffer(char * buffer,size_t * bufferPos,size_t bufferSize) const432 void SensorRequestManager::logStateToBuffer(char *buffer, size_t *bufferPos,
433                                             size_t bufferSize) const {
434   debugDumpPrint(buffer, bufferPos, bufferSize, "\nSensors:\n");
435   for (uint8_t i = 0; i < static_cast<uint8_t>(SensorType::SENSOR_TYPE_COUNT);
436        i++) {
437     SensorType sensor = static_cast<SensorType>(i);
438     if (isValidSensorType(sensor)) {
439       for (const auto& request : getRequests(sensor)) {
440         debugDumpPrint(buffer, bufferPos, bufferSize, " %s: mode=%d"
441                        " interval(ns)=%" PRIu64 " latency(ns)=%"
442                        PRIu64 " nanoappId=%" PRIu32 "\n",
443                        getSensorTypeName(sensor), request.getMode(),
444                        request.getInterval().toRawNanoseconds(),
445                        request.getLatency().toRawNanoseconds(),
446                        request.getInstanceId());
447       }
448     }
449   }
450 }
451 
postFlushCompleteEvent(uint32_t sensorHandle,uint8_t errorCode,const FlushRequest & request)452 void SensorRequestManager::postFlushCompleteEvent(
453     uint32_t sensorHandle, uint8_t errorCode, const FlushRequest& request) {
454   auto *event = memoryAlloc<chreSensorFlushCompleteEvent>();
455   if (event == nullptr) {
456     LOG_OOM();
457   } else {
458     event->sensorHandle = sensorHandle;
459     event->errorCode = errorCode;
460     event->cookie = request.cookie;
461     memset(event->reserved, 0, sizeof(event->reserved));
462 
463     EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
464         CHRE_EVENT_SENSOR_FLUSH_COMPLETE, event, freeEventDataCallback,
465         request.nanoappInstanceId);
466   }
467 }
468 
completeFlushRequestAtIndex(size_t index,uint8_t errorCode)469 void SensorRequestManager::completeFlushRequestAtIndex(
470     size_t index, uint8_t errorCode) {
471   if (index < mFlushRequestQueue.size()) {
472     const FlushRequest& request = mFlushRequestQueue[index];
473     SensorType sensorType = request.sensorType;
474     if (request.isActive) {
475       SensorRequests& requests = getSensorRequests(sensorType);
476       requests.clearPendingFlushRequest();
477     }
478 
479     uint32_t sensorHandle;
480     if (getSensorHandle(sensorType, &sensorHandle)) {
481       postFlushCompleteEvent(sensorHandle, errorCode, request);
482     }
483     mFlushRequestQueue.erase(index);
484   }
485 }
486 
dispatchNextFlushRequest(SensorType sensorType)487 void SensorRequestManager::dispatchNextFlushRequest(SensorType sensorType) {
488   SensorRequests& requests = getSensorRequests(sensorType);
489 
490   for (size_t i = 0; i < mFlushRequestQueue.size(); i++) {
491     FlushRequest& request = mFlushRequestQueue[i];
492     if (request.sensorType == sensorType) {
493       uint8_t newRequestErrorCode = requests.makeFlushRequest(request);
494       if (newRequestErrorCode == CHRE_ERROR_NONE) {
495         break;
496       } else {
497         completeFlushRequestAtIndex(i,  newRequestErrorCode);
498         i--;
499       }
500     }
501   }
502 }
503 
handleFlushCompleteEventSync(uint8_t errorCode,SensorType sensorType)504 void SensorRequestManager::handleFlushCompleteEventSync(
505     uint8_t errorCode, SensorType sensorType) {
506   for (size_t i = 0; i < mFlushRequestQueue.size(); i++) {
507     if (mFlushRequestQueue[i].sensorType == sensorType) {
508       completeFlushRequestAtIndex(i, errorCode);
509       dispatchNextFlushRequest(sensorType);
510       break;
511     }
512   }
513 }
514 
cancelFlushRequests(SensorType sensorType,uint32_t nanoappInstanceId)515 void SensorRequestManager::cancelFlushRequests(
516     SensorType sensorType, uint32_t nanoappInstanceId) {
517   bool removeAll = (nanoappInstanceId == kSystemInstanceId);
518   for (size_t i = 0; i < mFlushRequestQueue.size(); i++) {
519     const FlushRequest& request = mFlushRequestQueue[i];
520     if (request.sensorType == sensorType &&
521         (request.nanoappInstanceId == nanoappInstanceId || removeAll)) {
522       completeFlushRequestAtIndex(
523           i, CHRE_ERROR_FUNCTION_DISABLED /* errorCode */);
524       i--;
525     }
526   }
527 
528   SensorRequests& requests = getSensorRequests(sensorType);
529   if (!requests.isFlushRequestPending()) {
530     dispatchNextFlushRequest(sensorType);
531   }
532 }
533 
find(uint32_t instanceId,size_t * index) const534 const SensorRequest *SensorRequestManager::SensorRequests::find(
535     uint32_t instanceId, size_t *index) const {
536   CHRE_ASSERT(index);
537 
538   const auto& requests = mMultiplexer.getRequests();
539   for (size_t i = 0; i < requests.size(); i++) {
540     const SensorRequest& sensorRequest = requests[i];
541     if (sensorRequest.getInstanceId() == instanceId) {
542       *index = i;
543       return &sensorRequest;
544     }
545   }
546 
547   return nullptr;
548 }
549 
add(const SensorRequest & request,bool * requestChanged)550 bool SensorRequestManager::SensorRequests::add(const SensorRequest& request,
551                                                bool *requestChanged) {
552   CHRE_ASSERT(requestChanged != nullptr);
553   CHRE_ASSERT(isSensorSupported());
554 
555   size_t addIndex;
556   bool success = true;
557   if (!mMultiplexer.addRequest(request, &addIndex, requestChanged)) {
558     *requestChanged = false;
559     success = false;
560     LOG_OOM();
561   } else if (*requestChanged) {
562     success = mSensor->setRequest(mMultiplexer.getCurrentMaximalRequest());
563     if (!success) {
564       // Remove the newly added request since the platform failed to handle it.
565       // The sensor is expected to maintain the existing request so there is no
566       // need to reset the platform to the last maximal request.
567       mMultiplexer.removeRequest(addIndex, requestChanged);
568 
569       // This is a roll-back operation so the maximal change in the multiplexer
570       // must not have changed. The request changed state is forced to false.
571       *requestChanged = false;
572     }
573   }
574 
575   return success;
576 }
577 
remove(size_t removeIndex,bool * requestChanged)578 bool SensorRequestManager::SensorRequests::remove(size_t removeIndex,
579                                                   bool *requestChanged) {
580   CHRE_ASSERT(requestChanged != nullptr);
581   CHRE_ASSERT(isSensorSupported());
582 
583   bool success = true;
584   mMultiplexer.removeRequest(removeIndex, requestChanged);
585   if (*requestChanged) {
586     success = mSensor->setRequest(mMultiplexer.getCurrentMaximalRequest());
587     if (!success) {
588       LOGE("SensorRequestManager failed to remove a request");
589 
590       // If the platform fails to handle this request in a debug build there is
591       // likely an error in the platform. This is not strictly a programming
592       // error but it does make sense to use assert semantics when a platform
593       // fails to handle a request that it had been sent previously.
594       CHRE_ASSERT(false);
595 
596       // The request to the platform to set a request when removing has failed
597       // so the request has not changed.
598       *requestChanged = false;
599     }
600   }
601 
602   return success;
603 }
604 
update(size_t updateIndex,const SensorRequest & request,bool * requestChanged)605 bool SensorRequestManager::SensorRequests::update(size_t updateIndex,
606                                                   const SensorRequest& request,
607                                                   bool *requestChanged) {
608   CHRE_ASSERT(requestChanged != nullptr);
609   CHRE_ASSERT(isSensorSupported());
610 
611   bool success = true;
612   SensorRequest previousRequest = mMultiplexer.getRequests()[updateIndex];
613   mMultiplexer.updateRequest(updateIndex, request, requestChanged);
614   if (*requestChanged) {
615     success = mSensor->setRequest(mMultiplexer.getCurrentMaximalRequest());
616     if (!success) {
617       // Roll back the request since sending it to the sensor failed. The
618       // request will roll back to the previous maximal. The sensor is
619       // expected to maintain the existing request if a request fails so there
620       // is no need to reset the platform to the last maximal request.
621       mMultiplexer.updateRequest(updateIndex, previousRequest, requestChanged);
622 
623       // This is a roll-back operation so the maximal change in the multiplexer
624       // must not have changed. The request changed state is forced to false.
625       *requestChanged = false;
626     }
627   }
628 
629   return success;
630 }
631 
removeAll()632 bool SensorRequestManager::SensorRequests::removeAll() {
633   CHRE_ASSERT(isSensorSupported());
634 
635   bool requestChanged;
636   mMultiplexer.removeAllRequests(&requestChanged);
637 
638   bool success = true;
639   if (requestChanged) {
640     SensorRequest maximalRequest = mMultiplexer.getCurrentMaximalRequest();
641     success = mSensor->setRequest(maximalRequest);
642     if (!success) {
643       LOGE("SensorRequestManager failed to remove all request");
644 
645       // If the platform fails to handle this request in a debug build there is
646       // likely an error in the platform. This is not strictly a programming
647       // error but it does make sense to use assert semantics when a platform
648       // fails to handle a request that it had been sent previously.
649       CHRE_ASSERT(false);
650     }
651   }
652   return success;
653 }
654 
makeFlushRequest(FlushRequest & request)655 uint8_t SensorRequestManager::SensorRequests::makeFlushRequest(
656     FlushRequest& request) {
657   uint8_t errorCode = CHRE_ERROR;
658   if (!isSensorSupported()) {
659     LOGE("Cannot flush on unsupported sensor");
660   } else if (mMultiplexer.getRequests().size() == 0) {
661     LOGE("Cannot flush on disabled sensor");
662   } else if (!isFlushRequestPending()) {
663     Nanoseconds now = SystemTime::getMonotonicTime();
664     Nanoseconds deadline = request.deadlineTimestamp;
665     if (now >= deadline) {
666       LOGE("Flush sensor %" PRIu32 " failed for nanoapp ID %" PRIu32
667            ": deadline exceeded", static_cast<uint32_t>(request.sensorType),
668            request.nanoappInstanceId);
669       errorCode = CHRE_ERROR_TIMEOUT;
670     } else if (doMakeFlushRequest()) {
671       errorCode = CHRE_ERROR_NONE;
672       Nanoseconds delay = deadline - now;
673       request.isActive = true;
674 
675       NestedDataPtr<SensorType> nestedType = {};
676       nestedType.data = request.sensorType;
677 
678       auto callback = [](uint16_t /* eventType */, void * eventData) {
679         LOGE("Flush request timed out.");
680         NestedDataPtr<SensorType> nestedType;
681         nestedType.dataPtr = eventData;
682         // Send a complete event, thus closing out this flush request. If the
683         // request that has just timed out receives a response later, this may
684         // inadvertently close out a new request before it has actually
685         // completed.
686         // TODO: Attach an ID to all flush requests / responses so stale
687         // responses can be properly dropped.
688         EventLoopManagerSingleton::get()->getSensorRequestManager()
689             .handleFlushCompleteEventSync(CHRE_ERROR_TIMEOUT,
690                                           nestedType.data);
691       };
692 
693       mFlushRequestTimerHandle =
694           EventLoopManagerSingleton::get()->setDelayedCallback(
695               SystemCallbackType::SensorFlushTimeout, nestedType.dataPtr,
696               callback, delay);
697     }
698   } else {
699     // Flush request will be made once the pending request is completed.
700     // Return true so that the nanoapp can wait for a result through the
701     // CHRE_EVENT_SENSOR_FLUSH_COMPLETE event.
702     errorCode = CHRE_ERROR_NONE;
703   }
704 
705   return errorCode;
706 }
707 
clearPendingFlushRequest()708 void SensorRequestManager::SensorRequests::clearPendingFlushRequest() {
709   cancelPendingFlushRequestTimer();
710   mFlushRequestPending = false;
711 }
712 
cancelPendingFlushRequestTimer()713 void SensorRequestManager::SensorRequests::cancelPendingFlushRequestTimer() {
714   if (mFlushRequestTimerHandle != CHRE_TIMER_INVALID) {
715     EventLoopManagerSingleton::get()->cancelDelayedCallback(
716         mFlushRequestTimerHandle);
717     mFlushRequestTimerHandle = CHRE_TIMER_INVALID;
718   }
719 }
720 
doMakeFlushRequest()721 bool SensorRequestManager::SensorRequests::doMakeFlushRequest() {
722   // Set to true before making the request since it's a synchronous request
723   // and we may get the complete event before it returns.
724   mFlushRequestPending = true;
725   mFlushRequestPending = mSensor->flushAsync();
726   return mFlushRequestPending;
727 }
728 
729 }  // namespace chre
730