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