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