• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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/platform/platform_sensor.h"
18 
19 #include "sns_std_sensor.pb.h"
20 #include "stringl.h"
21 
22 #include <cmath>
23 
24 #include "chre_api/chre/sensor.h"
25 #include "chre/core/event_loop_manager.h"
26 #include "chre/core/sensor.h"
27 #include "chre/platform/assert.h"
28 #include "chre/platform/fatal_error.h"
29 #include "chre/platform/log.h"
30 #include "chre/platform/shared/platform_sensor_util.h"
31 #include "chre/platform/slpi/power_control_util.h"
32 #include "chre/platform/slpi/see/see_client.h"
33 #include "chre/platform/slpi/see/see_helper.h"
34 #include "chre/platform/system_time.h"
35 
36 #ifdef CHREX_SENSOR_SUPPORT
37 #include "chre/extensions/platform/slpi/see/vendor_data_types.h"
38 #endif  // CHREX_SENSOR_SUPPORT
39 
40 #ifdef CHRE_VARIANT_SUPPLIES_SEE_SENSORS_LIST
41 #include "see_sensors.h"
42 #endif  // CHRE_VARIANT_SUPPLIES_SEE_SENSORS_LIST
43 
44 #ifndef CHRE_SEE_NUM_TEMP_SENSORS
45 // There are usually more than one 'sensor_temperature' sensors in SEE.
46 // Define this in the variant-specific makefile to avoid missing sensors in
47 // sensor discovery.
48 #error "CHRE_SEE_NUM_TEMP_SENSORS is not defined"
49 #endif
50 
51 namespace chre {
52 namespace {
53 
54 #ifdef CHRE_SLPI_UIMG_ENABLED
55 #ifndef CHREX_SENSOR_SUPPORT
56 // The current implementation uses vendor sensor type 3 to remap into accel,
57 // with requests made through QMI instead of QSockets, as SEE does not support
58 // micro-image batching in QCM.
59 #error "CHRE extensions are required for micro-image SEE support"
60 #endif  // CHREX_SENSOR_SUPPORT
61 
isBigImageSensorType(SensorType sensorType)62 bool isBigImageSensorType(SensorType sensorType) {
63   return (sensorType == SensorType::VendorType3       // accel
64           || sensorType == SensorType::VendorType6    // uncal accel
65           || sensorType == SensorType::VendorType7    // uncal gyro
66           || sensorType == SensorType::VendorType8);  // uncal mag
67 }
68 
69 /**
70  * Obtains the big-image sensor type given the specified data type and whether
71  * the sensor is runtime-calibrated or not.
72  */
getBigImageSensorTypeFromDataType(const char * dataType,bool calibrated)73 SensorType getBigImageSensorTypeFromDataType(const char *dataType,
74                                              bool calibrated) {
75   SensorType sensorType = SensorType::Unknown;
76   if (strcmp(dataType, "accel") == 0) {
77     if (calibrated) {
78       sensorType = SensorType::VendorType3;
79     } else {
80       sensorType = SensorType::VendorType6;
81     }
82   } else if (strcmp(dataType, "gyro") == 0 && !calibrated) {
83     sensorType = SensorType::VendorType7;
84   } else if (strcmp(dataType, "mag") == 0 && !calibrated) {
85     sensorType = SensorType::VendorType8;
86   }
87   return sensorType;
88 }
89 
90 /**
91  * Obtains the micro-image sensor type given the specified sensor type.
92  *
93  * @param sensorType The sensor type to convert from.
94  * @return The associated micro-image sensor type, or the input sensor type
95  *     if not associated with one
96  */
getUimgSensorType(SensorType sensorType)97 SensorType getUimgSensorType(SensorType sensorType) {
98   switch (sensorType) {
99     case SensorType::VendorType3:
100       return SensorType::Accelerometer;
101     case SensorType::VendorType6:
102       return SensorType::UncalibratedAccelerometer;
103     case SensorType::VendorType7:
104       return SensorType::UncalibratedGyroscope;
105     case SensorType::VendorType8:
106       return SensorType::UncalibratedGeomagneticField;
107     default:
108       return sensorType;
109   }
110 }
111 #endif  // CHRE_SLPI_UIMG_ENABLED
112 
113 //! A class that implements SeeHelperCallbackInterface.
114 class SeeHelperCallback : public SeeHelperCallbackInterface {
115   void onSamplingStatusUpdate(
116       UniquePtr<SeeHelperCallbackInterface::SamplingStatusData>&& status)
117       override;
118 
119   void onSensorDataEvent(
120       SensorType sensorType, UniquePtr<uint8_t>&& eventData) override;
121 
122   void onHostWakeSuspendEvent(bool awake) override;
123 
124   void onSensorBiasEvent(UniquePtr<struct chreSensorThreeAxisData>&& biasData)
125       override;
126 
127   void onFlushCompleteEvent(SensorType sensorType) override;
128 };
129 
130 //! A struct to facilitate sensor discovery
131 struct SuidAttr {
132   sns_std_suid suid;
133   SeeAttributes attr;
134 };
135 
136 #ifndef CHRE_VARIANT_SUPPLIES_SEE_SENSORS_LIST
137 
138 //! The list of SEE platform sensor data types that CHRE intends to support.
139 //! The standardized strings are defined in sns_xxx.proto.
140 const char *kSeeDataTypes[] = {
141   "accel",
142   "gyro",
143   "mag",
144   "pressure",
145   "ambient_light",
146   "proximity",
147   "motion_detect",
148   "stationary_detect",
149 };
150 
151 #endif  // CHRE_VARIANT_SUPPLIES_SEE_SENSORS_LIST
152 
handleMissingSensor()153 void handleMissingSensor() {
154   // Try rebooting if a sensor is missing, which might help recover from a
155   // transient failure/race condition at startup. But to avoid endless crashes,
156   // only do this within the first 45 seconds after boot - we rely on knowledge
157   // that getMonotonicTime() maps into QTimer here, and QTimer only resets when
158   // the entire system is rebooted (it continues increasing after SLPI SSR).
159 #ifndef CHRE_LOG_ONLY_NO_SENSOR
160   if (SystemTime::getMonotonicTime() < Seconds(45)) {
161     FATAL_ERROR("Missing required sensor(s)");
162   } else
163 #endif
164   {
165     LOGE("Missing required sensor(s)");
166   }
167 }
168 
169 /**
170  * Obtains the sensor type given the specified data type and whether the sensor
171  * is runtime-calibrated or not.
172  */
getSensorTypeFromDataType(const char * dataType,bool calibrated)173 SensorType getSensorTypeFromDataType(const char *dataType, bool calibrated) {
174   SensorType sensorType;
175   if (strcmp(dataType, "accel") == 0) {
176     if (calibrated) {
177       sensorType = SensorType::Accelerometer;
178     } else {
179       sensorType = SensorType::UncalibratedAccelerometer;
180     }
181   } else if (strcmp(dataType, "gyro") == 0) {
182     if (calibrated) {
183       sensorType = SensorType::Gyroscope;
184     } else {
185       sensorType = SensorType::UncalibratedGyroscope;
186     }
187   } else if (strcmp(dataType, "mag") == 0) {
188     if (calibrated) {
189       sensorType = SensorType::GeomagneticField;
190     } else {
191       sensorType = SensorType::UncalibratedGeomagneticField;
192     }
193   } else if (strcmp(dataType, "pressure") == 0) {
194     sensorType = SensorType::Pressure;
195   } else if (strcmp(dataType, "ambient_light") == 0) {
196     sensorType = SensorType::Light;
197   } else if (strcmp(dataType, "proximity") == 0) {
198     sensorType = SensorType::Proximity;
199   } else if (strcmp(dataType, "motion_detect") == 0) {
200     sensorType = SensorType::InstantMotion;
201   } else if (strcmp(dataType, "stationary_detect") == 0) {
202     sensorType = SensorType::StationaryDetect;
203   } else if (strcmp(dataType, "step_detect") == 0) {
204     sensorType = SensorType::StepDetect;
205 #ifdef CHREX_SENSOR_SUPPORT
206   } else if (strcmp(dataType, kVendorDataTypes[0]) == 0) {
207     sensorType = SensorType::VendorType0;
208 #endif  // CHREX_SENSOR_SUPPORT
209   } else {
210     sensorType = SensorType::Unknown;
211   }
212   return sensorType;
213 }
214 
seeSensorDataEventFree(uint16_t eventType,void * eventData)215 void seeSensorDataEventFree(uint16_t eventType, void *eventData) {
216   memoryFree(eventData);
217 
218   // Remove all requests if it's a one-shot sensor and only after data has been
219   // delivered to all clients.
220   SensorType sensorType = getSensorTypeForSampleEventType(eventType);
221   if (sensorTypeIsOneShot(sensorType)) {
222     EventLoopManagerSingleton::get()->getSensorRequestManager()
223         .removeAllRequests(sensorType);
224   }
225 }
226 
227 /**
228  * Posts a CHRE_EVENT_SENSOR_SAMPLING_CHANGE event to the specified Nanoapp.
229  *
230  * @param instaceId The instance ID of the nanoapp with an open request.
231  * @param sensorHandle The handle of the sensor.
232  * @param status A reference of the sampling status to be posted.
233  */
postSamplingStatusEvent(uint32_t instanceId,uint32_t sensorHandle,const struct chreSensorSamplingStatus & status)234 void postSamplingStatusEvent(uint32_t instanceId, uint32_t sensorHandle,
235                              const struct chreSensorSamplingStatus& status) {
236   auto *event = memoryAlloc<struct chreSensorSamplingStatusEvent>();
237   if (event == nullptr) {
238     LOG_OOM();
239   } else {
240     event->sensorHandle = sensorHandle;
241     event->status = status;
242 
243     EventLoopManagerSingleton::get()->getEventLoop().postEventOrFree(
244         CHRE_EVENT_SENSOR_SAMPLING_CHANGE, event, freeEventDataCallback,
245         kSystemInstanceId, instanceId);
246   }
247 }
248 
249 /**
250  * Helper function to post a bias event given the bias data.
251  *
252  * @param sensorType The sensor type to post the event for.
253  * @param bias The bias data.
254  */
postSensorBiasEvent(SensorType sensorType,const chreSensorThreeAxisData & bias)255 void postSensorBiasEvent(SensorType sensorType,
256                          const chreSensorThreeAxisData& bias) {
257   uint16_t eventType;
258   if (getSensorBiasEventType(sensorType, &eventType)) {
259     auto *event = memoryAlloc<struct chreSensorThreeAxisData>();
260     if (event == nullptr) {
261       LOG_OOM();
262     } else {
263       *event = bias;
264       event->header.sensorHandle = getSensorHandleFromSensorType(sensorType);
265       EventLoopManagerSingleton::get()->getEventLoop().postEventOrFree(
266           eventType, event, freeEventDataCallback);
267     }
268   }
269 }
270 
271 /**
272  * Updates the sampling status.
273  */
updateSamplingStatus(const SeeHelperCallbackInterface::SamplingStatusData & update)274 void updateSamplingStatus(
275     const SeeHelperCallbackInterface::SamplingStatusData& update) {
276   Sensor *sensor = EventLoopManagerSingleton::get()->getSensorRequestManager()
277       .getSensor(update.sensorType);
278   struct chreSensorSamplingStatus prevStatus;
279 
280   if (sensor != nullptr && !sensorTypeIsOneShot(update.sensorType)
281       && sensor->getSamplingStatus(&prevStatus)) {
282     struct chreSensorSamplingStatus newStatus = prevStatus;
283 
284     if (update.enabledValid) {
285       newStatus.enabled = update.status.enabled;
286     }
287     if (update.intervalValid) {
288       newStatus.interval = update.status.interval;
289     }
290     if (update.latencyValid) {
291       newStatus.latency = update.status.latency;
292     }
293 
294     if (newStatus.enabled != prevStatus.enabled ||
295         (newStatus.enabled && (newStatus.interval != prevStatus.interval
296                                || newStatus.latency != prevStatus.latency))) {
297       sensor->setSamplingStatus(newStatus);
298 
299       // Only post to Nanoapps with an open request.
300       uint32_t sensorHandle = getSensorHandleFromSensorType(update.sensorType);
301       const DynamicVector<SensorRequest>& requests =
302           EventLoopManagerSingleton::get()->getSensorRequestManager()
303           .getRequests(update.sensorType);
304       for (const auto& req : requests) {
305         postSamplingStatusEvent(req.getInstanceId(), sensorHandle, newStatus);
306       }
307     }
308   }
309 }
310 
onSamplingStatusUpdate(UniquePtr<SeeHelperCallbackInterface::SamplingStatusData> && status)311 void SeeHelperCallback::onSamplingStatusUpdate(
312     UniquePtr<SeeHelperCallbackInterface::SamplingStatusData>&& status) {
313   auto callback = [](uint16_t /* type */, void *data) {
314     auto cbData = UniquePtr<SeeHelperCallbackInterface::SamplingStatusData>(
315         static_cast<SeeHelperCallbackInterface::SamplingStatusData *>(data));
316     updateSamplingStatus(*cbData);
317   };
318 
319   // Schedule a deferred callback to handle sensor status change in the main
320   // thread.
321   EventLoopManagerSingleton::get()->deferCallback(
322       SystemCallbackType::SensorStatusUpdate, status.release(), callback);
323 }
324 
onSensorDataEvent(SensorType sensorType,UniquePtr<uint8_t> && eventData)325 void SeeHelperCallback::onSensorDataEvent(
326     SensorType sensorType, UniquePtr<uint8_t>&& eventData) {
327   // Schedule a deferred callback to update on-change sensor's last event in
328   // the main thread.
329   if (sensorTypeIsOnChange(sensorType)) {
330     updateLastEvent(sensorType, eventData.get());
331   }
332 
333   uint16_t eventType = getSampleEventTypeForSensorType(sensorType);
334   EventLoopManagerSingleton::get()->getEventLoop().postEventOrFree(
335       eventType, eventData.get(), seeSensorDataEventFree);
336   eventData.release();
337 }
338 
onHostWakeSuspendEvent(bool awake)339 void SeeHelperCallback::onHostWakeSuspendEvent(bool awake) {
340   if (EventLoopManagerSingleton::isInitialized()) {
341     EventLoopManagerSingleton::get()->getEventLoop()
342         .getPowerControlManager().onHostWakeSuspendEvent(awake);
343   }
344 }
345 
onSensorBiasEvent(UniquePtr<struct chreSensorThreeAxisData> && biasData)346 void SeeHelperCallback::onSensorBiasEvent(
347     UniquePtr<struct chreSensorThreeAxisData>&& biasData) {
348   SensorType sensorType = getSensorTypeFromSensorHandle(
349       biasData->header.sensorHandle);
350 
351   uint16_t eventType;
352   if (!sensorTypeIsCalibrated(sensorType) ||
353       !getSensorBiasEventType(sensorType, &eventType)) {
354     LOGE("Received bias event for unsupported sensor type %" PRIu8, sensorType);
355   } else {
356     // Posts a newly allocated event for the uncalibrated type
357     postSensorBiasEvent(toUncalibratedSensorType(sensorType), *biasData.get());
358 
359     EventLoopManagerSingleton::get()->getEventLoop().postEventOrFree(
360         eventType, biasData.release(), freeEventDataCallback);
361   }
362 }
363 
onFlushCompleteEvent(SensorType sensorType)364 void SeeHelperCallback::onFlushCompleteEvent(SensorType sensorType) {
365   if (EventLoopManagerSingleton::isInitialized()) {
366     EventLoopManagerSingleton::get()->getSensorRequestManager()
367         .handleFlushCompleteEvent(CHRE_ERROR_NONE, sensorType);
368   }
369 }
370 
371 /**
372  * Allocates memory and specifies the memory size for an on-change sensor to
373  * store its last data event.
374  *
375  * @param sensorType The sensorType of this sensor.
376  * @param eventSize A non-null pointer to indicate the memory size allocated.
377  * @return Pointer to the memory allocated.
378  */
allocateLastEvent(SensorType sensorType,size_t * eventSize)379 ChreSensorData *allocateLastEvent(SensorType sensorType, size_t *eventSize) {
380   CHRE_ASSERT(eventSize);
381 
382   *eventSize = 0;
383   ChreSensorData *event = nullptr;
384   if (sensorTypeIsOnChange(sensorType)) {
385     SensorSampleType sampleType = getSensorSampleTypeFromSensorType(sensorType);
386     switch (sampleType) {
387       case SensorSampleType::ThreeAxis:
388         *eventSize = sizeof(chreSensorThreeAxisData);
389         break;
390       case SensorSampleType::Float:
391         *eventSize = sizeof(chreSensorFloatData);
392         break;
393       case SensorSampleType::Byte:
394         *eventSize = sizeof(chreSensorByteData);
395         break;
396       case SensorSampleType::Occurrence:
397         *eventSize = sizeof(chreSensorOccurrenceData);
398         break;
399       default:
400         CHRE_ASSERT_LOG(false, "Unhandled sample type");
401         break;
402     }
403 
404     event = static_cast<ChreSensorData *>(memoryAlloc(*eventSize));
405     if (event == nullptr) {
406       *eventSize = 0;
407       FATAL_ERROR("Failed to allocate last event memory for SensorType %" PRIu8,
408                   static_cast<uint8_t>(sensorType));
409     }
410   }
411   return event;
412 }
413 
414 /**
415  * Constructs and initializes a sensor, and adds it to the sensor list.
416  *
417  * @param seeHelper SeeHelper instance to register sensor with
418  * @param suid The SUID of the sensor as provided by SEE.
419  * @param sensorType The sensor type of the sensor.
420  * @param calibrated Whether the sensor is runtime-calibrated or not.
421  * @param attr A reference to SeeAttrbutes.
422  * @param sensor The sensor list.
423  */
addSensor(SeeHelper & seeHelper,SensorType sensorType,const sns_std_suid & suid,const SeeAttributes & attr,DynamicVector<Sensor> * sensors)424 void addSensor(SeeHelper& seeHelper, SensorType sensorType,
425                const sns_std_suid& suid, const SeeAttributes& attr,
426                DynamicVector<Sensor> *sensors) {
427   // Concatenate vendor and name with a space in between.
428   char sensorName[kSensorNameMaxLen];
429   strlcpy(sensorName, attr.vendor, sizeof(sensorName));
430   strlcat(sensorName, " ", sizeof(sensorName));
431   strlcat(sensorName, attr.name, sizeof(sensorName));
432 
433   // Override one-shot sensor's minInterval to default
434   uint64_t minInterval = sensorTypeIsOneShot(sensorType) ?
435       CHRE_SENSOR_INTERVAL_DEFAULT : static_cast<uint64_t>(
436           ceilf(Seconds(1).toRawNanoseconds() / attr.maxSampleRate));
437 
438   // Allocates memory for on-change sensor's last event.
439   size_t lastEventSize;
440   ChreSensorData *lastEvent = allocateLastEvent(sensorType, &lastEventSize);
441 
442   // Constructs and initializes PlatformSensorBase.
443   Sensor sensor;
444   sensor.initBase(sensorType, minInterval, sensorName, lastEvent,
445                   lastEventSize, attr.passiveRequest);
446 
447   if (!sensors->push_back(std::move(sensor))) {
448     FATAL_ERROR("Failed to allocate new sensor: out of memory");
449   }
450 
451   // Resample big image sensors to reduce system load during sw flush.
452 #ifdef CHRE_SLPI_UIMG_ENABLED
453   bool resample = isBigImageSensorType(sensorType);
454 #else
455   bool resample = false;
456 #endif
457   bool prevRegistered;
458   bool registered = seeHelper.registerSensor(
459       sensorType, suid, resample, &prevRegistered);
460   if (!registered && prevRegistered) {
461     LOGW("SUID has been previously registered");
462   } else if (!registered) {
463     FATAL_ERROR("Failed to register SUID/SensorType mapping.");
464   }
465 }
466 
467 /**
468  * Compare SEE reported stream type attribute to the expected one. Some SEE
469  * sensors may support more than one stream type.
470  */
isStreamTypeCorrect(SensorType sensorType,uint8_t streamType)471 bool isStreamTypeCorrect(SensorType sensorType, uint8_t streamType) {
472   bool success = true;
473   if ((sensorTypeIsContinuous(sensorType)
474        && streamType != SNS_STD_SENSOR_STREAM_TYPE_STREAMING)
475       || (sensorTypeIsOnChange(sensorType)
476           && streamType != SNS_STD_SENSOR_STREAM_TYPE_ON_CHANGE)
477       || (sensorTypeIsOneShot(sensorType)
478           && streamType != SNS_STD_SENSOR_STREAM_TYPE_SINGLE_OUTPUT)) {
479     success = false;
480     LOGW("Inconsistent sensor type %" PRIu8 " and stream type %" PRIu8,
481          static_cast<uint8_t>(sensorType), streamType);
482   }
483   return success;
484 }
485 
486 /**
487  * Obtains the list of SUIDs and their attributes that support the specified
488  * data type.
489  */
getSuidAndAttrs(SeeHelper & seeHelper,const char * dataType,DynamicVector<SuidAttr> * suidAttrs,uint8_t minNumSuids)490 bool getSuidAndAttrs(SeeHelper& seeHelper, const char *dataType,
491                      DynamicVector<SuidAttr> *suidAttrs, uint8_t minNumSuids) {
492   DynamicVector<sns_std_suid> suids;
493   bool success = seeHelper.findSuidSync(dataType, &suids, minNumSuids);
494   if (!success) {
495     LOGE("Failed to find sensor '%s'", dataType);
496   } else {
497     LOGD("Num of SUIDs found for '%s': %zu", dataType, suids.size());
498 
499     for (const auto& suid : suids) {
500       SeeAttributes attr;
501       if (!seeHelper.getAttributesSync(suid, &attr)) {
502         success = false;
503         LOGE("Failed to get attributes of SUID 0x%" PRIx64 " %" PRIx64,
504              suid.suid_high, suid.suid_low);
505       } else {
506         LOGI("%s %s, hw id %" PRId64 ", max ODR %f Hz, stream type %" PRIu8
507              " passive %d",
508              attr.vendor, attr.name, attr.hwId, attr.maxSampleRate,
509              attr.streamType, attr.passiveRequest);
510         SuidAttr sensor = {
511           .suid = suid,
512           .attr = attr,
513         };
514         if (!suidAttrs->push_back(sensor)) {
515           success = false;
516           LOG_OOM();
517         }
518       }
519     }
520   }
521   return success;
522 }
523 
524 //! Check whether two sensors with the specified attrtibutes belong to the same
525 //! sensor hardware module.
sensorHwMatch(const SeeAttributes & attr0,const SeeAttributes & attr1)526 bool sensorHwMatch(const SeeAttributes& attr0, const SeeAttributes& attr1) {
527   // When HW ID is absent, it's default to 0 and won't be a factor.
528   return ((strncmp(attr0.vendor, attr1.vendor, kSeeAttrStrValLen) == 0)
529           && (strncmp(attr0.name, attr1.name, kSeeAttrStrValLen) == 0)
530           && (attr0.hwId == attr1.hwId));
531 }
532 
533 /**
534  * Looks up SUID(s) associated with a given sensor data type string and sensor
535  * type enum, registers them with SeeHelper, and adds a Sensor instance to the
536  * supplied vector for use in CHRE. When given an uncalibrated sensor type, will
537  * also look for and add the calibrated sensor type.
538  *
539  * @param seeHelper SeeHelper instance to use for lookup/registration
540  * @param temperatureSensors List of previously discovered temperature sensor
541  *        info to use for adding temp sensors associated with this sensor type
542  * @param dataType SEE data type string
543  * @param sensorType CHRE sensor type enum associated with dataType
544  * @param skipAdditionalTypes if true, don't attempt to add
545  *        calibrated/temperature sensor types associated with this sensorType
546  * @param sensors Vector to append found sensor(s) to
547  */
findAndAddSensorsForType(SeeHelper & seeHelper,const DynamicVector<SuidAttr> & temperatureSensors,const char * dataType,SensorType sensorType,bool skipAdditionalTypes,DynamicVector<Sensor> * sensors)548 void findAndAddSensorsForType(
549     SeeHelper& seeHelper, const DynamicVector<SuidAttr>& temperatureSensors,
550     const char *dataType, SensorType sensorType, bool skipAdditionalTypes,
551     DynamicVector<Sensor> *sensors) {
552   DynamicVector<SuidAttr> primarySensors;
553   if (!getSuidAndAttrs(seeHelper, dataType, &primarySensors,
554                        1 /* minNumSuids */)) {
555     handleMissingSensor();
556   }
557 
558   for (const auto& primarySensor : primarySensors) {
559     sns_std_suid suid = primarySensor.suid;
560     SeeAttributes attr = primarySensor.attr;
561 
562     // Some sensors support both continuous and on-change streams.
563     // If there are more than one SUIDs that support the data type,
564     // choose the first one that has the expected stream type.
565     if (isStreamTypeCorrect(sensorType, attr.streamType)) {
566       addSensor(seeHelper, sensorType, suid, attr, sensors);
567 
568       if (!skipAdditionalTypes) {
569         // Check if this sensor has a runtime-calibrated version.
570         SensorType calibratedType = getSensorTypeFromDataType(
571             dataType, true /* calibrated */);
572         if (calibratedType != sensorType) {
573           addSensor(seeHelper, calibratedType, suid, attr, sensors);
574         }
575 
576         // Check if this sensor has a secondary temperature sensor.
577         SensorType temperatureType = getTempSensorType(sensorType);
578         if (temperatureType != SensorType::Unknown) {
579           bool tempFound = false;
580           for (const auto& tempSensor : temperatureSensors) {
581             sns_std_suid tempSuid = tempSensor.suid;
582             SeeAttributes tempAttr = tempSensor.attr;
583 
584             if (sensorHwMatch(attr, tempAttr)) {
585               LOGD("Found matching temperature sensor type");
586               tempFound = true;
587               addSensor(seeHelper, temperatureType, tempSuid, tempAttr,
588                         sensors);
589               break;
590             }
591           }
592           if (!tempFound) {
593             LOGW("Temperature sensor type %" PRIu8 " not found!",
594                  static_cast<uint8_t>(temperatureType));
595           }
596         }
597       }
598       break;
599     }
600   }
601 }
602 
603 #ifdef CHRE_SLPI_UIMG_ENABLED
604 /**
605  * Registers alternate sensor(s) to be used separately by big image nanoapps.
606  */
getBigImageSensors(DynamicVector<Sensor> * sensors)607 void getBigImageSensors(DynamicVector<Sensor> *sensors) {
608   CHRE_ASSERT(sensors);
609 
610   // Currently, just adding calibrated accel and uncal accel/gyro/mag as they
611   // are the ones we know that big image nanoapps will need at a different
612   // batching rate compared to uimg.
613   const char *kBigImageDataTypes[] = {
614     "accel",
615     "gyro",
616     "mag",
617   };
618 
619   SeeHelper& seeHelper = *getBigImageSeeHelper();
620   DynamicVector<SuidAttr> nullTemperatureSensorList;
621 
622   for (size_t i = 0; i < ARRAY_SIZE(kBigImageDataTypes); i++) {
623     const char *dataType = kBigImageDataTypes[i];
624     // Loop through potential cal/uncal sensors.
625     for (size_t j = 0; j < 2; j++) {
626       SensorType sensorType = getBigImageSensorTypeFromDataType(
627           dataType, (j == 0) /* calibrated */);
628       if (sensorType != SensorType::Unknown) {
629         findAndAddSensorsForType(
630             seeHelper, nullTemperatureSensorList, dataType, sensorType,
631             true /* skipAdditionalTypes */, sensors);
632       }
633     }
634   }
635 }
636 #endif  // CHRE_SLPI_UIMG_ENABLED
637 
638 /**
639  * Helper function to retrieve the SeeHelper for a given sensor type.
640  * @param sensorType the sensor type
641  * @return the appropriate (bimg or uimg) SeeHelper
642  */
getSeeHelperForSensorType(SensorType sensorType)643 SeeHelper *getSeeHelperForSensorType(SensorType sensorType) {
644   SeeHelper *seeHelper = getSeeHelper();
645 #ifdef CHRE_SLPI_UIMG_ENABLED
646   if (isBigImageSensorType(sensorType)) {
647     seeHelper = getBigImageSeeHelper();
648     slpiForceBigImage();
649   }
650 #endif
651 
652   return seeHelper;
653 }
654 
655 
656 }  // anonymous namespace
657 
~PlatformSensor()658 PlatformSensor::~PlatformSensor() {
659   if (mLastEvent != nullptr) {
660     LOGD("Releasing lastEvent: sensor %s, size %zu",
661          getSensorTypeName(getSensorType()), mLastEventSize);
662     memoryFree(mLastEvent);
663   }
664 }
665 
init()666 void PlatformSensor::init() {
667   SeeHelperSingleton::init();
668 
669   static SeeHelperCallback seeHelperCallback;
670   if (!getSeeHelper()->init(&seeHelperCallback)) {
671     FATAL_ERROR("Failed to initialize SEE helper");
672   }
673 
674 #ifdef CHRE_SLPI_UIMG_ENABLED
675   BigImageSeeHelperSingleton::init(getSeeHelper()->getCalHelper());
676   if (!getBigImageSeeHelper()->init(&seeHelperCallback, kDefaultSeeWaitTimeout,
677                                     true /* skipDefaultSensorInit */)) {
678     FATAL_ERROR("Failed to init bimg SEE helper");
679   }
680 #endif  // CHRE_SLPI_UIMG_ENABLED
681 }
682 
deinit()683 void PlatformSensor::deinit() {
684 #ifdef CHRE_SLPI_UIMG_ENABLED
685   BigImageSeeHelperSingleton::deinit();
686 #endif
687 
688   SeeHelperSingleton::deinit();
689 }
690 
getSensors(DynamicVector<Sensor> * sensors)691 bool PlatformSensor::getSensors(DynamicVector<Sensor> *sensors) {
692   CHRE_ASSERT(sensors);
693 
694   SeeHelper& seeHelper = *getSeeHelper();
695   DynamicVector<SuidAttr> tempSensors;
696   if (!getSuidAndAttrs(seeHelper, "sensor_temperature", &tempSensors,
697                        CHRE_SEE_NUM_TEMP_SENSORS)) {
698     handleMissingSensor();
699   }
700 
701 #ifndef CHREX_SENSOR_SUPPORT
702   const char *kVendorDataTypes[] = {};
703 #endif  // CHREX_SENSOR_SUPPORT
704   constexpr size_t kNumSeeTypes = ARRAY_SIZE(kSeeDataTypes);
705   constexpr size_t kNumVendorTypes = ARRAY_SIZE(kVendorDataTypes);
706   for (size_t i = 0; i < kNumSeeTypes + kNumVendorTypes; i++) {
707     const char *dataType = (i < kNumSeeTypes)
708         ? kSeeDataTypes[i] : kVendorDataTypes[i - kNumSeeTypes];
709 
710     SensorType sensorType = getSensorTypeFromDataType(
711         dataType, false /* calibrated */);
712     if (sensorType == SensorType::Unknown) {
713       LOGE("Unknown sensor type found for '%s'", dataType);
714       continue;
715     }
716 
717     findAndAddSensorsForType(seeHelper, tempSensors, dataType, sensorType,
718                              false /* skipAdditionalTypes */, sensors);
719   }
720 
721 #ifdef CHRE_SLPI_UIMG_ENABLED
722   getBigImageSensors(sensors);
723 #endif
724 
725   return true;
726 }
727 
applyRequest(const SensorRequest & request)728 bool PlatformSensor::applyRequest(const SensorRequest& request) {
729   SeeSensorRequest req = {
730     .sensorType = getSensorType(),
731     .enable = (request.getMode() != SensorMode::Off),
732     .passive = sensorModeIsPassive(request.getMode()),
733     .samplingRateHz = static_cast<float>(
734         kOneSecondInNanoseconds / request.getInterval().toRawNanoseconds()),
735     // Override batch period to 0 for non-continuous sensors to ensure one
736     // sample per batch.
737     .batchPeriodUs = !sensorTypeIsContinuous(mSensorType) ? 0
738         : static_cast<uint32_t>(request.getLatency().toRawNanoseconds()
739                                 / kOneMicrosecondInNanoseconds),
740   };
741 
742   if (req.enable && req.passive && !mPassiveSupported) {
743     LOGD("Promoting sensor %" PRIu8 " passive request to active",
744          static_cast<uint8_t>(getSensorType()));
745   }
746 
747   SeeHelper *seeHelper = getSeeHelperForSensorType(getSensorType());
748   bool wasInUImage = slpiInUImage();
749   bool success = seeHelper->makeRequest(req);
750 
751   // If we dropped into micro-image during that blocking call to SEE, go back to
752   // big image. This won't happen if the calling nanoapp is a big image one, but
753   // other code paths currently assume that we will only transition from big
754   // image to micro-image from CHRE's perspective while it's waiting for an
755   // event to arrive in its empty queue.
756   // TODO: transition back to big image only when needed, at the point of
757   // invoking a nanoapp's free event/message callback
758   if (!wasInUImage && slpiInUImage()) {
759     LOGD("Restoring big image operating mode");
760     slpiForceBigImage();
761   }
762 
763   if (success) {
764     if (request.getMode() == SensorMode::Off) {
765       mLastEventValid = false;
766     }
767 
768     // TODO: remove setSamplingStatus when .latency is available in status
769     // update from SEE.
770     struct chreSensorSamplingStatus status;
771     if (getSamplingStatus(&status)) {
772 
773       // If passive request is not supported by this SEE sensor, it won't be
774       // dynamically enabled/disabled and its status stays the same as set here.
775       if (!mPassiveSupported) {
776         status.enabled = req.enable;
777       }
778       status.latency = req.batchPeriodUs * kOneMicrosecondInNanoseconds;
779       setSamplingStatus(status);
780     }
781   }
782   return success;
783 }
784 
flushAsync()785 bool PlatformSensor::flushAsync() {
786   SensorType sensorType = getSensorType();
787   return getSeeHelperForSensorType(sensorType)->flush(sensorType);
788 }
789 
getSensorType() const790 SensorType PlatformSensor::getSensorType() const {
791   return mSensorType;
792 }
793 
getMinInterval() const794 uint64_t PlatformSensor::getMinInterval() const {
795   return mMinInterval;
796 }
797 
getSensorName() const798 const char *PlatformSensor::getSensorName() const {
799   return mSensorName;
800 }
801 
PlatformSensor(PlatformSensor && other)802 PlatformSensor::PlatformSensor(PlatformSensor&& other) {
803   // Our move assignment operator doesn't assume that "this" is initialized, so
804   // we can just use that here.
805   *this = std::move(other);
806 }
807 
operator =(PlatformSensor && other)808 PlatformSensor& PlatformSensor::operator=(PlatformSensor&& other) {
809   // Note: if this implementation is ever changed to depend on "this" containing
810   // initialized values, the move constructor implemenation must be updated.
811   mSensorType = other.mSensorType;
812   mMinInterval = other.mMinInterval;
813   memcpy(mSensorName, other.mSensorName, kSensorNameMaxLen);
814 
815   mLastEvent = other.mLastEvent;
816   other.mLastEvent = nullptr;
817 
818   mLastEventSize = other.mLastEventSize;
819   other.mLastEventSize = 0;
820 
821   mLastEventValid = other.mLastEventValid;
822   mSamplingStatus = other.mSamplingStatus;
823   mPassiveSupported = other.mPassiveSupported;
824 
825   return *this;
826 }
827 
getLastEvent() const828 ChreSensorData *PlatformSensor::getLastEvent() const {
829   return mLastEventValid ? mLastEvent : nullptr;
830 }
831 
getSamplingStatus(struct chreSensorSamplingStatus * status) const832 bool PlatformSensor::getSamplingStatus(
833     struct chreSensorSamplingStatus *status) const {
834   CHRE_ASSERT(status);
835 
836   memcpy(status, &mSamplingStatus, sizeof(*status));
837   return true;
838 }
839 
getThreeAxisBias(struct chreSensorThreeAxisData * bias) const840 bool PlatformSensor::getThreeAxisBias(
841     struct chreSensorThreeAxisData *bias) const {
842   SensorType sensorType = getSensorType();
843   SeeCalHelper *calHelper =
844       getSeeHelperForSensorType(sensorType)->getCalHelper();
845 
846   bool success = sensorTypeReportsBias(sensorType);
847   if (success) {
848     // We use the runtime-calibrated sensor type here, per documentation
849     // of SeeCalHelper::getBias(), but overwrite the sensorHandle to that of
850     // the curent sensor, because the calibration data itself is equivalent
851     // for both calibrated/uncalibrated sensor types.
852 #ifdef CHRE_SLPI_UIMG_ENABLED
853     // Use the uimg runtime-calibrated sensor type to get the calibration
854     // bias, since SeeCalHelper is unaware of the bimg/uimg differentiation.
855     SensorType calSensorType =
856         toCalibratedSensorType(getUimgSensorType(sensorType));
857 #else
858     SensorType calSensorType = toCalibratedSensorType(sensorType);
859 #endif
860     if (calHelper->getBias(calSensorType, bias)) {
861       bias->header.sensorHandle = getSensorHandleFromSensorType(sensorType);
862     } else {
863       // Set to zero value + unknown accuracy per CHRE API requirements.
864       memset(bias, 0, sizeof(chreSensorThreeAxisData));
865       bias->header.accuracy = CHRE_SENSOR_ACCURACY_UNKNOWN;
866     }
867   }
868 
869   return success;
870 }
871 
initBase(SensorType sensorType,uint64_t minInterval,const char * sensorName,ChreSensorData * lastEvent,size_t lastEventSize,bool passiveSupported)872 void PlatformSensorBase::initBase(
873     SensorType sensorType,uint64_t minInterval, const char *sensorName,
874     ChreSensorData *lastEvent, size_t lastEventSize, bool passiveSupported) {
875   mSensorType = sensorType;
876   mMinInterval = minInterval;
877   memcpy(mSensorName, sensorName, kSensorNameMaxLen);
878   mLastEvent = lastEvent;
879   mLastEventSize = lastEventSize;
880 
881   mSamplingStatus.enabled = false;
882   mSamplingStatus.interval = CHRE_SENSOR_INTERVAL_DEFAULT;
883   mSamplingStatus.latency = CHRE_SENSOR_LATENCY_DEFAULT;
884 
885   mPassiveSupported = passiveSupported;
886 }
887 
setLastEvent(const ChreSensorData * event)888 void PlatformSensorBase::setLastEvent(const ChreSensorData *event) {
889   memcpy(mLastEvent, event, mLastEventSize);
890   mLastEventValid = true;
891 }
892 
setSamplingStatus(const struct chreSensorSamplingStatus & status)893 void PlatformSensorBase::setSamplingStatus(
894     const struct chreSensorSamplingStatus& status) {
895   mSamplingStatus = status;
896 }
897 
898 }  // namespace chre
899