1 /*
2  * Copyright (C) 2019 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_manager.h"
18 
19 #include "sns_std_sensor.pb.h"
20 #include "stringl.h"
21 
22 #include <cmath>
23 
24 #include "chre/core/event_loop_manager.h"
25 #include "chre/core/sensor.h"
26 #include "chre/core/sensor_type_helpers.h"
27 #include "chre/platform/log.h"
28 #include "chre/platform/slpi/power_control_util.h"
29 #include "chre/platform/system_time.h"
30 #include "chre_api/chre/sensor.h"
31 
32 #ifdef CHREX_SENSOR_SUPPORT
33 #include "chre/extensions/platform/slpi/see/vendor_data_types.h"
34 #endif  // CHREX_SENSOR_SUPPORT
35 
36 #ifdef CHRE_VARIANT_SUPPLIES_SEE_SENSORS_LIST
37 #include "see_sensors.h"
38 #endif  // CHRE_VARIANT_SUPPLIES_SEE_SENSORS_LIST
39 
40 #ifndef CHRE_SEE_NUM_TEMP_SENSORS
41 // There are usually more than one 'sensor_temperature' sensors in SEE.
42 // Define this in the variant-specific makefile to avoid missing sensors in
43 // sensor discovery.
44 #error "CHRE_SEE_NUM_TEMP_SENSORS is not defined"
45 #endif
46 
47 namespace chre {
48 namespace {
49 
50 //! A struct to facilitate sensor discovery
51 struct SuidAttr {
52   sns_std_suid suid;
53   SeeAttributes attr;
54 };
55 
56 #ifndef CHRE_VARIANT_SUPPLIES_SEE_SENSORS_LIST
57 
58 //! The list of SEE platform sensor data types that CHRE intends to support.
59 //! The standardized strings are defined in sns_xxx.proto.
60 const char *kSeeDataTypes[] = {
61     "accel",
62     "gyro",
63     "mag",
64     "pressure",
65     "ambient_light",
66     "proximity",
67 #ifdef CHRE_SLPI_DEFAULT_BUILD
68     // Both instant motion and stationary detect share the same data type.
69     "amd",
70     "amd",
71 #else
72     "motion_detect", "stationary_detect",
73 #endif
74 };
75 
76 #endif  // CHRE_VARIANT_SUPPLIES_SEE_SENSORS_LIST
77 
78 #ifdef CHRE_SLPI_UIMG_ENABLED
79 #ifndef CHREX_SENSOR_SUPPORT
80 // The current implementation uses vendor sensor type 3 to remap into accel,
81 // with requests made through QMI instead of QSockets, as SEE does not support
82 // micro-image batching in QCM.
83 #error "CHRE extensions are required for micro-image SEE support"
84 #endif  // CHREX_SENSOR_SUPPORT
85 
86 bool isBigImageSensorType(uint8_t sensorType) {
87   return (sensorType == CHRE_SLPI_SENSOR_TYPE_BIG_IMAGE_ACCEL ||
88           sensorType == CHRE_SLPI_SENSOR_TYPE_BIG_IMAGE_UNCAL_ACCEL ||
89           sensorType == CHRE_SLPI_SENSOR_TYPE_BIG_IMAGE_UNCAL_GYRO ||
90           sensorType == CHRE_SLPI_SENSOR_TYPE_BIG_IMAGE_UNCAL_MAG ||
91           sensorType == CHRE_SLPI_SENSOR_TYPE_BIG_IMAGE_LIGHT);
92 }
93 
94 /**
95  * Obtains the big-image sensor type given the specified data type and whether
96  * the sensor is runtime-calibrated or not.
97  */
98 bool getBigImageSensorTypeFromDataType(const char *dataType, bool calibrated,
99                                        uint8_t *sensorType) {
100   bool found = true;
101   if (strcmp(dataType, "accel") == 0) {
102     if (calibrated) {
103       *sensorType = CHRE_SLPI_SENSOR_TYPE_BIG_IMAGE_ACCEL;
104     } else {
105       *sensorType = CHRE_SLPI_SENSOR_TYPE_BIG_IMAGE_UNCAL_ACCEL;
106     }
107   } else if (strcmp(dataType, "gyro") == 0 && !calibrated) {
108     *sensorType = CHRE_SLPI_SENSOR_TYPE_BIG_IMAGE_UNCAL_GYRO;
109   } else if (strcmp(dataType, "mag") == 0 && !calibrated) {
110     *sensorType = CHRE_SLPI_SENSOR_TYPE_BIG_IMAGE_UNCAL_MAG;
111   } else if (strcmp(dataType, "ambient_light") == 0 && calibrated) {
112     *sensorType = CHRE_SLPI_SENSOR_TYPE_BIG_IMAGE_LIGHT;
113   } else {
114     found = false;
115   }
116   return found;
117 }
118 
119 /**
120  * Obtains the micro-image sensor type given the specified sensor type.
121  *
122  * @param sensorType The sensor type to convert from.
123  * @return The associated micro-image sensor type, or the input sensor type
124  *     if not associated with one
125  */
126 uint8_t getUimgSensorType(uint8_t sensorType) {
127   switch (sensorType) {
128     case (CHRE_SENSOR_TYPE_VENDOR_START + 3):
129       return CHRE_SENSOR_TYPE_ACCELEROMETER;
130     case (CHRE_SENSOR_TYPE_VENDOR_START + 6):
131       return CHRE_SENSOR_TYPE_UNCALIBRATED_ACCELEROMETER;
132     case (CHRE_SENSOR_TYPE_VENDOR_START + 7):
133       return CHRE_SENSOR_TYPE_UNCALIBRATED_GYROSCOPE;
134     case (CHRE_SENSOR_TYPE_VENDOR_START + 8):
135       return CHRE_SENSOR_TYPE_UNCALIBRATED_GEOMAGNETIC_FIELD;
136     case (CHRE_SENSOR_TYPE_VENDOR_START + 9):
137       return CHRE_SENSOR_TYPE_LIGHT;
138     default:
139       return sensorType;
140   }
141 }
142 
143 #endif  // CHRE_SLPI_UIMG_ENABLED
144 
145 void handleMissingSensor() {
146   // Try rebooting if a sensor is missing, which might help recover from a
147   // transient failure/race condition at startup. But to avoid endless crashes,
148   // only do this within 15 seconds of the timeout on initializing SEE - we rely
149   // on knowledge that getMonotonicTime() maps into QTimer here, and QTimer only
150   // resets when the entire system is rebooted (it continues increasing after
151   // SLPI SSR).
152 #ifndef CHRE_LOG_ONLY_NO_SENSOR
153   if (SystemTime::getMonotonicTime() < (kDefaultSeeWaitTimeout + Seconds(15))) {
154     FATAL_ERROR("Missing required sensor(s)");
155   } else
156 #endif
157   {
158     LOGE("Missing required sensor(s)");
159   }
160 }
161 
162 /**
163  * Obtains the sensor type given the specified data type and whether the sensor
164  * is runtime-calibrated or not.
165  *
166  * @return Whether a sensor type was found for the given data type.
167  */
168 bool getSensorTypeFromDataType(const char *dataType, bool calibrated,
169                                uint8_t *sensorType) {
170   bool success = true;
171   if (strcmp(dataType, "accel") == 0) {
172     if (calibrated) {
173       *sensorType = CHRE_SENSOR_TYPE_ACCELEROMETER;
174     } else {
175       *sensorType = CHRE_SENSOR_TYPE_UNCALIBRATED_ACCELEROMETER;
176     }
177   } else if (strcmp(dataType, "gyro") == 0) {
178     if (calibrated) {
179       *sensorType = CHRE_SENSOR_TYPE_GYROSCOPE;
180     } else {
181       *sensorType = CHRE_SENSOR_TYPE_UNCALIBRATED_GYROSCOPE;
182     }
183   } else if (strcmp(dataType, "mag") == 0) {
184     if (calibrated) {
185       *sensorType = CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD;
186     } else {
187       *sensorType = CHRE_SENSOR_TYPE_UNCALIBRATED_GEOMAGNETIC_FIELD;
188     }
189   } else if (strcmp(dataType, "pressure") == 0) {
190     *sensorType = CHRE_SENSOR_TYPE_PRESSURE;
191   } else if (strcmp(dataType, "ambient_light") == 0) {
192     *sensorType = CHRE_SENSOR_TYPE_LIGHT;
193   } else if (strcmp(dataType, "proximity") == 0) {
194     *sensorType = CHRE_SENSOR_TYPE_PROXIMITY;
195   } else if (strcmp(dataType, "motion_detect") == 0 ||
196              strcmp(dataType, "amd") == 0) {
197     *sensorType = CHRE_SENSOR_TYPE_INSTANT_MOTION_DETECT;
198   } else if (strcmp(dataType, "stationary_detect") == 0) {
199     *sensorType = CHRE_SENSOR_TYPE_STATIONARY_DETECT;
200   } else if (strcmp(dataType, "step_detect") == 0) {
201     *sensorType = CHRE_SENSOR_TYPE_STEP_DETECT;
202   } else {
203 #ifdef CHREX_SENSOR_SUPPORT
204     success = extension::vendorSensorTypeFromDataType(dataType, calibrated,
205                                                       sensorType);
206   }
207 #else
208     success = false;
209   }
210 #endif
211   return success;
212 }
213 
214 /**
215  * Merges a status update with an existing sampling status.
216  */
217 void mergeUpdatedStatus(
218     uint32_t sensorHandle,
219     const SeeHelperCallbackInterface::SamplingStatusData &update,
220     struct chreSensorSamplingStatus *mergedStatus) {
221   Sensor *sensor = getSensorRequestManager().getSensor(sensorHandle);
222   sensor->getSamplingStatus(mergedStatus);
223 
224   if (update.enabledValid) {
225     mergedStatus->enabled = update.status.enabled;
226   }
227   if (update.intervalValid) {
228     mergedStatus->interval = update.status.interval;
229   }
230   if (update.latencyValid) {
231     mergedStatus->latency = update.status.latency;
232   }
233 }
234 
235 /**
236  * Helper function to post a bias event given the bias data.
237  *
238  * @param sensorType The sensor type to post the event for.
239  * @param bias The bias data.
240  */
241 void postSensorBiasEvent(uint8_t sensorType,
242                          const chreSensorThreeAxisData &bias) {
243   uint16_t eventType;
244   if (SensorTypeHelpers::getBiasEventType(sensorType, &eventType)) {
245     auto *event = memoryAlloc<struct chreSensorThreeAxisData>();
246     if (event == nullptr) {
247       LOG_OOM();
248     } else {
249       *event = bias;
250       getSensorRequestManager().getSensorHandle(sensorType,
251                                                 &event->header.sensorHandle);
252       EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
253           eventType, event, freeEventDataCallback);
254     }
255   }
256 }
257 
258 /**
259  * Compares the given status updates and returns true if they are the same.
260  *
261  * A simple memcmp cannot be done because if a given field is not valid, then
262  * the field may be different across updates, but doesn't indicate the update
263  * is different.
264  */
265 bool isSameStatusUpdate(
266     const SeeHelperCallbackInterface::SamplingStatusData &status1,
267     const SeeHelperCallbackInterface::SamplingStatusData &status2) {
268   bool sameStatus = status1.enabledValid == status2.enabledValid;
269   if (sameStatus && status1.enabledValid) {
270     sameStatus &= status1.status.enabled == status2.status.enabled;
271   }
272   // Only check interval / latency fields if both status updates say the sensor
273   // is enabled since CHRE doesn't care what the fields are set to if the sensor
274   // is disabled.
275   if (sameStatus && status1.status.enabled) {
276     sameStatus &= status1.intervalValid == status2.intervalValid;
277     if (sameStatus && status1.intervalValid) {
278       sameStatus &= status1.status.interval == status2.status.interval;
279     }
280     sameStatus &= status1.latencyValid == status2.latencyValid;
281     if (sameStatus && status1.latencyValid) {
282       sameStatus &= status1.status.latency == status2.status.latency;
283     }
284   }
285   return sameStatus;
286 }
287 
288 /**
289  * Constructs and initializes a sensor, and adds it to the sensor list.
290  *
291  * @param seeHelper SeeHelper instance to register sensor with
292  * @param sensorType The sensor type of the sensor.
293  * @param suid The SUID of the sensor as provided by SEE.
294  * @param attr A reference to SeeAttrbutes.
295  * @param sensors The sensor list.
296  */
297 void addSensor(SeeHelper &seeHelper, uint8_t sensorType,
298                const sns_std_suid &suid, const SeeAttributes &attr,
299                DynamicVector<Sensor> *sensors) {
300   // Concatenate vendor and name with a space in between.
301   char sensorName[kSensorNameMaxLen];
302   strlcpy(sensorName, attr.vendor, sizeof(sensorName));
303   strlcat(sensorName, " ", sizeof(sensorName));
304   strlcat(sensorName, attr.name, sizeof(sensorName));
305 
306   // Some sensors have a max sample rate of 0 which makes ceilf return infinity
307   // for on-change or continuous sensors when that's not the correct
308   // minInterval.
309   float maxSampleRate = (attr.maxSampleRate == 0.0f) ? 10 : attr.maxSampleRate;
310 
311   // Override one-shot sensor's minInterval to default
312   uint64_t minInterval =
313       SensorTypeHelpers::isOneShot(sensorType)
314           ? CHRE_SENSOR_INTERVAL_DEFAULT
315           : static_cast<uint64_t>(
316                 ceilf(Seconds(1).toRawNanoseconds() / maxSampleRate));
317 
318   if (!sensors->emplace_back()) {
319     FATAL_ERROR("Failed to allocate new sensor: out of memory");
320   }
321 
322   // The sensor base class must be initialized before the main Sensor init()
323   // can be invoked as init() is allowed to invoke base class methods.
324   sensors->back().initBase(sensorType, minInterval, sensorName,
325                            attr.passiveRequest);
326   sensors->back().init();
327 
328   // Resample big image sensors to reduce system load during sw flush.
329 #ifdef CHRE_SLPI_UIMG_ENABLED
330   bool resample = isBigImageSensorType(sensorType);
331 #else
332   bool resample = false;
333 #endif
334   bool prevRegistered;
335   bool registered =
336       seeHelper.registerSensor(sensorType, suid, resample, &prevRegistered);
337   if (!registered && prevRegistered) {
338     LOGW("SUID has been previously registered");
339   } else if (!registered) {
340     FATAL_ERROR("Failed to register SUID/SensorType mapping.");
341   }
342 }
343 
344 /**
345  * Compare SEE reported stream type attribute to the expected one. Some SEE
346  * sensors may support more than one stream type.
347  */
348 bool isStreamTypeCorrect(uint8_t sensorType, uint8_t streamType) {
349   bool success = true;
350   if ((SensorTypeHelpers::isContinuous(sensorType) &&
351        streamType != SNS_STD_SENSOR_STREAM_TYPE_STREAMING) ||
352       (SensorTypeHelpers::isOnChange(sensorType) &&
353        streamType != SNS_STD_SENSOR_STREAM_TYPE_ON_CHANGE)
354 // The default SLPI build exposes instant motion / stationary sensors as
355 // on-change, but CHRE uses them as one-shot
356 #ifndef CHRE_SLPI_DEFAULT_BUILD
357       || (SensorTypeHelpers::isOneShot(sensorType) &&
358           streamType != SNS_STD_SENSOR_STREAM_TYPE_SINGLE_OUTPUT)
359 #endif
360   ) {
361     success = false;
362     LOGW("Inconsistent sensor type %" PRIu8 " and stream type %" PRIu8,
363          static_cast<uint8_t>(sensorType), streamType);
364   }
365   return success;
366 }
367 
368 /**
369  * Obtains the list of SUIDs and their attributes that support the specified
370  * data type.
371  */
372 bool getSuidAndAttrs(SeeHelper &seeHelper, const char *dataType,
373                      DynamicVector<SuidAttr> *suidAttrs, uint8_t minNumSuids) {
374   DynamicVector<sns_std_suid> suids;
375   bool success = seeHelper.findSuidSync(dataType, &suids, minNumSuids);
376   if (!success) {
377     LOGE("Failed to find sensor '%s'", dataType);
378   } else {
379     LOGD("Num of SUIDs found for '%s': %zu", dataType, suids.size());
380 
381     for (const auto &suid : suids) {
382       SeeAttributes attr;
383       if (!seeHelper.getAttributesSync(suid, &attr)) {
384         success = false;
385         LOGE("Failed to get attributes of SUID 0x%" PRIx64 " %" PRIx64,
386              suid.suid_high, suid.suid_low);
387       } else {
388         LOGI("%s %s, hw id %" PRId64 ", max ODR %f Hz, stream type %" PRIu8
389              " passive %d",
390              attr.vendor, attr.name, attr.hwId, attr.maxSampleRate,
391              attr.streamType, attr.passiveRequest);
392         SuidAttr sensor = {
393             .suid = suid,
394             .attr = attr,
395         };
396         if (!suidAttrs->push_back(sensor)) {
397           success = false;
398           LOG_OOM();
399         }
400       }
401     }
402   }
403   return success;
404 }
405 
406 #ifndef CHRE_SLPI_DEFAULT_BUILD
407 //! Check whether two sensors with the specified attrtibutes belong to the same
408 //! sensor hardware module.
409 bool sensorHwMatch(const SeeAttributes &attr0, const SeeAttributes &attr1) {
410   // When HW ID is absent, its default to 0 and won't be a factor.
411   return ((strncmp(attr0.vendor, attr1.vendor, kSeeAttrStrValLen) == 0) &&
412           (strncmp(attr0.name, attr1.name, kSeeAttrStrValLen) == 0) &&
413           (attr0.hwId == attr1.hwId));
414 }
415 #endif
416 
417 /**
418  * Looks up SUID(s) associated with a given sensor data type string and sensor
419  * type enum, registers them with SeeHelper, and adds a Sensor instance to the
420  * supplied vector for use in CHRE. When given an uncalibrated sensor type, will
421  * also look for and add the calibrated sensor type.
422  *
423  * @param seeHelper SeeHelper instance to use for lookup/registration
424  * @param temperatureSensors List of previously discovered temperature sensor
425  *        info to use for adding temp sensors associated with this sensor type
426  * @param dataType SEE data type string
427  * @param sensorType CHRE sensor type associated with dataType
428  * @param skipAdditionalTypes if true, don't attempt to add
429  *        calibrated/temperature sensor types associated with this sensorType
430  * @param sensors Vector to append found sensor(s) to
431  */
432 void findAndAddSensorsForType(SeeHelper &seeHelper,
433                               const DynamicVector<SuidAttr> &temperatureSensors,
434                               const char *dataType, uint8_t sensorType,
435                               bool skipAdditionalTypes,
436                               DynamicVector<Sensor> *sensors) {
437   DynamicVector<SuidAttr> primarySensors;
438   if (!getSuidAndAttrs(seeHelper, dataType, &primarySensors,
439                        1 /* minNumSuids */)) {
440     handleMissingSensor();
441   }
442 
443   for (const auto &primarySensor : primarySensors) {
444     sns_std_suid suid = primarySensor.suid;
445     SeeAttributes attr = primarySensor.attr;
446 
447     // Some sensors support both continuous and on-change streams.
448     // If there are more than one SUIDs that support the data type,
449     // choose the first one that has the expected stream type.
450     if (isStreamTypeCorrect(sensorType, attr.streamType)) {
451       addSensor(seeHelper, sensorType, suid, attr, sensors);
452 
453       if (!skipAdditionalTypes) {
454         // Check if this sensor has a runtime-calibrated version.
455         uint8_t calibratedType;
456         if (getSensorTypeFromDataType(dataType, true /* calibrated */,
457                                       &calibratedType) &&
458             calibratedType != sensorType) {
459           addSensor(seeHelper, calibratedType, suid, attr, sensors);
460         }
461 
462         // Check if this sensor has a secondary temperature sensor.
463         uint8_t temperatureType =
464             PlatformSensorTypeHelpers::getTempSensorType(sensorType);
465         if (temperatureType != CHRE_SENSOR_TYPE_INVALID) {
466           bool tempFound = false;
467           for (const auto &tempSensor : temperatureSensors) {
468             sns_std_suid tempSuid = tempSensor.suid;
469             SeeAttributes tempAttr = tempSensor.attr;
470 
471 #ifdef CHRE_SLPI_DEFAULT_BUILD
472             // The default build exposes a single temp sensor to be used for
473             // all temperature sensors that doesn't have the same attributes
474             // as the primarySensor.
475             if (true) {
476 #else
477             if (sensorHwMatch(attr, tempAttr)) {
478 #endif
479               LOGD("Found matching temperature sensor type");
480               tempFound = true;
481               addSensor(seeHelper, temperatureType, tempSuid, tempAttr,
482                         sensors);
483               break;
484             }
485           }
486           if (!tempFound) {
487             LOGW("Temperature sensor type %" PRIu8 " not found!",
488                  static_cast<uint8_t>(temperatureType));
489           }
490         }
491       }
492       break;
493     }
494   }
495 }
496 
497 }  // namespace
498 
499 PlatformSensorManager::~PlatformSensorManager() {}
500 
501 void PlatformSensorManager::init() {
502   if (!mSeeHelper.init(this)) {
503     FATAL_ERROR("Failed to initialize SEE helper");
504   }
505 
506 #ifdef CHRE_SLPI_UIMG_ENABLED
507   if (!mBigImageSeeHelper.init(this, kDefaultSeeWaitTimeout,
508                                true /* skipDefaultSensorInit */)) {
509     FATAL_ERROR("Failed to init bimg SEE helper");
510   }
511 #endif  // CHRE_SLPI_UIMG_ENABLED
512 }
513 
514 SeeHelper &PlatformSensorManagerBase::getSeeHelperForSensorType(
515     uint8_t sensorType) {
516 #ifdef CHRE_SLPI_UIMG_ENABLED
517   if (isBigImageSensorType(sensorType)) {
518     slpiForceBigImage();
519     return mBigImageSeeHelper;
520   } else
521 #endif
522   {
523     return mSeeHelper;
524   }
525 }
526 
527 #ifdef CHRE_SLPI_UIMG_ENABLED
528 void PlatformSensorManagerBase::getBigImageSensors(
529     DynamicVector<Sensor> *sensors) {
530   CHRE_ASSERT(sensors);
531 
532   // Currently, just adding calibrated accel, uncal accel/gyro/mag and als as
533   // they are the ones we know that big image nanoapps will need at a different
534   // batching rate compared to uimg.
535   const char *kBigImageDataTypes[] = {
536       "accel",
537       "gyro",
538       "mag",
539       "ambient_light",
540   };
541 
542   DynamicVector<SuidAttr> nullTemperatureSensorList;
543 
544   for (size_t i = 0; i < ARRAY_SIZE(kBigImageDataTypes); i++) {
545     const char *dataType = kBigImageDataTypes[i];
546     // Loop through potential cal/uncal sensors.
547     for (size_t j = 0; j < 2; j++) {
548       uint8_t sensorType;
549       if (getBigImageSensorTypeFromDataType(dataType, (j == 0) /* calibrated */,
550                                             &sensorType)) {
551         findAndAddSensorsForType(mBigImageSeeHelper, nullTemperatureSensorList,
552                                  dataType, sensorType,
553                                  true /* skipAdditionalTypes */, sensors);
554       }
555     }
556   }
557 }
558 #endif  // CHRE_SLPI_UIMG_ENABLED
559 
560 DynamicVector<Sensor> PlatformSensorManager::getSensors() {
561   DynamicVector<Sensor> sensors;
562   DynamicVector<SuidAttr> tempSensors;
563   if (!getSuidAndAttrs(mSeeHelper, "sensor_temperature", &tempSensors,
564                        CHRE_SEE_NUM_TEMP_SENSORS)) {
565     handleMissingSensor();
566   }
567 
568 #ifndef CHREX_SENSOR_SUPPORT
569   const char *kVendorDataTypes[] = {};
570 #endif  // CHREX_SENSOR_SUPPORT
571   constexpr size_t kNumSeeTypes = ARRAY_SIZE(kSeeDataTypes);
572   constexpr size_t kNumVendorTypes = ARRAY_SIZE(kVendorDataTypes);
573   for (size_t i = 0; i < kNumSeeTypes + kNumVendorTypes; i++) {
574     const char *dataType = (i < kNumSeeTypes)
575                                ? kSeeDataTypes[i]
576                                : kVendorDataTypes[i - kNumSeeTypes];
577 
578     uint8_t sensorType;
579     if (!getSensorTypeFromDataType(dataType, false /* calibrated */,
580                                    &sensorType)) {
581       LOGE("Unknown sensor type found for '%s'", dataType);
582       continue;
583     }
584 
585     bool skipAdditionalTypes = false;
586 
587 #ifdef CHRE_SLPI_DEFAULT_BUILD
588     // Stationary and motion detect share the same dataType on the default build
589     if (sensorType == CHRE_SENSOR_TYPE_INSTANT_MOTION_DETECT &&
590         i == kNumSeeTypes - 1) {
591       sensorType = CHRE_SENSOR_TYPE_STATIONARY_DETECT;
592       // Skip additional types or InstantMotion will be added to the sensor list
593       // twice.
594       skipAdditionalTypes = true;
595     }
596 #endif
597 
598     findAndAddSensorsForType(mSeeHelper, tempSensors, dataType, sensorType,
599                              skipAdditionalTypes, &sensors);
600   }
601 
602 #ifdef CHRE_SLPI_UIMG_ENABLED
603   getBigImageSensors(&sensors);
604 #endif
605 
606   return sensors;
607 }
608 
609 bool PlatformSensorManager::configureSensor(Sensor &sensor,
610                                             const SensorRequest &request) {
611   SeeSensorRequest req = {
612       .sensorType = sensor.getSensorType(),
613       .enable = (request.getMode() != SensorMode::Off),
614       .passive = sensorModeIsPassive(request.getMode()),
615       .samplingRateHz = static_cast<float>(
616           kOneSecondInNanoseconds / request.getInterval().toRawNanoseconds()),
617       // Override batch period to 0 for micro-image non-continuous sensors to
618       // ensure one sample per batch so that nanoapps do not miss state changes.
619       .batchPeriodUs =
620 #ifdef CHRE_SLPI_UIMG_ENABLED
621           (!sensor.isContinuous() &&
622            !isBigImageSensorType(sensor.getSensorType()))
623               ? 0
624               :
625 #endif
626               static_cast<uint32_t>(request.getLatency().toRawNanoseconds() /
627                                     kOneMicrosecondInNanoseconds),
628   };
629 
630   SeeHelper &seeHelper = getSeeHelperForSensorType(sensor.getSensorType());
631   bool wasInUImage = slpiInUImage();
632 
633   bool success = true;
634 
635   // TODO(b/150144912): Merge the two implementations to avoid having separate
636   // code paths.
637 #ifdef CHRE_SLPI_DEFAULT_BUILD
638   // Calibration updates are not enabled automatically in the default build.
639   SeeCalHelper *calHelper = seeHelper.getCalHelper();
640 
641   const sns_std_suid *suid =
642       calHelper->getCalSuidFromSensorType(sensor.getSensorType());
643   bool wereCalUpdatesEnabled = false;
644   if (suid != nullptr) {
645     wereCalUpdatesEnabled = calHelper->areCalUpdatesEnabled(*suid);
646     success = calHelper->configureCalUpdates(*suid, req.enable, seeHelper);
647   }
648 #endif
649 
650   if (success) {
651     success = seeHelper.makeRequest(req);
652   }
653 
654 #ifdef CHRE_SLPI_DEFAULT_BUILD
655   // If any part of the configuration process failed, reset our subscription
656   // for calibration updates to its previous value to attempt to restore state.
657   if (suid != nullptr && !success) {
658     bool areCalUpdatesEnabled = calHelper->areCalUpdatesEnabled(*suid);
659     if (areCalUpdatesEnabled != wereCalUpdatesEnabled) {
660       calHelper->configureCalUpdates(*suid, wereCalUpdatesEnabled, seeHelper);
661     }
662   }
663 #endif
664 
665   // If we dropped into micro-image during that blocking call to SEE, go back
666   // to big image. This won't happen if the calling nanoapp is a big image one,
667   // but other code paths currently assume that we will only transition from big
668   // image to micro-image from CHRE's perspective while it's waiting for an
669   // event to arrive in its empty queue.
670   // TODO: transition back to big image only when needed, at the point of
671   // invoking a nanoapp's free event/message callback
672   if (!wasInUImage && slpiInUImage()) {
673     LOGD("Restoring big image operating mode");
674     slpiForceBigImage();
675   }
676 
677   if (success) {
678     // TODO: remove setSamplingStatus when .latency is available in status
679     // update from SEE.
680     struct chreSensorSamplingStatus status;
681     if (sensor.getSamplingStatus(&status)) {
682       // If passive request is not supported by this SEE sensor, it won't be
683       // dynamically enabled/disabled and its status stays the same as set here.
684       if (!sensor.supportsPassiveMode()) {
685         status.enabled = req.enable;
686       }
687       status.latency = req.batchPeriodUs * kOneMicrosecondInNanoseconds;
688       sensor.setSamplingStatus(status);
689     }
690   }
691   return success;
692 }
693 
694 bool PlatformSensorManager::configureBiasEvents(const Sensor & /* sensor */,
695                                                 bool /* enable */,
696                                                 uint64_t /* latencyNs */) {
697   // TODO: Allow enabling / disabling bias events rather than enabling all
698   // bias sensors at init.
699   return true;
700 }
701 
702 bool PlatformSensorManager::getThreeAxisBias(
703     const Sensor &sensor, struct chreSensorThreeAxisData *bias) const {
704   uint8_t sensorType = sensor.getSensorType();
705   SeeCalHelper *calHelper =
706       getSeeHelperForSensorType(sensorType).getCalHelper();
707 
708   bool success = sensor.reportsBiasEvents();
709   if (success) {
710     // We use the runtime-calibrated sensor type here, per documentation
711     // of SeeCalHelper::getBias(), but overwrite the sensorHandle to that of
712     // the current sensor, because the calibration data itself is equivalent
713     // for both calibrated/uncalibrated sensor types.
714 #ifdef CHRE_SLPI_UIMG_ENABLED
715     // Use the uimg runtime-calibrated sensor type to get the calibration
716     // bias, since SeeCalHelper is unaware of the bimg/uimg differentiation.
717     uint8_t calSensorType = PlatformSensorTypeHelpers::toCalibratedSensorType(
718         getUimgSensorType(sensorType));
719 #else
720     uint8_t calSensorType =
721         PlatformSensorTypeHelpers::toCalibratedSensorType(sensorType);
722 #endif
723     if (!calHelper->getBias(calSensorType, bias)) {
724       // Set to zero bias + unknown accuracy per CHRE API requirements.
725       memset(bias, 0, sizeof(chreSensorThreeAxisData));
726       bias->header.readingCount = 1;
727       bias->header.accuracy = CHRE_SENSOR_ACCURACY_UNKNOWN;
728     }
729 
730     // Overwrite sensorHandle to match the request type.
731     getSensorRequestManager().getSensorHandle(sensorType,
732                                               &bias->header.sensorHandle);
733   }
734 
735   return success;
736 }
737 
738 bool PlatformSensorManager::flush(const Sensor &sensor,
739                                   uint32_t *flushRequestId) {
740   uint8_t sensorType = sensor.getSensorType();
741   return getSeeHelperForSensorType(sensorType).flush(sensorType);
742 }
743 
744 void PlatformSensorManager::releaseSamplingStatusUpdate(
745     struct chreSensorSamplingStatus *status) {
746   memoryFree(status);
747 }
748 
749 void PlatformSensorManager::releaseSensorDataEvent(void *data) {
750   memoryFree(data);
751 }
752 
753 void PlatformSensorManager::releaseBiasEvent(void *biasData) {
754   memoryFree(biasData);
755 }
756 
757 void PlatformSensorManagerBase::onSamplingStatusUpdate(
758     UniquePtr<SeeHelperCallbackInterface::SamplingStatusData> &&status) {
759   uint32_t sensorHandle;
760   getSensorRequestManager().getSensorHandle(status->sensorType, &sensorHandle);
761   Sensor *sensor = getSensorRequestManager().getSensor(sensorHandle);
762 
763   // TODO: Once the latency field is actually filled in by SEE, modify this
764   // logic to avoid reacting if the latency and interval of the sensor are
765   // updated separately, but contain the same info as before.
766   if (sensor != nullptr) {
767     // Ignore the enabled flag from status update if this is not a passive mode
768     // supported sensor because this may cause the sampling status in CHRE to
769     // go out of sync with reality
770     if (!sensor->supportsPassiveMode()) {
771       status->status.enabled =
772           sensor->mLastReceivedSamplingStatus.status.enabled;
773       status->enabledValid = sensor->mLastReceivedSamplingStatus.enabledValid;
774     }
775     if (!isSameStatusUpdate(sensor->mLastReceivedSamplingStatus,
776                             *status.get())) {
777       sensor->mLastReceivedSamplingStatus = *status.get();
778 
779       auto callback = [](uint16_t /* type */, void *data) {
780         auto cbData = UniquePtr<SeeHelperCallbackInterface::SamplingStatusData>(
781             static_cast<SeeHelperCallbackInterface::SamplingStatusData *>(
782                 data));
783 
784         uint32_t sensorHandle;
785         getSensorRequestManager().getSensorHandle(cbData->sensorType,
786                                                   &sensorHandle);
787 
788         // Memory will be freed after core framework performs its updates.
789         struct chreSensorSamplingStatus *status =
790             memoryAlloc<struct chreSensorSamplingStatus>();
791         mergeUpdatedStatus(sensorHandle, *cbData.get(), status);
792 
793         getSensorRequestManager().handleSamplingStatusUpdate(sensorHandle,
794                                                              status);
795       };
796       // Schedule a deferred callback to handle sensor status change in the main
797       // thread.
798       EventLoopManagerSingleton::get()->deferCallback(
799           SystemCallbackType::SensorStatusUpdate, status.release(), callback);
800     }
801   }
802 }
803 
804 void PlatformSensorManagerBase::onSensorDataEvent(
805     uint8_t sensorType, UniquePtr<uint8_t> &&eventData) {
806   uint32_t sensorHandle;
807   getSensorRequestManager().getSensorHandle(sensorType, &sensorHandle);
808   auto *header =
809       reinterpret_cast<struct chreSensorDataHeader *>(eventData.get());
810   header->sensorHandle = sensorHandle;
811 
812   getSensorRequestManager().handleSensorDataEvent(sensorHandle,
813                                                   eventData.release());
814 }
815 
816 void PlatformSensorManagerBase::onHostWakeSuspendEvent(bool awake) {
817   // Host wake events are sent as soon as SEE is up so verify the event loop is
818   // up before attempting to post the event to avoid a crash.
819   if (EventLoopManagerSingleton::isInitialized()) {
820     EventLoopManagerSingleton::get()
821         ->getEventLoop()
822         .getPowerControlManager()
823         .onHostWakeSuspendEvent(awake);
824   }
825 }
826 
827 void PlatformSensorManagerBase::onSensorBiasEvent(
828     uint8_t sensorType, UniquePtr<struct chreSensorThreeAxisData> &&biasData) {
829   uint32_t sensorHandle;
830   if (getSensorRequestManager().getSensorHandle(sensorType, &sensorHandle)) {
831     biasData->header.sensorHandle = sensorHandle;
832     Sensor *sensor = getSensorRequestManager().getSensor(sensorHandle);
833     if (!sensor->reportsBiasEvents()) {
834       LOGE("Received bias event for unsupported sensor type %" PRIu8,
835            sensorType);
836     } else {
837       // Posts newly allocated event for the uncalibrated type
838       postSensorBiasEvent(
839           PlatformSensorTypeHelpers::toUncalibratedSensorType(sensorType),
840           *biasData);
841 
842       getSensorRequestManager().handleBiasEvent(sensorHandle,
843                                                 biasData.release());
844     }
845   }
846 }
847 
848 void PlatformSensorManagerBase::onFlushCompleteEvent(uint8_t sensorType) {
849   // Flush complete events are sent after any batch delivery so verify the
850   // event loop is up before attempting to post the event to avoid a crash.
851   if (EventLoopManagerSingleton::isInitialized()) {
852     // TODO: Have SEE pass flush request IDs through the flush complete event
853     uint32_t sensorHandle;
854     getSensorRequestManager().getSensorHandle(sensorType, &sensorHandle);
855     getSensorRequestManager().handleFlushCompleteEvent(
856         sensorHandle, UINT32_MAX, /* invalid flush request ID */
857         CHRE_ERROR_NONE);
858   }
859 }
860 
861 }  // namespace chre
862