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