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