platform_sensor.cc revision 83a6e8255099bcbd0758c1dbe6e002bb8542ec4d
138bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol/*
238bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol * Copyright (C) 2016 The Android Open Source Project
338bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol *
438bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol * Licensed under the Apache License, Version 2.0 (the "License");
538bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol * you may not use this file except in compliance with the License.
638bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol * You may obtain a copy of the License at
738bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol *
838bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol *      http://www.apache.org/licenses/LICENSE-2.0
938bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol *
1038bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol * Unless required by applicable law or agreed to in writing, software
1138bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol * distributed under the License is distributed on an "AS IS" BASIS,
1238bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1338bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol * See the License for the specific language governing permissions and
1438bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol * limitations under the License.
1538bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol */
1638bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol
17cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol#include <cinttypes>
18cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol
1938bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignolextern "C" {
2038bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol
2183a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol#include "fixed_point.h"
2238bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol#include "qmi_client.h"
2338bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol#include "sns_smgr_api_v01.h"
2483a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol#include "timetick.h"
2538bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol
2638bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol}  // extern "C"
2738bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol
2883a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol#include "chre_api/chre/sensor.h"
2938bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol#include "chre/platform/fatal_error.h"
3038bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol#include "chre/platform/log.h"
3138bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol#include "chre/platform/sensor_context.h"
3280b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol#include "chre/target_platform/sensor_context_util.h"
3380b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol
3480b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignolnamespace {
3580b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol
3680b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol//! The QMI client handle.
3780b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignolqmi_client_type gSensorContextQmiClientHandle = nullptr;
3880b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol
3983a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol//! A sensor report indication for deserializing sensor sample indications
4083a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol//! into. This global instance is used to avoid thrashy use of the heap by
4183a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol//! allocating and freeing this on the heap for every new sensor sample. This
4283a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol//! relies on the assumption that the QMI callback is not reentrant.
4383a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignolsns_smgr_periodic_report_ind_msg_v01 gSensorReportIndication;
4483a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol
4580b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol//! The next ReportID to assign to a request for sensor data. The SMGR APIs use
4680b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol//! a ReportID to track requests. We will use one report ID per sensor to keep
4780b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol//! requests separate. Zero is reserved. If this wraps around 255, this is
4880b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol//! considered a fatal error. This will never happen because the report ID is
4980b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol//! assigned to the sensor when it is first enabled and reused for all future
5080b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol//! requests.
5180b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignoluint8_t gNextSensorReportId = 1;
5280b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol
5380b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol}  // anonymous namespace
5438bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol
5538bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignolnamespace chre {
5638bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol
5738bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol//! The timeout for QMI messages in milliseconds.
5838bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignolconstexpr uint32_t kQmiTimeoutMs = 1000;
5938bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol
6080b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol/**
6180b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol * Generates a unique ReportID to provide to a request to the SMGR APIs for
6280b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol * sensor data. Each sensor is assigned a unique ReportID and as such there will
6380b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol * be few of these. If more than 255 are created, it is a fatal error.
6480b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol *
6580b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol * @return A unique ReportID for a request of sensor data.
6680b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol */
6780b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignoluint8_t generateUniqueReportId() {
6880b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  uint8_t reportId = gNextSensorReportId++;
6980b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  if (reportId == 0) {
7080b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol    FATAL_ERROR("Unique ReportIDs exhausted. Too many sensor requests");
7180b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  }
7280b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol
7380b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  return reportId;
7480b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol}
7538bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol
7683a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol/**
7783a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * Converts a sensorId and dataType as provided by SMGR to a CHRE SensorType as
7883a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * used by platform-independent CHRE code.
7983a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol *
8083a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * @param sensorId The sensorID as provided by the SMGR request for sensor info.
8183a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * @param dataType The dataType for the sesnor as provided by the SMGR request
8283a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol *                 for sensor info.
8383a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * @return Returns the platform-independent CHRE sensor type or Unknown if no
8483a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol *         match is found.
8583a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol */
86cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew RossignolSensorType getSensorTypeFromSensorId(uint8_t sensorId, uint8_t dataType) {
87cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  // Here be dragons. These constants below are defined in
88cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  // sns_smgr_common_v01.h. Refer to the section labelled "Define sensor
89cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  // identifier" for more details. This function relies on the ordering of
90cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  // constants provided by their API. Do not change these values without care.
91cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  // You have been warned!
92cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  if (dataType == SNS_SMGR_DATA_TYPE_PRIMARY_V01) {
93cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    if (sensorId >= SNS_SMGR_ID_ACCEL_V01
94cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol        && sensorId < SNS_SMGR_ID_GYRO_V01) {
95cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      return SensorType::Accelerometer;
96cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    } else if (sensorId >= SNS_SMGR_ID_GYRO_V01
97cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol        && sensorId < SNS_SMGR_ID_MAG_V01) {
98cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      return SensorType::Gyroscope;
99cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    } else if (sensorId >= SNS_SMGR_ID_MAG_V01
100cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol        && sensorId < SNS_SMGR_ID_PRESSURE_V01) {
101cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      return SensorType::GeomagneticField;
102cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    } else if (sensorId >= SNS_SMGR_ID_PRESSURE_V01
103cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol        && sensorId < SNS_SMGR_ID_PROX_LIGHT_V01) {
104cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      return SensorType::Pressure;
105cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    } else if (sensorId >= SNS_SMGR_ID_PROX_LIGHT_V01
106cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol        && sensorId < SNS_SMGR_ID_HUMIDITY_V01) {
107cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      return SensorType::Proximity;
108cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    }
109cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  } else if (dataType == SNS_SMGR_DATA_TYPE_SECONDARY_V01) {
110cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    if ((sensorId >= SNS_SMGR_ID_PROX_LIGHT_V01
111cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol            && sensorId < SNS_SMGR_ID_HUMIDITY_V01)
112cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol        || (sensorId >= SNS_SMGR_ID_ULTRA_VIOLET_V01
113cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol            && sensorId < SNS_SMGR_ID_OBJECT_TEMP_V01)) {
114cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      return SensorType::Light;
115cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    }
116cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  }
117cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol
118cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  return SensorType::Unknown;
119cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol}
120cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol
121cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol/**
12283a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * Converts SMGR ticks to nanoseconds as a uint64_t.
12383a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol *
12483a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * @param ticks The number of ticks.
12583a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * @return The number of nanoseconds represented by the ticks value.
12683a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol */
12783a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignoluint64_t getNanosecondsFromSmgrTicks(uint32_t ticks) {
12883a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  return (ticks * Seconds(1).toRawNanoseconds())
12983a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol      / TIMETICK_NOMINAL_FREQ_HZ;
13083a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol}
13183a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol
13283a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol/**
13383a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * Handles sensor data provided by the SMGR framework. This function does not
13483a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * return but logs errors and warnings.
13583a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol *
13683a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * @param userHandle The userHandle is used by the QMI decode function.
13783a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * @param buffer The buffer to decode sensor data from.
13883a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * @param bufferLength The size of the buffer to decode.
13983a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol */
14083a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignolvoid handleSensorDataIndication(void *userHandle, void *buffer,
14183a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol                                unsigned int bufferLength) {
14283a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  int status = qmi_client_message_decode(
14383a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol      userHandle, QMI_IDL_INDICATION, SNS_SMGR_REPORT_IND_V01, buffer,
14483a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol      bufferLength, &gSensorReportIndication,
14583a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol      sizeof(sns_smgr_periodic_report_ind_msg_v01));
14683a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  if (status != QMI_NO_ERR) {
14783a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol    LOGE("Error parsing sensor data indication %d", status);
14883a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol    return;
14983a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  }
15083a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol
15183a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  // TODO: We send one event per sample at the moment. The CHRE API allows for
15283a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  // multiple samples to be delivered per batch which should improve
15383a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  // performance. Switch to that implementation.
15483a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  for (size_t i = 0; i < gSensorReportIndication.Item_len; i++) {
15583a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol    const sns_smgr_data_item_s_v01& sensorData =
15683a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol        gSensorReportIndication.Item[i];
15783a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol    SensorType sensorType = getSensorTypeFromSensorId(sensorData.SensorId,
15883a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol                                                      sensorData.DataType);
15983a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol    if (sensorType == SensorType::Unknown) {
16083a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol      LOGW("Received sensor sample for unknown sensor %" PRIu8 " %" PRIu8,
16183a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol           sensorData.SensorId, sensorData.DataType);
16283a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol    } else {
16383a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol      chreSensorDataHeader header;
16483a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol      memset(&header.reserved, 0, sizeof(header.reserved));
16583a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol      header.baseTimestamp = getNanosecondsFromSmgrTicks(sensorData.TimeStamp);
16683a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol      header.sensorHandle = 0xbeef; // TODO: Get a real sensor handle.
16783a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol      header.readingCount = 1;
16883a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol
16983a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol      if (sensorType == SensorType::Accelerometer
17083a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol          || sensorType == SensorType::Gyroscope
17183a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol          || sensorType == SensorType::GeomagneticField) {
17283a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol        chreSensorThreeAxisData *data = memoryAlloc<chreSensorThreeAxisData>();
17383a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol        if (data == nullptr) {
17483a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol          LOGW("Dropping event due to allocation failure");
17583a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol        } else {
17683a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol          data->header = header;
17783a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol          data->readings[0].timestampDelta = 0;
17883a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol          data->readings[0].x = FX_FIXTOFLT_Q16(sensorData.ItemData[0]);
17983a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol          data->readings[0].y = FX_FIXTOFLT_Q16(sensorData.ItemData[1]);
18083a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol          data->readings[0].z = FX_FIXTOFLT_Q16(sensorData.ItemData[2]);
18183a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol
18283a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol          // TODO: Post the event to the TBD SensorRequestManager.
18383a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol          LOGD("Accel sample at %" PRIu64 ": %f %f %f",
18483a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol               data->header.baseTimestamp,
18583a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol               data->readings[0].x, data->readings[0].y, data->readings[0].z);
18683a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol          memoryFree(data);
18783a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol        }
18883a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol      } else {
18983a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol        LOGW("Unhandled sensor data %" PRIu8, sensorType);
19083a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol      }
19183a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol    }
19283a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  }
19383a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol}
19483a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol
19583a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol/**
19683a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * This callback is invoked by the QMI framework when an asynchronous message is
19783a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * delivered. Unhandled messages are logged. The signature is defined by the QMI
19883a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * library.
19983a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol *
20083a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * @param userHandle The userHandle is used by the QMI library.
20183a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * @param messageId The type of the message to decode.
20283a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * @param buffer The buffer to decode.
20383a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * @param bufferLength The length of the buffer to decode.
20483a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * @param callbackData Data that is provided as a context to this callback. This
20583a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol *                     is not used in this context.
20683a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol */
20783a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignolvoid sensorContextQmiIndicationCallback(void *userHandle,
20883a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol                                        unsigned int messageId,
20983a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol                                        void *buffer, unsigned int bufferLength,
21083a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol                                        void *callbackData) {
21183a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  switch (messageId) {
21283a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol    case SNS_SMGR_REPORT_IND_V01:
21383a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol      handleSensorDataIndication(userHandle, buffer, bufferLength);
21483a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol      break;
21583a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol    default:
21683a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol      LOGW("Received unhandled sensor QMI indication message: %u", messageId);
21783a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol      break;
21883a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  };
21983a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol}
22083a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol
22183a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignolvoid SensorContext::init() {
22283a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  qmi_idl_service_object_type sensorServiceObject =
22383a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol      SNS_SMGR_SVC_get_service_object_v01();
22483a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  if (sensorServiceObject == nullptr) {
22583a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol    FATAL_ERROR("Failed to obtain the SNS SMGR service instance");
22683a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  }
22783a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol
22883a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  qmi_client_os_params sensorContextOsParams;
22983a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  qmi_client_error_type status = qmi_client_init_instance(sensorServiceObject,
23083a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol      QMI_CLIENT_INSTANCE_ANY, &sensorContextQmiIndicationCallback, nullptr,
23183a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol      &sensorContextOsParams, kQmiTimeoutMs, &gSensorContextQmiClientHandle);
23283a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  if (status != QMI_NO_ERR) {
23383a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol    FATAL_ERROR("Failed to initialize the sensors QMI client: %d", status);
23483a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  }
23583a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol}
23683a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol
23783a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignolvoid SensorContext::deinit() {
23883a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  qmi_client_release(&gSensorContextQmiClientHandle);
23983a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  gSensorContextQmiClientHandle = nullptr;
24083a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol}
24183a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol
24283a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol/**
243cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol * Requests the sensors for a given sensor ID and appends them to the provided
244cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol * list of sensors. If an error occurs, false is returned.
245cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol *
246cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol * @param sensorId The sensor ID to request sensor info for.
247cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol * @param sensors The list of sensors to append newly found sensors to.
248cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol * @return Returns false if an error occurs.
249cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol */
250cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignolbool getSensorsForSensorId(uint8_t sensorId,
251cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol                           DynamicVector<PlatformSensor> *sensors) {
252cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  sns_smgr_single_sensor_info_req_msg_v01 sensorInfoRequest;
253cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  sns_smgr_single_sensor_info_resp_msg_v01 sensorInfoResponse;
254cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol
255cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  sensorInfoRequest.SensorID = sensorId;
256cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol
257cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  qmi_client_error_type status = qmi_client_send_msg_sync(
258cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      gSensorContextQmiClientHandle, SNS_SMGR_SINGLE_SENSOR_INFO_REQ_V01,
259cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      &sensorInfoRequest, sizeof(sns_smgr_single_sensor_info_req_msg_v01),
260cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      &sensorInfoResponse, sizeof(sns_smgr_single_sensor_info_resp_msg_v01),
261cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      kQmiTimeoutMs);
262cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol
263cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  bool success = false;
264cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  if (status != QMI_NO_ERR) {
265cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    LOGE("Error requesting single sensor info: %d", status);
266cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  } else if (sensorInfoResponse.Resp.sns_result_t != SNS_RESULT_SUCCESS_V01) {
267cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    LOGE("Single sensor info request failed with error: %d",
268cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol         sensorInfoResponse.Resp.sns_err_t);
269cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  } else {
270cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    const sns_smgr_sensor_info_s_v01& sensorInfoList =
271cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol        sensorInfoResponse.SensorInfo;
272cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    for (uint32_t i = 0; i < sensorInfoList.data_type_info_len; i++) {
273cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      const sns_smgr_sensor_datatype_info_s_v01 *sensorInfo =
274cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol          &sensorInfoList.data_type_info[i];
275cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      SensorType sensorType = getSensorTypeFromSensorId(sensorInfo->SensorID,
276cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol                                                        sensorInfo->DataType);
277cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      if (sensorType != SensorType::Unknown) {
278cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol        PlatformSensor platformSensor(sensorType);
27980b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol        platformSensor.mSensorId = sensorInfo->SensorID;
28080b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol        platformSensor.mDataType = sensorInfo->DataType;
281cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol        if (!sensors->push_back(platformSensor)) {
282cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol          FATAL_ERROR("Failed to allocate new sensor: out of memory");
283cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol        }
284cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      }
285cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    }
286cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol
287cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    success = true;
288cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  }
289cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol
290cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  return success;
291cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol}
292cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol
293cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignolbool SensorContext::getSensors(DynamicVector<PlatformSensor> *sensors) {
294cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  CHRE_ASSERT(sensors);
295cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol
296cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  sns_smgr_all_sensor_info_req_msg_v01 sensorListRequest;
297cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  sns_smgr_all_sensor_info_resp_msg_v01 sensorListResponse;
298cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol
299cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  qmi_client_error_type status = qmi_client_send_msg_sync(
300cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      gSensorContextQmiClientHandle, SNS_SMGR_ALL_SENSOR_INFO_REQ_V01,
301cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      &sensorListRequest, sizeof(sns_smgr_all_sensor_info_req_msg_v01),
302cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      &sensorListResponse, sizeof(sns_smgr_all_sensor_info_resp_msg_v01),
303cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      kQmiTimeoutMs);
304cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol
305cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  bool success = false;
306cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  if (status != QMI_NO_ERR) {
307cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    LOGE("Error requesting sensor list: %d", status);
308cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  } else if (sensorListResponse.Resp.sns_result_t != SNS_RESULT_SUCCESS_V01) {
309cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    LOGE("Sensor list lequest failed with error: %d",
310cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol         sensorListResponse.Resp.sns_err_t);
311cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  } else {
312cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    success = true;
313cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    for (uint32_t i = 0; i < sensorListResponse.SensorInfo_len; i++) {
314cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      uint8_t sensorId = sensorListResponse.SensorInfo[i].SensorID;
315cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      if (!getSensorsForSensorId(sensorId, sensors)) {
316cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol        success = false;
317cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol        break;
318cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      }
319cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    }
32038bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol  }
321cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol
322cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  return success;
32338bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol}
32438bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol
32580b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol/**
32680b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol * Converts a SensorMode into an SMGR request action. When the net request for
32780b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol * a sensor is considered to be active an add operation is required for the
32880b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol * SMGR request. When the sensor becomes inactive the request is deleted.
32980b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol *
33080b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol * @param mode The sensor mode.
33180b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol * @return Returns the SMGR request action given the sensor mode.
33280b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol */
33380b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignoluint8_t getSmgrRequestActionForMode(SensorMode mode) {
33480b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  if (sensorModeIsActive(mode)) {
33580b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol    return SNS_SMGR_REPORT_ACTION_ADD_V01;
33680b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  } else {
33780b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol    return SNS_SMGR_REPORT_ACTION_DELETE_V01;
33880b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  }
33980b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol}
34080b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol
341f546f4c27e66dc4ea868e660cebac9ba0c31fad9Andrew Rossignolbool PlatformSensor::updatePlatformSensorRequest(const SensorRequest& request) {
34280b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  // If requestId for this sensor is zero and the mode is not active, the sensor
34380b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  // has never been enabled. This means that the request is a no-op from the
34480b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  // disabled state and true can be returned to indicate success.
34580b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  if (mReportId == 0 && !sensorModeIsActive(request.getMode())) {
34680b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol    return true;
34780b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  }
34880b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol
34980b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  // Allocate request and response for the sensor request.
35080b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  // TODO: Replace this with the templatized memoryAlloc to avoid these ugly
35180b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  // casts.
35280b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  sns_smgr_periodic_report_req_msg_v01 *sensorDataRequest =
35380b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol      static_cast<sns_smgr_periodic_report_req_msg_v01 *>(
35480b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol          memoryAlloc(sizeof(sns_smgr_periodic_report_req_msg_v01)));
35580b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  sns_smgr_periodic_report_resp_msg_v01 *sensorDataResponse =
35680b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol      static_cast<sns_smgr_periodic_report_resp_msg_v01 *>(
35780b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol          memoryAlloc(sizeof(sns_smgr_periodic_report_resp_msg_v01)));
35880b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  if (sensorDataRequest == nullptr || sensorDataResponse == nullptr) {
35980b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol    memoryFree(sensorDataRequest);
36080b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol    memoryFree(sensorDataResponse);
36180b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol    FATAL_ERROR("Failed to allocated sensor request/response: out of memory");
36280b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  }
36380b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol
36480b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  // Check if a new report ID is needed for this request.
36580b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  if (mReportId == 0) {
36680b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol    mReportId = generateUniqueReportId();
36780b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  }
36880b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol
36980b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  // Zero the fields in the request. All mandatory and unused fields are
37080b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  // specified to be set to false or zero so this is safe.
37180b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  memset(sensorDataRequest, 0, sizeof(sns_smgr_periodic_report_req_msg_v01));
37280b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol
37380b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  // Build the request for one sensor at the requested rate. An add action for a
37480b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  // ReportID that is already in use causes a replacement of the last request.
37580b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  uint16_t reportRate = intervalToSmgrReportRate(request.getInterval());
37680b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  sensorDataRequest->ReportRate = reportRate;
37780b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  sensorDataRequest->ReportId = mReportId;
37880b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  sensorDataRequest->Action = getSmgrRequestActionForMode(request.getMode());
37980b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  sensorDataRequest->Item_len = 1; // Each request is for one sensor.
38080b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  sensorDataRequest->Item[0].SensorId = mSensorId;
38180b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  sensorDataRequest->Item[0].DataType = mDataType;
38280b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  sensorDataRequest->Item[0].Decimation = SNS_SMGR_DECIMATION_RECENT_SAMPLE_V01;
38380b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol
38480b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  bool success = false;
38580b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  qmi_client_error_type status = qmi_client_send_msg_sync(
38680b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol      gSensorContextQmiClientHandle, SNS_SMGR_REPORT_REQ_V01,
38780b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol      sensorDataRequest, sizeof(sns_smgr_periodic_report_req_msg_v01),
38880b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol      sensorDataResponse, sizeof(sns_smgr_single_sensor_info_resp_msg_v01),
38980b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol      kQmiTimeoutMs);
39080b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  if (status != QMI_NO_ERR) {
39180b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol    LOGE("Error requesting sensor data: %d", status);
39280b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  } else if (sensorDataResponse->Resp.sns_result_t != SNS_RESULT_SUCCESS_V01) {
39380b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol    LOGE("Sensor data request failed with error: %d",
39480b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol         sensorDataResponse->Resp.sns_result_t);
39580b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  } else {
39680b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol    if (sensorDataResponse->AckNak == SNS_SMGR_RESPONSE_ACK_SUCCESS_V01
39780b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol        || sensorDataResponse->AckNak == SNS_SMGR_RESPONSE_ACK_MODIFIED_V01) {
39880b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol      success = true;
39980b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol    } else {
40080b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol      LOGE("Sensor data AckNak failed with error: %d",
40180b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol           sensorDataResponse->AckNak);
40280b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol    }
40380b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  }
40480b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol
40580b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  memoryFree(sensorDataRequest);
40680b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  memoryFree(sensorDataResponse);
40780b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  return success;
408f546f4c27e66dc4ea868e660cebac9ba0c31fad9Andrew Rossignol}
409f546f4c27e66dc4ea868e660cebac9ba0c31fad9Andrew Rossignol
41038bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol}  // namespace chre
411