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