• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 <algorithm>
18 #include <cinttypes>
19 
20 extern "C" {
21 
22 #include "fixed_point.h"
23 #include "qmi_client.h"
24 #include "sns_smgr_api_v01.h"
25 #include "sns_smgr_internal_api_v02.h"
26 #include "timetick.h"
27 
28 }  // extern "C"
29 
30 #include "chre_api/chre/sensor.h"
31 #include "chre/core/event_loop_manager.h"
32 #include "chre/platform/assert.h"
33 #include "chre/platform/fatal_error.h"
34 #include "chre/platform/log.h"
35 #include "chre/platform/platform_sensor.h"
36 #include "chre/platform/slpi/platform_sensor_util.h"
37 
38 namespace chre {
39 namespace {
40 
41 //! The timeout for QMI messages in milliseconds.
42 constexpr uint32_t kQmiTimeoutMs = 1000;
43 
44 constexpr float kMicroTeslaPerGauss = 100.0f;
45 
46 //! The QMI sensor service client handle.
47 qmi_client_type gPlatformSensorServiceQmiClientHandle = nullptr;
48 
49 //! The QMI sensor internal service client handle.
50 qmi_client_type gPlatformSensorInternalServiceQmiClientHandle = nullptr;
51 
52 //! A sensor report indication for deserializing sensor sample indications
53 //! into. This global instance is used to avoid thrashy use of the heap by
54 //! allocating and freeing this on the heap for every new sensor sample. This
55 //! relies on the assumption that the QMI callback is not reentrant.
56 sns_smgr_buffering_ind_msg_v01 gSmgrBufferingIndMsg;
57 
58 //! A struct to store the sensor monitor status indication results.
59 struct SensorStatus {
60   uint8_t sensorId;
61   uint8_t numClients;
62 };
63 
64 //! A vector that tracks the number clients of each supported sensorId.
65 DynamicVector<SensorStatus> gSensorStatusMonitor;
66 
67 /**
68  * Converts a sensorId, dataType and calType as provided by SMGR to a
69  * SensorType as used by platform-independent CHRE code. This is useful in
70  * sensor discovery.
71  *
72  * @param sensorId The sensorID as provided by the SMGR request for sensor info.
73  * @param dataType The dataType for the sesnor as provided by the SMGR request
74  *                 for sensor info.
75  * @param calType The calibration type (CAL_SEL) as defined in the SMGR API.
76  * @return Returns the platform-independent sensor type or Unknown if no
77  *         match is found.
78  */
getSensorTypeFromSensorId(uint8_t sensorId,uint8_t dataType,uint8_t calType)79 SensorType getSensorTypeFromSensorId(uint8_t sensorId, uint8_t dataType,
80                                      uint8_t calType) {
81   // Here be dragons. These constants below are defined in
82   // sns_smgr_common_v01.h. Refer to the section labelled "Define sensor
83   // identifier" for more details. This function relies on the ordering of
84   // constants provided by their API. Do not change these values without care.
85   // You have been warned!
86   if (dataType == SNS_SMGR_DATA_TYPE_PRIMARY_V01) {
87     if (sensorId >= SNS_SMGR_ID_ACCEL_V01
88         && sensorId < SNS_SMGR_ID_GYRO_V01) {
89       if (calType == SNS_SMGR_CAL_SEL_FULL_CAL_V01) {
90         return SensorType::Accelerometer;
91       } else if (calType == SNS_SMGR_CAL_SEL_FACTORY_CAL_V01) {
92         return SensorType::UncalibratedAccelerometer;
93       }
94     } else if (sensorId >= SNS_SMGR_ID_GYRO_V01
95         && sensorId < SNS_SMGR_ID_MAG_V01) {
96       if (calType == SNS_SMGR_CAL_SEL_FULL_CAL_V01) {
97         return SensorType::Gyroscope;
98       } else if (calType == SNS_SMGR_CAL_SEL_FACTORY_CAL_V01) {
99         return SensorType::UncalibratedGyroscope;
100       }
101     } else if (sensorId >= SNS_SMGR_ID_MAG_V01
102         && sensorId < SNS_SMGR_ID_PRESSURE_V01) {
103       if (calType == SNS_SMGR_CAL_SEL_FULL_CAL_V01) {
104         return SensorType::GeomagneticField;
105       } else if (calType == SNS_SMGR_CAL_SEL_FACTORY_CAL_V01) {
106         return SensorType::UncalibratedGeomagneticField;
107       }
108     } else if (sensorId >= SNS_SMGR_ID_PRESSURE_V01
109         && sensorId < SNS_SMGR_ID_PROX_LIGHT_V01) {
110       return SensorType::Pressure;
111     } else if (sensorId >= SNS_SMGR_ID_PROX_LIGHT_V01
112         && sensorId < SNS_SMGR_ID_HUMIDITY_V01) {
113       return SensorType::Proximity;
114     } else if (sensorId == SNS_SMGR_ID_OEM_SENSOR_09_V01) {
115       return SensorType::StationaryDetect;
116     } else if (sensorId == SNS_SMGR_ID_OEM_SENSOR_10_V01) {
117       return SensorType::InstantMotion;
118     }
119   } else if (dataType == SNS_SMGR_DATA_TYPE_SECONDARY_V01) {
120     if (sensorId >= SNS_SMGR_ID_ACCEL_V01
121         && sensorId < SNS_SMGR_ID_GYRO_V01) {
122       return SensorType::AccelerometerTemperature;
123     } else if (sensorId >= SNS_SMGR_ID_GYRO_V01
124         && sensorId < SNS_SMGR_ID_MAG_V01) {
125       return SensorType::GyroscopeTemperature;
126     } else if ((sensorId >= SNS_SMGR_ID_PROX_LIGHT_V01
127         && sensorId < SNS_SMGR_ID_HUMIDITY_V01)
128         || (sensorId >= SNS_SMGR_ID_ULTRA_VIOLET_V01
129             && sensorId < SNS_SMGR_ID_OBJECT_TEMP_V01)) {
130       return SensorType::Light;
131     }
132   }
133 
134   return SensorType::Unknown;
135 }
136 
137 /**
138  * Converts a reportId as provided by SMGR to a SensorType.
139  *
140  * @param reportId The reportID as provided by the SMGR buffering index.
141  * @return Returns the sensorType that corresponds to the reportId.
142  */
getSensorTypeFromReportId(uint8_t reportId)143 SensorType getSensorTypeFromReportId(uint8_t reportId) {
144   SensorType sensorType;
145   if (reportId < static_cast<uint8_t>(SensorType::SENSOR_TYPE_COUNT)) {
146     sensorType = static_cast<SensorType>(reportId);
147   } else {
148     sensorType = SensorType::Unknown;
149   }
150   return sensorType;
151 }
152 
153 /**
154  * Converts a PlatformSensor to a unique report ID through SensorType. This is
155  * useful in making sensor request.
156  *
157  * @param sensorId The sensorID as provided by the SMGR request for sensor info.
158  * @param dataType The dataType for the sesnor as provided by the SMGR request
159  *                 for sensor info.
160  * @param calType The calibration type (CAL_SEL) as defined in the SMGR API.
161  * @return Returns a unique report ID that is based on SensorType.
162  */
getReportId(uint8_t sensorId,uint8_t dataType,uint8_t calType)163 uint8_t getReportId(uint8_t sensorId, uint8_t dataType, uint8_t calType) {
164   SensorType sensorType = getSensorTypeFromSensorId(
165       sensorId, dataType, calType);
166 
167   CHRE_ASSERT_LOG(sensorType != SensorType::Unknown,
168                   "sensorId %" PRIu8 ", dataType %" PRIu8 ", calType %" PRIu8,
169                   sensorId, dataType, calType);
170   return static_cast<uint8_t>(sensorType);
171 }
172 
173 /**
174  * Checks whether the corresponding sensor is a sencondary temperature sensor.
175  *
176  * @param reportId The reportID as provided by the SMGR buffering index.
177  * @return true if the sensor is a secondary temperature sensor.
178  */
isSecondaryTemperature(uint8_t reportId)179 bool isSecondaryTemperature(uint8_t reportId) {
180   SensorType sensorType = getSensorTypeFromReportId(reportId);
181   return (sensorType == SensorType::AccelerometerTemperature
182           || sensorType == SensorType::GyroscopeTemperature);
183 }
184 
185 /**
186  * Verifies whether the buffering index's report ID matches the expected
187  * indices length.
188  *
189  * @return true if it's a valid pair of indices length and report ID.
190  */
isValidIndicesLength()191 bool isValidIndicesLength() {
192   return ((gSmgrBufferingIndMsg.Indices_len == 1
193            && !isSecondaryTemperature(gSmgrBufferingIndMsg.ReportId))
194           || (gSmgrBufferingIndMsg.Indices_len == 2
195               && isSecondaryTemperature(gSmgrBufferingIndMsg.ReportId)));
196 }
197 
198 /**
199  * Allocates memory and specifies the memory size for an on-change sensor to
200  * store its last data event.
201  *
202  * @param sensorType The sensorType of this sensor.
203  * @param eventSize A non-null pointer to indicate the memory size allocated.
204  * @return Pointer to the memory allocated.
205  */
allocateLastEvent(SensorType sensorType,size_t * eventSize)206 ChreSensorData *allocateLastEvent(SensorType sensorType, size_t *eventSize) {
207   CHRE_ASSERT(eventSize);
208 
209   *eventSize = 0;
210   ChreSensorData *event = nullptr;
211   if (sensorTypeIsOnChange(sensorType)) {
212     SensorSampleType sampleType = getSensorSampleTypeFromSensorType(sensorType);
213     switch (sampleType) {
214       case SensorSampleType::ThreeAxis:
215         *eventSize = sizeof(chreSensorThreeAxisData);
216         break;
217       case SensorSampleType::Float:
218         *eventSize = sizeof(chreSensorFloatData);
219         break;
220       case SensorSampleType::Byte:
221         *eventSize = sizeof(chreSensorByteData);
222         break;
223       case SensorSampleType::Occurrence:
224         *eventSize = sizeof(chreSensorOccurrenceData);
225         break;
226       default:
227         CHRE_ASSERT_LOG(false, "Unhandled sample type");
228         break;
229     }
230 
231     event = static_cast<ChreSensorData *>(memoryAlloc(*eventSize));
232     if (event == nullptr) {
233       *eventSize = 0;
234       FATAL_ERROR("Failed to allocate last event memory for SensorType %d",
235                   static_cast<int>(sensorType));
236     }
237   }
238   return event;
239 }
240 
241 /**
242  * Adds a Platform sensor to the sensor list.
243  *
244  * @param sensorInfo The sensorInfo as provided by the SMGR.
245  * @param calType The calibration type (CAL_SEL) as defined in the SMGR API.
246  * @param sensor The sensor list.
247  */
addPlatformSensor(const sns_smgr_sensor_datatype_info_s_v01 & sensorInfo,uint8_t calType,DynamicVector<PlatformSensor> * sensors)248 void addPlatformSensor(const sns_smgr_sensor_datatype_info_s_v01& sensorInfo,
249                        uint8_t calType,
250                        DynamicVector<PlatformSensor> *sensors) {
251   PlatformSensor platformSensor;
252   platformSensor.sensorId = sensorInfo.SensorID;
253   platformSensor.dataType = sensorInfo.DataType;
254   platformSensor.calType = calType;
255   size_t bytesToCopy = std::min(sizeof(platformSensor.sensorName) - 1,
256                                 static_cast<size_t>(sensorInfo.SensorName_len));
257   memcpy(platformSensor.sensorName, sensorInfo.SensorName, bytesToCopy);
258   platformSensor.sensorName[bytesToCopy] = '\0';
259   platformSensor.minInterval = static_cast<uint64_t>(
260       Seconds(1).toRawNanoseconds() / sensorInfo.MaxSampleRate);
261 
262   // Allocates memory for on-change sensor's last event.
263   SensorType sensorType = getSensorTypeFromSensorId(
264       sensorInfo.SensorID, sensorInfo.DataType, calType);
265   platformSensor.lastEvent = allocateLastEvent(sensorType,
266                                                &platformSensor.lastEventSize);
267 
268   if (!sensors->push_back(std::move(platformSensor))) {
269     FATAL_ERROR("Failed to allocate new sensor: out of memory");
270   }
271 }
272 
273 /**
274  * Converts SMGR ticks to nanoseconds as a uint64_t.
275  *
276  * @param ticks The number of ticks.
277  * @return The number of nanoseconds represented by the ticks value.
278  */
getNanosecondsFromSmgrTicks(uint32_t ticks)279 uint64_t getNanosecondsFromSmgrTicks(uint32_t ticks) {
280   return (ticks * Seconds(1).toRawNanoseconds())
281       / TIMETICK_NOMINAL_FREQ_HZ;
282 }
283 
284 /**
285  * Populate the header
286  */
populateSensorDataHeader(SensorType sensorType,chreSensorDataHeader * header,const sns_smgr_buffering_sample_index_s_v01 & sensorIndex)287 void populateSensorDataHeader(
288     SensorType sensorType, chreSensorDataHeader *header,
289     const sns_smgr_buffering_sample_index_s_v01& sensorIndex) {
290   uint64_t baseTimestamp = getNanosecondsFromSmgrTicks(
291       sensorIndex.FirstSampleTimestamp);
292   memset(header->reserved, 0, sizeof(header->reserved));
293   header->baseTimestamp = baseTimestamp;
294   header->sensorHandle = getSensorHandleFromSensorType(sensorType);
295   header->readingCount = sensorIndex.SampleCount;
296 }
297 
298 /**
299  * Populate three-axis event data.
300  */
populateThreeAxisEvent(SensorType sensorType,chreSensorThreeAxisData * data,const sns_smgr_buffering_sample_index_s_v01 & sensorIndex)301 void populateThreeAxisEvent(
302     SensorType sensorType, chreSensorThreeAxisData *data,
303     const sns_smgr_buffering_sample_index_s_v01& sensorIndex) {
304   populateSensorDataHeader(sensorType, &data->header, sensorIndex);
305 
306   for (size_t i = 0; i < sensorIndex.SampleCount; i++) {
307     const sns_smgr_buffering_sample_s_v01& sensorData =
308         gSmgrBufferingIndMsg.Samples[i + sensorIndex.FirstSampleIdx];
309 
310     // TimeStampOffset has max value of < 2 sec so it will not overflow here.
311     data->readings[i].timestampDelta =
312         getNanosecondsFromSmgrTicks(sensorData.TimeStampOffset);
313 
314     // Convert from SMGR's NED coordinate to Android coordinate.
315     data->readings[i].x = FX_FIXTOFLT_Q16(sensorData.Data[1]);
316     data->readings[i].y = FX_FIXTOFLT_Q16(sensorData.Data[0]);
317     data->readings[i].z = -FX_FIXTOFLT_Q16(sensorData.Data[2]);
318 
319     // Convert from Gauss to micro Tesla
320     if (sensorType == SensorType::GeomagneticField
321         || sensorType == SensorType::UncalibratedGeomagneticField) {
322       data->readings[i].x *= kMicroTeslaPerGauss;
323       data->readings[i].y *= kMicroTeslaPerGauss;
324       data->readings[i].z *= kMicroTeslaPerGauss;
325     }
326   }
327 }
328 
329 /**
330  * Populate float event data.
331  */
populateFloatEvent(SensorType sensorType,chreSensorFloatData * data,const sns_smgr_buffering_sample_index_s_v01 & sensorIndex)332 void populateFloatEvent(
333     SensorType sensorType, chreSensorFloatData *data,
334     const sns_smgr_buffering_sample_index_s_v01& sensorIndex) {
335   populateSensorDataHeader(sensorType, &data->header, sensorIndex);
336 
337   for (size_t i = 0; i < sensorIndex.SampleCount; i++) {
338     const sns_smgr_buffering_sample_s_v01& sensorData =
339         gSmgrBufferingIndMsg.Samples[i + sensorIndex.FirstSampleIdx];
340 
341     // TimeStampOffset has max value of < 2 sec so it will not overflow.
342     data->readings[i].timestampDelta =
343         getNanosecondsFromSmgrTicks(sensorData.TimeStampOffset);
344     data->readings[i].value = FX_FIXTOFLT_Q16(sensorData.Data[0]);
345   }
346 }
347 
348 /**
349  * Populate byte event data.
350  */
populateByteEvent(SensorType sensorType,chreSensorByteData * data,const sns_smgr_buffering_sample_index_s_v01 & sensorIndex)351 void populateByteEvent(
352     SensorType sensorType, chreSensorByteData *data,
353     const sns_smgr_buffering_sample_index_s_v01& sensorIndex) {
354   populateSensorDataHeader(sensorType, &data->header, sensorIndex);
355 
356   for (size_t i = 0; i < sensorIndex.SampleCount; i++) {
357     const sns_smgr_buffering_sample_s_v01& sensorData =
358         gSmgrBufferingIndMsg.Samples[i + sensorIndex.FirstSampleIdx];
359 
360     // TimeStampOffset has max value of < 2 sec so it will not overflow.
361     data->readings[i].timestampDelta =
362         getNanosecondsFromSmgrTicks(sensorData.TimeStampOffset);
363     // Zero out fields invalid and padding0.
364     data->readings[i].value = 0;
365     // SMGR reports 1 in Q16 for near, and 0 for far.
366     data->readings[i].isNear = sensorData.Data[0] ? 1 : 0;
367   }
368 }
369 
370 /**
371  * Populate occurrence event data.
372  */
populateOccurrenceEvent(SensorType sensorType,chreSensorOccurrenceData * data,const sns_smgr_buffering_sample_index_s_v01 & sensorIndex)373 void populateOccurrenceEvent(
374     SensorType sensorType, chreSensorOccurrenceData *data,
375     const sns_smgr_buffering_sample_index_s_v01& sensorIndex) {
376   populateSensorDataHeader(sensorType, &data->header, sensorIndex);
377 
378   for (size_t i = 0; i < sensorIndex.SampleCount; i++) {
379     const sns_smgr_buffering_sample_s_v01& sensorData =
380         gSmgrBufferingIndMsg.Samples[i + sensorIndex.FirstSampleIdx];
381 
382     // TimeStampOffset has max value of < 2 sec so it will not overflow.
383     data->readings[i].timestampDelta =
384         getNanosecondsFromSmgrTicks(sensorData.TimeStampOffset);
385   }
386 }
387 
388 /**
389  * Allocate event memory according to SensorType and populate event readings.
390  */
allocateAndPopulateEvent(SensorType sensorType,const sns_smgr_buffering_sample_index_s_v01 & sensorIndex)391 void *allocateAndPopulateEvent(
392     SensorType sensorType,
393     const sns_smgr_buffering_sample_index_s_v01& sensorIndex) {
394   SensorSampleType sampleType = getSensorSampleTypeFromSensorType(sensorType);
395   size_t memorySize = sizeof(chreSensorDataHeader);
396   switch (sampleType) {
397     case SensorSampleType::ThreeAxis: {
398       memorySize += sensorIndex.SampleCount *
399           sizeof(chreSensorThreeAxisData::chreSensorThreeAxisSampleData);
400       auto *event =
401           static_cast<chreSensorThreeAxisData *>(memoryAlloc(memorySize));
402       if (event != nullptr) {
403         populateThreeAxisEvent(sensorType, event, sensorIndex);
404       }
405       return event;
406     }
407 
408     case SensorSampleType::Float: {
409       memorySize += sensorIndex.SampleCount *
410           sizeof(chreSensorFloatData::chreSensorFloatSampleData);
411       auto *event =
412           static_cast<chreSensorFloatData *>(memoryAlloc(memorySize));
413       if (event != nullptr) {
414         populateFloatEvent(sensorType, event, sensorIndex);
415       }
416       return event;
417     }
418 
419     case SensorSampleType::Byte: {
420       memorySize += sensorIndex.SampleCount *
421           sizeof(chreSensorByteData::chreSensorByteSampleData);
422       auto *event =
423           static_cast<chreSensorByteData *>(memoryAlloc(memorySize));
424       if (event != nullptr) {
425         populateByteEvent(sensorType, event, sensorIndex);
426       }
427       return event;
428     }
429 
430     case SensorSampleType::Occurrence: {
431       memorySize += sensorIndex.SampleCount *
432           sizeof(chreSensorOccurrenceData::chreSensorOccurrenceSampleData);
433       auto *event =
434           static_cast<chreSensorOccurrenceData *>(memoryAlloc(memorySize));
435       if (event != nullptr) {
436         populateOccurrenceEvent(sensorType, event, sensorIndex);
437       }
438       return event;
439     }
440 
441     default:
442       LOGW("Unhandled sensor data %" PRIu8, sensorType);
443       return nullptr;
444   }
445 }
446 
smgrSensorDataEventFree(uint16_t eventType,void * eventData)447 void smgrSensorDataEventFree(uint16_t eventType, void *eventData) {
448   // Events are allocated using the simple memoryAlloc/memoryFree platform
449   // functions.
450   // TODO: Consider using a MemoryPool.
451   memoryFree(eventData);
452 
453   // Remove all requests if it's a one-shot sensor and only after data has been
454   // delivered to all clients.
455   SensorType sensorType = getSensorTypeForSampleEventType(eventType);
456   if (sensorTypeIsOneShot(sensorType)) {
457     EventLoopManagerSingleton::get()->getSensorRequestManager()
458         .removeAllRequests(sensorType);
459   }
460 }
461 
462 /**
463  * A helper function that updates the last event of a in the main thread.
464  * Platform should call this function only for an on-change sensor.
465  *
466  * @param sensorType The SensorType of the sensor.
467  * @param eventData A non-null pointer to the sensor's CHRE event data.
468  */
updateLastEvent(SensorType sensorType,const void * eventData)469 void updateLastEvent(SensorType sensorType, const void *eventData) {
470   CHRE_ASSERT(eventData);
471 
472   auto *header = static_cast<const chreSensorDataHeader *>(eventData);
473   if (header->readingCount != 1) {
474     // TODO: better error handling when SMGR behavior changes.
475     // SMGR delivers one sample per report for on-change sensors.
476     LOGE("%" PRIu16 " samples in an event for on-change sensor %d",
477          header->readingCount, static_cast<int>(sensorType));
478   } else {
479     struct CallbackData {
480       SensorType sensorType;
481       const ChreSensorData *event;
482     };
483     auto *callbackData = memoryAlloc<CallbackData>();
484     if (callbackData == nullptr) {
485       LOGE("Failed to allocate deferred callback memory");
486     } else {
487       callbackData->sensorType = sensorType;
488       callbackData->event = static_cast<const ChreSensorData *>(eventData);
489 
490       auto callback = [](uint16_t /* type */, void *data) {
491         auto *cbData = static_cast<CallbackData *>(data);
492 
493         Sensor *sensor = EventLoopManagerSingleton::get()
494             ->getSensorRequestManager().getSensor(cbData->sensorType);
495         if (sensor != nullptr) {
496           sensor->setLastEvent(cbData->event);
497         }
498         memoryFree(cbData);
499       };
500 
501       // Schedule a deferred callback.
502       if (!EventLoopManagerSingleton::get()->deferCallback(
503           SystemCallbackType::SensorLastEventUpdate, callbackData, callback)) {
504         LOGE("Failed to schedule a deferred callback for sensorType %d",
505              static_cast<int>(sensorType));
506         memoryFree(callbackData);
507       }
508     }  // if (callbackData == nullptr)
509   }
510 }
511 
512 /**
513  * Handles sensor data provided by the SMGR framework.
514  *
515  * @param userHandle The userHandle is used by the QMI decode function.
516  * @param buffer The buffer to decode sensor data from.
517  * @param bufferLength The size of the buffer to decode.
518  */
handleSensorDataIndication(void * userHandle,void * buffer,unsigned int bufferLength)519 void handleSensorDataIndication(void *userHandle, void *buffer,
520                                 unsigned int bufferLength) {
521   int status = qmi_client_message_decode(
522       userHandle, QMI_IDL_INDICATION, SNS_SMGR_BUFFERING_IND_V01, buffer,
523       bufferLength, &gSmgrBufferingIndMsg,
524       sizeof(sns_smgr_buffering_ind_msg_v01));
525   if (status != QMI_NO_ERR) {
526     LOGE("Error parsing sensor data indication %d", status);
527   } else {
528     // We only requested one sensor per request except for a secondary
529     // temperature sensor.
530     bool validReport = isValidIndicesLength();
531     CHRE_ASSERT_LOG(validReport,
532                     "Got buffering indication from %" PRIu32
533                     " sensors with report ID %" PRIu8,
534                     gSmgrBufferingIndMsg.Indices_len,
535                     gSmgrBufferingIndMsg.ReportId);
536     if (validReport) {
537       // Identify the index for the desired sensor. It is always 0 except
538       // possibly for a secondary temperature sensor.
539       uint32_t index = 0;
540       if (isSecondaryTemperature(gSmgrBufferingIndMsg.ReportId)) {
541         index = (gSmgrBufferingIndMsg.Indices[0].DataType
542                  == SNS_SMGR_DATA_TYPE_SECONDARY_V01) ? 0 : 1;
543       }
544       const sns_smgr_buffering_sample_index_s_v01& sensorIndex =
545           gSmgrBufferingIndMsg.Indices[index];
546 
547       // Use ReportID to identify sensors as
548       // gSmgrBufferingIndMsg.Samples[i].Flags are not populated.
549       SensorType sensorType = getSensorTypeFromReportId(
550           gSmgrBufferingIndMsg.ReportId);
551       if (sensorType == SensorType::Unknown) {
552         LOGW("Received sensor sample for unknown sensor %" PRIu8 " %" PRIu8,
553              sensorIndex.SensorId, sensorIndex.DataType);
554       } else if (sensorIndex.SampleCount == 0) {
555         LOGW("Received sensorType %d event with 0 sample",
556              static_cast<int>(sensorType));
557       } else {
558         void *eventData = allocateAndPopulateEvent(sensorType, sensorIndex);
559         if (eventData == nullptr) {
560           LOGW("Dropping event due to allocation failure");
561         } else {
562           // Schedule a deferred callback to update on-change sensor's last
563           // event in the main thread.
564           if (sensorTypeIsOnChange(sensorType)) {
565             updateLastEvent(sensorType, eventData);
566           }
567 
568           EventLoopManagerSingleton::get()->postEvent(
569               getSampleEventTypeForSensorType(sensorType), eventData,
570               smgrSensorDataEventFree);
571         }
572       }
573     }  // if (validReport)
574   }
575 }
576 
577 /**
578  * This callback is invoked by the QMI framework when an asynchronous message is
579  * delivered. Unhandled messages are logged. The signature is defined by the QMI
580  * library.
581  *
582  * @param userHandle The userHandle is used by the QMI library.
583  * @param messageId The type of the message to decode.
584  * @param buffer The buffer to decode.
585  * @param bufferLength The length of the buffer to decode.
586  * @param callbackData Data that is provided as a context to this callback. This
587  *                     is not used in this context.
588  */
platformSensorServiceQmiIndicationCallback(void * userHandle,unsigned int messageId,void * buffer,unsigned int bufferLength,void * callbackData)589 void platformSensorServiceQmiIndicationCallback(void *userHandle,
590                                                 unsigned int messageId,
591                                                 void *buffer,
592                                                 unsigned int bufferLength,
593                                                 void *callbackData) {
594   switch (messageId) {
595     case SNS_SMGR_BUFFERING_IND_V01:
596       handleSensorDataIndication(userHandle, buffer, bufferLength);
597       break;
598     default:
599       LOGW("Received unhandled sensor service message: 0x%x", messageId);
600       break;
601   };
602 }
603 
getNumClients(uint8_t sensorId)604 uint8_t getNumClients(uint8_t sensorId) {
605   for (size_t i = 0; i < gSensorStatusMonitor.size(); i++) {
606     if (gSensorStatusMonitor[i].sensorId == sensorId) {
607       return gSensorStatusMonitor[i].numClients;
608     }
609   }
610   return 0;
611 }
612 
setNumClients(uint8_t sensorId,uint8_t numClients)613 void setNumClients(uint8_t sensorId, uint8_t numClients) {
614   for (size_t i = 0; i < gSensorStatusMonitor.size(); i++) {
615     if (gSensorStatusMonitor[i].sensorId == sensorId) {
616       gSensorStatusMonitor[i].numClients = numClients;
617     }
618   }
619 }
620 
621 /**
622  * Handles sensor status provided by the SMGR framework.
623  *
624  * @param userHandle The userHandle is used by the QMI decode function.
625  * @param buffer The buffer to decode sensor data from.
626  * @param bufferLength The size of the buffer to decode.
627  */
handleSensorStatusMonitorIndication(void * userHandle,void * buffer,unsigned int bufferLength)628 void handleSensorStatusMonitorIndication(void *userHandle, void *buffer,
629                                          unsigned int bufferLength) {
630   sns_smgr_sensor_status_monitor_ind_msg_v02 smgrMonitorIndMsg;
631 
632   int status = qmi_client_message_decode(
633       userHandle, QMI_IDL_INDICATION, SNS_SMGR_SENSOR_STATUS_MONITOR_IND_V02,
634       buffer, bufferLength, &smgrMonitorIndMsg, sizeof(smgrMonitorIndMsg));
635   if (status != QMI_NO_ERR) {
636     LOGE("Error parsing sensor status monitor indication %d", status);
637   } else {
638     uint8_t numClients = getNumClients(smgrMonitorIndMsg.sensor_id);
639     if (numClients != smgrMonitorIndMsg.num_clients) {
640       LOGD("Status: id %" PRIu64 ", num clients: curr %" PRIu8 " new %" PRIu8,
641            smgrMonitorIndMsg.sensor_id, numClients,
642            smgrMonitorIndMsg.num_clients);
643       setNumClients(smgrMonitorIndMsg.sensor_id,
644                     smgrMonitorIndMsg.num_clients);
645 
646       //TODO: add onNumClientsChange()
647     }
648   }
649 }
650 
651 /**
652  * This callback is invoked by the QMI framework when an asynchronous message is
653  * delivered. Unhandled messages are logged. The signature is defined by the QMI
654  * library.
655  *
656  * @param userHandle The userHandle is used by the QMI library.
657  * @param messageId The type of the message to decode.
658  * @param buffer The buffer to decode.
659  * @param bufferLength The length of the buffer to decode.
660  * @param callbackData Data that is provided as a context to this callback. This
661  *                     is not used in this context.
662  */
platformSensorInternalServiceQmiIndicationCallback(void * userHandle,unsigned int messageId,void * buffer,unsigned int bufferLength,void * callbackData)663 void platformSensorInternalServiceQmiIndicationCallback(void *userHandle,
664     unsigned int messageId, void *buffer, unsigned int bufferLength,
665     void *callbackData) {
666   switch (messageId) {
667     case SNS_SMGR_SENSOR_STATUS_MONITOR_IND_V02:
668       handleSensorStatusMonitorIndication(userHandle, buffer, bufferLength);
669       break;
670     default:
671       LOGW("Received unhandled sensor internal service message: 0x%x",
672            messageId);
673       break;
674   };
675 }
676 
setSensorStatusMonitor(uint8_t sensorId,bool enable)677 void setSensorStatusMonitor(uint8_t sensorId, bool enable) {
678   sns_smgr_sensor_status_monitor_req_msg_v02 monitorRequest;
679   sns_smgr_sensor_status_monitor_resp_msg_v02 monitorResponse;
680   monitorRequest.sensor_id = sensorId;
681   monitorRequest.registering = enable ? TRUE : FALSE;
682 
683   qmi_client_error_type status = qmi_client_send_msg_sync(
684       gPlatformSensorInternalServiceQmiClientHandle,
685       SNS_SMGR_SENSOR_STATUS_MONITOR_REQ_V02,
686       &monitorRequest, sizeof(monitorRequest),
687       &monitorResponse, sizeof(monitorResponse), kQmiTimeoutMs);
688 
689   if (status != QMI_NO_ERR) {
690     LOGE("Error setting sensor status monitor: %d", status);
691   } else if (monitorResponse.resp.sns_result_t != SNS_RESULT_SUCCESS_V01) {
692     LOGE("Sensor status monitor request failed with error: %" PRIu8
693          " sensor ID %" PRIu8 " enable %d",
694          monitorResponse.resp.sns_err_t, sensorId, enable);
695   }
696 }
697 
698 /**
699  * Requests the sensors for a given sensor ID and appends them to the provided
700  * list of sensors. If an error occurs, false is returned.
701  *
702  * @param sensorId The sensor ID to request sensor info for.
703  * @param sensors The list of sensors to append newly found sensors to.
704  * @return Returns false if an error occurs.
705  */
getSensorsForSensorId(uint8_t sensorId,DynamicVector<PlatformSensor> * sensors)706 bool getSensorsForSensorId(uint8_t sensorId,
707                            DynamicVector<PlatformSensor> *sensors) {
708   sns_smgr_single_sensor_info_req_msg_v01 sensorInfoRequest;
709   sns_smgr_single_sensor_info_resp_msg_v01 sensorInfoResponse;
710 
711   sensorInfoRequest.SensorID = sensorId;
712 
713   qmi_client_error_type status = qmi_client_send_msg_sync(
714       gPlatformSensorServiceQmiClientHandle, SNS_SMGR_SINGLE_SENSOR_INFO_REQ_V01,
715       &sensorInfoRequest, sizeof(sns_smgr_single_sensor_info_req_msg_v01),
716       &sensorInfoResponse, sizeof(sns_smgr_single_sensor_info_resp_msg_v01),
717       kQmiTimeoutMs);
718 
719   bool success = false;
720   if (status != QMI_NO_ERR) {
721     LOGE("Error requesting single sensor info: %d", status);
722   } else if (sensorInfoResponse.Resp.sns_result_t != SNS_RESULT_SUCCESS_V01) {
723     LOGE("Single sensor info request failed with error: %d",
724          sensorInfoResponse.Resp.sns_err_t);
725   } else {
726     bool isSensorIdSupported = false;
727     const sns_smgr_sensor_info_s_v01& sensorInfoList =
728         sensorInfoResponse.SensorInfo;
729     for (uint32_t i = 0; i < sensorInfoList.data_type_info_len; i++) {
730       const sns_smgr_sensor_datatype_info_s_v01& sensorInfo =
731           sensorInfoList.data_type_info[i];
732       LOGD("SensorID %" PRIu8 ", DataType %" PRIu8 ", MaxRate %" PRIu16
733            "Hz, SensorName %s",
734            sensorInfo.SensorID, sensorInfo.DataType,
735            sensorInfo.MaxSampleRate, sensorInfo.SensorName);
736 
737       SensorType sensorType = getSensorTypeFromSensorId(
738           sensorInfo.SensorID, sensorInfo.DataType,
739           SNS_SMGR_CAL_SEL_FULL_CAL_V01);
740       if (sensorType != SensorType::Unknown) {
741         isSensorIdSupported = true;
742         addPlatformSensor(sensorInfo, SNS_SMGR_CAL_SEL_FULL_CAL_V01, sensors);
743 
744         // Add an uncalibrated version if defined.
745         SensorType uncalibratedType = getSensorTypeFromSensorId(
746             sensorInfo.SensorID, sensorInfo.DataType,
747             SNS_SMGR_CAL_SEL_FACTORY_CAL_V01);
748         if (sensorType != uncalibratedType) {
749           addPlatformSensor(sensorInfo, SNS_SMGR_CAL_SEL_FACTORY_CAL_V01,
750                             sensors);
751         }
752       }
753     }
754 
755     // If CHRE supports sensors with this sensor ID, enable its status monitor.
756     if (isSensorIdSupported) {
757       // Initialize monitor status before making a QMI request.
758       SensorStatus sensorStatus;
759       sensorStatus.sensorId = sensorId;
760       sensorStatus.numClients = 0;
761       gSensorStatusMonitor.push_back(sensorStatus);
762 
763       setSensorStatusMonitor(sensorId, true);
764     }
765     success = true;
766   }
767 
768   return success;
769 }
770 
771 /**
772  * Converts a SensorMode into an SMGR request action. When the net request for
773  * a sensor is considered to be active an add operation is required for the
774  * SMGR request. When the sensor becomes inactive the request is deleted.
775  *
776  * @param mode The sensor mode.
777  * @return Returns the SMGR request action given the sensor mode.
778  */
getSmgrRequestActionForMode(SensorMode mode)779 uint8_t getSmgrRequestActionForMode(SensorMode mode) {
780   if (sensorModeIsActive(mode)) {
781     return SNS_SMGR_BUFFERING_ACTION_ADD_V01;
782   } else {
783     return SNS_SMGR_BUFFERING_ACTION_DELETE_V01;
784   }
785 }
786 
787 /**
788  * Populates a sns_smgr_buffering_req_msg_v01 struct to request sensor data.
789  *
790  * @param request The new request to set this sensor to.
791  * @param sensorId The sensorID as provided by the SMGR request for sensor info.
792  * @param dataType The dataType for the sesnor as provided by the SMGR request
793  *                 for sensor info.
794  * @param calType The calibration type (CAL_SEL) as defined in the SMGR API.
795  * @param minInterval The minimum interval allowed by this sensor.
796  * @param sensorDataRequest The pointer to the data request to be populated.
797  */
populateSensorRequest(const SensorRequest & chreRequest,uint8_t sensorId,uint8_t dataType,uint8_t calType,uint64_t minInterval,sns_smgr_buffering_req_msg_v01 * sensorRequest)798 void populateSensorRequest(
799     const SensorRequest& chreRequest, uint8_t sensorId, uint8_t dataType,
800     uint8_t calType, uint64_t minInterval,
801     sns_smgr_buffering_req_msg_v01 *sensorRequest) {
802   // Zero the fields in the request. All mandatory and unused fields are
803   // specified to be set to false or zero so this is safe.
804   memset(sensorRequest, 0, sizeof(*sensorRequest));
805 
806   // Reconstruts a request as CHRE API requires one-shot sensors to be
807   // requested with pre-defined interval and latency that may not be accepted
808   // by SMGR.
809   bool isOneShot = sensorTypeIsOneShot(getSensorTypeFromSensorId(
810       sensorId, dataType, calType));
811   SensorRequest request(
812       chreRequest.getMode(),
813       isOneShot ? Nanoseconds(minInterval) : chreRequest.getInterval(),
814       isOneShot ? Nanoseconds(0) : chreRequest.getLatency());
815 
816   // Build the request for one sensor at the requested rate. An add action for a
817   // ReportID that is already in use causes a replacement of the last request.
818   sensorRequest->ReportId = getReportId(sensorId, dataType, calType);
819   sensorRequest->Action = getSmgrRequestActionForMode(request.getMode());
820   // If latency < interval, request to SMGR would fail.
821   Nanoseconds batchingInterval =
822       (request.getLatency() > request.getInterval()) ?
823       request.getLatency() : request.getInterval();
824   sensorRequest->ReportRate = intervalToSmgrQ16ReportRate(batchingInterval);
825   sensorRequest->Item_len = 1; // One sensor per request if possible.
826   sensorRequest->Item[0].SensorId = sensorId;
827   sensorRequest->Item[0].DataType = dataType;
828   sensorRequest->Item[0].Decimation = SNS_SMGR_DECIMATION_RECENT_SAMPLE_V01;
829   sensorRequest->Item[0].Calibration = calType;
830   sensorRequest->Item[0].SamplingRate =
831       intervalToSmgrSamplingRate(request.getInterval());
832 
833   // Add a dummy primary sensor to accompany a secondary temperature sensor.
834   // This is requred by the SMGR. The primary sensor is requested with the same
835   // (low) rate and the same latency, whose response data will be ignored.
836   if (isSecondaryTemperature(sensorRequest->ReportId)) {
837     sensorRequest->Item_len = 2;
838     sensorRequest->Item[1].SensorId = sensorId;
839     sensorRequest->Item[1].DataType = SNS_SMGR_DATA_TYPE_PRIMARY_V01;
840     sensorRequest->Item[1].Decimation = SNS_SMGR_DECIMATION_RECENT_SAMPLE_V01;
841     sensorRequest->Item[1].Calibration = SNS_SMGR_CAL_SEL_FULL_CAL_V01;
842     sensorRequest->Item[1].SamplingRate = sensorRequest->Item[0].SamplingRate;
843   }
844 }
845 
846 }  // anonymous namespace
847 
~PlatformSensor()848 PlatformSensor::~PlatformSensor() {
849   if (lastEvent != nullptr) {
850     LOGD("Releasing lastEvent: 0x%p, id %" PRIu8 ", type %" PRIu8 ", cal %"
851          PRIu8 ", size %zu",
852          lastEvent, sensorId, dataType, calType, lastEventSize);
853     memoryFree(lastEvent);
854   }
855 }
856 
init()857 void PlatformSensor::init() {
858   // sns_smgr_api_v01
859   qmi_idl_service_object_type sensorServiceObject =
860       SNS_SMGR_SVC_get_service_object_v01();
861   if (sensorServiceObject == nullptr) {
862     FATAL_ERROR("Failed to obtain the SNS SMGR service instance");
863   }
864 
865   qmi_client_os_params sensorContextOsParams;
866   qmi_client_error_type status = qmi_client_init_instance(sensorServiceObject,
867       QMI_CLIENT_INSTANCE_ANY, &platformSensorServiceQmiIndicationCallback,
868       nullptr, &sensorContextOsParams, kQmiTimeoutMs,
869       &gPlatformSensorServiceQmiClientHandle);
870   if (status != QMI_NO_ERR) {
871     FATAL_ERROR("Failed to initialize the sensor service QMI client: %d",
872                 status);
873   }
874 
875   // sns_smgr_interal_api_v02
876   sensorServiceObject = SNS_SMGR_INTERNAL_SVC_get_service_object_v02();
877   if (sensorServiceObject == nullptr) {
878     FATAL_ERROR("Failed to obtain the SNS SMGR internal service instance");
879   }
880 
881   status = qmi_client_init_instance(sensorServiceObject,
882       QMI_CLIENT_INSTANCE_ANY,
883       &platformSensorInternalServiceQmiIndicationCallback, nullptr,
884       &sensorContextOsParams, kQmiTimeoutMs,
885       &gPlatformSensorInternalServiceQmiClientHandle);
886   if (status != QMI_NO_ERR) {
887     FATAL_ERROR("Failed to initialize the sensor internal service QMI client: "
888                 "%d", status);
889   }
890 }
891 
deinit()892 void PlatformSensor::deinit() {
893   qmi_client_release(&gPlatformSensorServiceQmiClientHandle);
894   gPlatformSensorServiceQmiClientHandle = nullptr;
895 
896   // Removing all sensor status monitor requests. Releaseing a QMI client also
897   // releases all of its subscriptions.
898   gSensorStatusMonitor.clear();
899 
900   qmi_client_release(&gPlatformSensorInternalServiceQmiClientHandle);
901   gPlatformSensorInternalServiceQmiClientHandle = nullptr;
902 }
903 
getSensors(DynamicVector<PlatformSensor> * sensors)904 bool PlatformSensor::getSensors(DynamicVector<PlatformSensor> *sensors) {
905   CHRE_ASSERT(sensors);
906 
907   sns_smgr_all_sensor_info_req_msg_v01 sensorListRequest;
908   sns_smgr_all_sensor_info_resp_msg_v01 sensorListResponse;
909 
910   qmi_client_error_type status = qmi_client_send_msg_sync(
911       gPlatformSensorServiceQmiClientHandle, SNS_SMGR_ALL_SENSOR_INFO_REQ_V01,
912       &sensorListRequest, sizeof(sns_smgr_all_sensor_info_req_msg_v01),
913       &sensorListResponse, sizeof(sns_smgr_all_sensor_info_resp_msg_v01),
914       kQmiTimeoutMs);
915 
916   bool success = false;
917   if (status != QMI_NO_ERR) {
918     LOGE("Error requesting sensor list: %d", status);
919   } else if (sensorListResponse.Resp.sns_result_t != SNS_RESULT_SUCCESS_V01) {
920     LOGE("Sensor list lequest failed with error: %d",
921          sensorListResponse.Resp.sns_err_t);
922   } else {
923     success = true;
924     for (uint32_t i = 0; i < sensorListResponse.SensorInfo_len; i++) {
925       uint8_t sensorId = sensorListResponse.SensorInfo[i].SensorID;
926       if (!getSensorsForSensorId(sensorId, sensors)) {
927         success = false;
928         break;
929       }
930     }
931   }
932 
933   return success;
934 }
935 
setRequest(const SensorRequest & request)936 bool PlatformSensor::setRequest(const SensorRequest& request) {
937   // Allocate request and response for the sensor request.
938   auto *sensorRequest = memoryAlloc<sns_smgr_buffering_req_msg_v01>();
939   auto *sensorResponse = memoryAlloc<sns_smgr_buffering_resp_msg_v01>();
940 
941   bool success = false;
942   if (sensorRequest == nullptr || sensorResponse == nullptr) {
943     LOGE("Failed to allocated sensor request/response: out of memory");
944   } else {
945     populateSensorRequest(request, this->sensorId, this->dataType,
946         this->calType, this->getMinInterval(), sensorRequest);
947 
948     qmi_client_error_type status = qmi_client_send_msg_sync(
949         gPlatformSensorServiceQmiClientHandle, SNS_SMGR_BUFFERING_REQ_V01,
950         sensorRequest, sizeof(*sensorRequest),
951         sensorResponse, sizeof(*sensorResponse),
952         kQmiTimeoutMs);
953 
954     if (status != QMI_NO_ERR) {
955       LOGE("Error requesting sensor data: %d", status);
956     } else if (sensorResponse->Resp.sns_result_t != SNS_RESULT_SUCCESS_V01
957         || (sensorResponse->AckNak != SNS_SMGR_RESPONSE_ACK_SUCCESS_V01
958             && sensorResponse->AckNak != SNS_SMGR_RESPONSE_ACK_MODIFIED_V01)) {
959       LOGE("Sensor data request failed with error: %d, AckNak: %d",
960            sensorResponse->Resp.sns_err_t, sensorResponse->AckNak);
961     } else {
962       success = true;
963     }
964   }
965 
966   memoryFree(sensorRequest);
967   memoryFree(sensorResponse);
968   return success;
969 }
970 
getSensorType() const971 SensorType PlatformSensor::getSensorType() const {
972   return getSensorTypeFromSensorId(this->sensorId, this->dataType,
973                                    this->calType);
974 }
975 
getMinInterval() const976 uint64_t PlatformSensor::getMinInterval() const {
977   return minInterval;
978 }
979 
getSensorName() const980 const char *PlatformSensor::getSensorName() const {
981   return sensorName;
982 }
983 
operator =(PlatformSensor && other)984 PlatformSensor& PlatformSensor::operator=(PlatformSensor&& other) {
985   sensorId = other.sensorId;
986   dataType = other.dataType;
987   calType = other.calType;
988   memcpy(sensorName, other.sensorName, SNS_SMGR_MAX_SENSOR_NAME_SIZE_V01);
989   minInterval = other.minInterval;
990 
991   lastEvent = other.lastEvent;
992   other.lastEvent = nullptr;
993 
994   lastEventSize = other.lastEventSize;
995   other.lastEventSize = 0;
996   return *this;
997 }
998 
getLastEvent() const999 ChreSensorData *PlatformSensor::getLastEvent() const {
1000   return lastEvent;
1001 }
1002 
setLastEvent(const ChreSensorData * event)1003 void PlatformSensor::setLastEvent(const ChreSensorData *event) {
1004   memcpy(lastEvent, event, lastEventSize);
1005 }
1006 
1007 }  // namespace chre
1008