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
1748fda6e1eedf6ba80ae7596fc7676f8318a1e88eMeng-hsuan Chung#include <algorithm>
18cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol#include <cinttypes>
19cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol
2038bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignolextern "C" {
2138bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol
2283a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol#include "fixed_point.h"
2338bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol#include "qmi_client.h"
2438bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol#include "sns_smgr_api_v01.h"
2501d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung#include "sns_smgr_internal_api_v02.h"
2683a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol#include "timetick.h"
2738bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol
2838bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol}  // extern "C"
2938bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol
3083a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol#include "chre_api/chre/sensor.h"
31c807971625839bf4689435f24b6cacbf7dbb3de9Andrew Rossignol#include "chre/core/event_loop_manager.h"
323e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung#include "chre/platform/assert.h"
3338bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol#include "chre/platform/fatal_error.h"
3438bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol#include "chre/platform/log.h"
350d94eb2fcf599754d9a1087c3292ab6ac6495de6Andrew Rossignol#include "chre/platform/platform_sensor.h"
360d94eb2fcf599754d9a1087c3292ab6ac6495de6Andrew Rossignol#include "chre/platform/slpi/platform_sensor_util.h"
3780b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol
3801d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chungnamespace chre {
3980b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignolnamespace {
4080b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol
4101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung//! The timeout for QMI messages in milliseconds.
4201d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chungconstexpr uint32_t kQmiTimeoutMs = 1000;
4301d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung
4401d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chungconstexpr float kMicroTeslaPerGauss = 100.0f;
4501d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung
4601d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung//! The QMI sensor service client handle.
4701d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chungqmi_client_type gPlatformSensorServiceQmiClientHandle = nullptr;
4801d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung
4901d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung//! The QMI sensor internal service client handle.
5001d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chungqmi_client_type gPlatformSensorInternalServiceQmiClientHandle = nullptr;
5180b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol
5283a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol//! A sensor report indication for deserializing sensor sample indications
5383a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol//! into. This global instance is used to avoid thrashy use of the heap by
5483a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol//! allocating and freeing this on the heap for every new sensor sample. This
5583a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol//! relies on the assumption that the QMI callback is not reentrant.
563e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chungsns_smgr_buffering_ind_msg_v01 gSmgrBufferingIndMsg;
5783a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol
5801d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung//! A struct to store the sensor monitor status indication results.
5901d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chungstruct SensorStatus {
6001d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  uint8_t sensorId;
6101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  uint8_t numClients;
6201d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung};
6338bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol
6401d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung//! A vector that tracks the number clients of each supported sensorId.
6501d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan ChungDynamicVector<SensorStatus> gSensorStatusMonitor;
669c8f6eb9f3429b0b8369e546ce2493b6c8829839Meng-hsuan Chung
6780b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol/**
68ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * Converts a sensorId, dataType and calType as provided by SMGR to a
69ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * SensorType as used by platform-independent CHRE code. This is useful in
70ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * sensor discovery.
7183a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol *
7283a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * @param sensorId The sensorID as provided by the SMGR request for sensor info.
7383a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * @param dataType The dataType for the sesnor as provided by the SMGR request
7483a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol *                 for sensor info.
75ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * @param calType The calibration type (CAL_SEL) as defined in the SMGR API.
76ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * @return Returns the platform-independent sensor type or Unknown if no
7783a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol *         match is found.
7883a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol */
79ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan ChungSensorType getSensorTypeFromSensorId(uint8_t sensorId, uint8_t dataType,
80ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung                                     uint8_t calType) {
81cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  // Here be dragons. These constants below are defined in
82cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  // sns_smgr_common_v01.h. Refer to the section labelled "Define sensor
83cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  // identifier" for more details. This function relies on the ordering of
84cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  // constants provided by their API. Do not change these values without care.
85cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  // You have been warned!
86cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  if (dataType == SNS_SMGR_DATA_TYPE_PRIMARY_V01) {
87cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    if (sensorId >= SNS_SMGR_ID_ACCEL_V01
88cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol        && sensorId < SNS_SMGR_ID_GYRO_V01) {
89ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung      if (calType == SNS_SMGR_CAL_SEL_FULL_CAL_V01) {
90ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung        return SensorType::Accelerometer;
91ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung      } else if (calType == SNS_SMGR_CAL_SEL_FACTORY_CAL_V01) {
92ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung        return SensorType::UncalibratedAccelerometer;
93ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung      }
94cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    } else if (sensorId >= SNS_SMGR_ID_GYRO_V01
95cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol        && sensorId < SNS_SMGR_ID_MAG_V01) {
96ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung      if (calType == SNS_SMGR_CAL_SEL_FULL_CAL_V01) {
97ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung        return SensorType::Gyroscope;
98ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung      } else if (calType == SNS_SMGR_CAL_SEL_FACTORY_CAL_V01) {
99ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung        return SensorType::UncalibratedGyroscope;
100ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung      }
101cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    } else if (sensorId >= SNS_SMGR_ID_MAG_V01
102cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol        && sensorId < SNS_SMGR_ID_PRESSURE_V01) {
103ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung      if (calType == SNS_SMGR_CAL_SEL_FULL_CAL_V01) {
104ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung        return SensorType::GeomagneticField;
105ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung      } else if (calType == SNS_SMGR_CAL_SEL_FACTORY_CAL_V01) {
106ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung        return SensorType::UncalibratedGeomagneticField;
107ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung      }
108cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    } else if (sensorId >= SNS_SMGR_ID_PRESSURE_V01
109cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol        && sensorId < SNS_SMGR_ID_PROX_LIGHT_V01) {
110cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      return SensorType::Pressure;
111cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    } else if (sensorId >= SNS_SMGR_ID_PROX_LIGHT_V01
112cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol        && sensorId < SNS_SMGR_ID_HUMIDITY_V01) {
113cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      return SensorType::Proximity;
11469fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung    } else if (sensorId == SNS_SMGR_ID_OEM_SENSOR_09_V01) {
11569fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung      return SensorType::StationaryDetect;
11669fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung    } else if (sensorId == SNS_SMGR_ID_OEM_SENSOR_10_V01) {
11769fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung      return SensorType::InstantMotion;
118cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    }
119cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  } else if (dataType == SNS_SMGR_DATA_TYPE_SECONDARY_V01) {
120ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung    if (sensorId >= SNS_SMGR_ID_ACCEL_V01
121ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung        && sensorId < SNS_SMGR_ID_GYRO_V01) {
122ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung      return SensorType::AccelerometerTemperature;
123ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung    } else if (sensorId >= SNS_SMGR_ID_GYRO_V01
124ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung        && sensorId < SNS_SMGR_ID_MAG_V01) {
125ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung      return SensorType::GyroscopeTemperature;
126ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung    } else if ((sensorId >= SNS_SMGR_ID_PROX_LIGHT_V01
127ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung        && sensorId < SNS_SMGR_ID_HUMIDITY_V01)
128cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol        || (sensorId >= SNS_SMGR_ID_ULTRA_VIOLET_V01
129cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol            && sensorId < SNS_SMGR_ID_OBJECT_TEMP_V01)) {
130cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      return SensorType::Light;
131cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    }
132cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  }
133cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol
134cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  return SensorType::Unknown;
135cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol}
136cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol
137cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol/**
138ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * Converts a reportId as provided by SMGR to a SensorType.
139ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung *
140ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * @param reportId The reportID as provided by the SMGR buffering index.
141ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * @return Returns the sensorType that corresponds to the reportId.
142ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung */
143ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan ChungSensorType getSensorTypeFromReportId(uint8_t reportId) {
144ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  SensorType sensorType;
145ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  if (reportId < static_cast<uint8_t>(SensorType::SENSOR_TYPE_COUNT)) {
146ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung    sensorType = static_cast<SensorType>(reportId);
147ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  } else {
148ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung    sensorType = SensorType::Unknown;
149ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  }
150ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  return sensorType;
151ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung}
152ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung
153ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung/**
154ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * Converts a PlatformSensor to a unique report ID through SensorType. This is
155ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * useful in making sensor request.
156ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung *
157ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * @param sensorId The sensorID as provided by the SMGR request for sensor info.
158ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * @param dataType The dataType for the sesnor as provided by the SMGR request
159ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung *                 for sensor info.
160ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * @param calType The calibration type (CAL_SEL) as defined in the SMGR API.
161ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * @return Returns a unique report ID that is based on SensorType.
162ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung */
163ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chunguint8_t getReportId(uint8_t sensorId, uint8_t dataType, uint8_t calType) {
164ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  SensorType sensorType = getSensorTypeFromSensorId(
165ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung      sensorId, dataType, calType);
166ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung
167ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  CHRE_ASSERT_LOG(sensorType != SensorType::Unknown,
168ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung                  "sensorId %" PRIu8 ", dataType %" PRIu8 ", calType %" PRIu8,
169ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung                  sensorId, dataType, calType);
170ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  return static_cast<uint8_t>(sensorType);
171ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung}
172ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung
173ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung/**
174ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * Checks whether the corresponding sensor is a sencondary temperature sensor.
175ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung *
176ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * @param reportId The reportID as provided by the SMGR buffering index.
177ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * @return true if the sensor is a secondary temperature sensor.
178ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung */
179ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chungbool isSecondaryTemperature(uint8_t reportId) {
180ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  SensorType sensorType = getSensorTypeFromReportId(reportId);
181ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  return (sensorType == SensorType::AccelerometerTemperature
182ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung          || sensorType == SensorType::GyroscopeTemperature);
183ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung}
184ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung
185ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung/**
186ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * Verifies whether the buffering index's report ID matches the expected
187ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * indices length.
188ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung *
189ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * @return true if it's a valid pair of indices length and report ID.
190ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung */
191ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chungbool isValidIndicesLength() {
192ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  return ((gSmgrBufferingIndMsg.Indices_len == 1
193ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung           && !isSecondaryTemperature(gSmgrBufferingIndMsg.ReportId))
194ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung          || (gSmgrBufferingIndMsg.Indices_len == 2
195ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung              && isSecondaryTemperature(gSmgrBufferingIndMsg.ReportId)));
196ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung}
197ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung
198ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung/**
19967de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung * Allocates memory and specifies the memory size for an on-change sensor to
20067de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung * store its last data event.
20167de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung *
20267de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung * @param sensorType The sensorType of this sensor.
20367de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung * @param eventSize A non-null pointer to indicate the memory size allocated.
20467de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung * @return Pointer to the memory allocated.
20567de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung */
20667de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan ChungChreSensorData *allocateLastEvent(SensorType sensorType, size_t *eventSize) {
20767de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  CHRE_ASSERT(eventSize);
20867de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung
20967de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  *eventSize = 0;
21067de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  ChreSensorData *event = nullptr;
21167de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  if (sensorTypeIsOnChange(sensorType)) {
21267de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung    SensorSampleType sampleType = getSensorSampleTypeFromSensorType(sensorType);
21367de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung    switch (sampleType) {
21467de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung      case SensorSampleType::ThreeAxis:
21567de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung        *eventSize = sizeof(chreSensorThreeAxisData);
21667de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung        break;
21767de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung      case SensorSampleType::Float:
21867de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung        *eventSize = sizeof(chreSensorFloatData);
21967de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung        break;
22067de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung      case SensorSampleType::Byte:
22167de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung        *eventSize = sizeof(chreSensorByteData);
22267de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung        break;
22367de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung      case SensorSampleType::Occurrence:
22467de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung        *eventSize = sizeof(chreSensorOccurrenceData);
22567de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung        break;
22667de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung      default:
22767de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung        CHRE_ASSERT_LOG(false, "Unhandled sample type");
22867de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung        break;
22967de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung    }
23067de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung
23167de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung    event = static_cast<ChreSensorData *>(memoryAlloc(*eventSize));
23267de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung    if (event == nullptr) {
23367de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung      *eventSize = 0;
23467de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung      FATAL_ERROR("Failed to allocate last event memory for SensorType %d",
23567de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung                  static_cast<int>(sensorType));
23667de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung    }
23767de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  }
23867de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  return event;
23967de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung}
24067de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung
24167de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung/**
242ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * Adds a Platform sensor to the sensor list.
243ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung *
244e62f9949c5aa827e175cfb239d9840d7517e8052Meng-hsuan Chung * @param sensorInfo The sensorInfo as provided by the SMGR.
245ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * @param calType The calibration type (CAL_SEL) as defined in the SMGR API.
246ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * @param sensor The sensor list.
247ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung */
248e62f9949c5aa827e175cfb239d9840d7517e8052Meng-hsuan Chungvoid addPlatformSensor(const sns_smgr_sensor_datatype_info_s_v01& sensorInfo,
24948fda6e1eedf6ba80ae7596fc7676f8318a1e88eMeng-hsuan Chung                       uint8_t calType,
25048fda6e1eedf6ba80ae7596fc7676f8318a1e88eMeng-hsuan Chung                       DynamicVector<PlatformSensor> *sensors) {
2519cab6df9598abbf843a7b37eed0c7039048deba7Meng-hsuan Chung  PlatformSensor platformSensor;
252e62f9949c5aa827e175cfb239d9840d7517e8052Meng-hsuan Chung  platformSensor.sensorId = sensorInfo.SensorID;
253e62f9949c5aa827e175cfb239d9840d7517e8052Meng-hsuan Chung  platformSensor.dataType = sensorInfo.DataType;
254ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  platformSensor.calType = calType;
25548fda6e1eedf6ba80ae7596fc7676f8318a1e88eMeng-hsuan Chung  size_t bytesToCopy = std::min(sizeof(platformSensor.sensorName) - 1,
25648fda6e1eedf6ba80ae7596fc7676f8318a1e88eMeng-hsuan Chung                                static_cast<size_t>(sensorInfo.SensorName_len));
25748fda6e1eedf6ba80ae7596fc7676f8318a1e88eMeng-hsuan Chung  memcpy(platformSensor.sensorName, sensorInfo.SensorName, bytesToCopy);
25848fda6e1eedf6ba80ae7596fc7676f8318a1e88eMeng-hsuan Chung  platformSensor.sensorName[bytesToCopy] = '\0';
25967de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  platformSensor.minInterval = static_cast<uint64_t>(
26067de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung      Seconds(1).toRawNanoseconds() / sensorInfo.MaxSampleRate);
26167de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung
26267de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  // Allocates memory for on-change sensor's last event.
26367de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  SensorType sensorType = getSensorTypeFromSensorId(
26467de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung      sensorInfo.SensorID, sensorInfo.DataType, calType);
26567de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  platformSensor.lastEvent = allocateLastEvent(sensorType,
26667de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung                                               &platformSensor.lastEventSize);
26767de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung
268ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  if (!sensors->push_back(std::move(platformSensor))) {
269ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung    FATAL_ERROR("Failed to allocate new sensor: out of memory");
270ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  }
271ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung}
272ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung
273ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung/**
27483a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * Converts SMGR ticks to nanoseconds as a uint64_t.
27583a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol *
27683a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * @param ticks The number of ticks.
27783a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * @return The number of nanoseconds represented by the ticks value.
27883a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol */
27983a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignoluint64_t getNanosecondsFromSmgrTicks(uint32_t ticks) {
28083a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  return (ticks * Seconds(1).toRawNanoseconds())
28183a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol      / TIMETICK_NOMINAL_FREQ_HZ;
28283a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol}
28383a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol
28483a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol/**
285bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung * Populate the header
286bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung */
287ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chungvoid populateSensorDataHeader(
288ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung    SensorType sensorType, chreSensorDataHeader *header,
289ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung    const sns_smgr_buffering_sample_index_s_v01& sensorIndex) {
2903e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung  uint64_t baseTimestamp = getNanosecondsFromSmgrTicks(
291ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung      sensorIndex.FirstSampleTimestamp);
292bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung  memset(header->reserved, 0, sizeof(header->reserved));
2933e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung  header->baseTimestamp = baseTimestamp;
294bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung  header->sensorHandle = getSensorHandleFromSensorType(sensorType);
295ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  header->readingCount = sensorIndex.SampleCount;
296bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung}
297bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung
298bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung/**
299bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung * Populate three-axis event data.
300bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung */
301ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chungvoid populateThreeAxisEvent(
302ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung    SensorType sensorType, chreSensorThreeAxisData *data,
303ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung    const sns_smgr_buffering_sample_index_s_v01& sensorIndex) {
304ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  populateSensorDataHeader(sensorType, &data->header, sensorIndex);
3053e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung
306ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  for (size_t i = 0; i < sensorIndex.SampleCount; i++) {
3073e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung    const sns_smgr_buffering_sample_s_v01& sensorData =
308ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung        gSmgrBufferingIndMsg.Samples[i + sensorIndex.FirstSampleIdx];
3093e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung
3103e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung    // TimeStampOffset has max value of < 2 sec so it will not overflow here.
3113e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung    data->readings[i].timestampDelta =
3123e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung        getNanosecondsFromSmgrTicks(sensorData.TimeStampOffset);
3133e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung
3143e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung    // Convert from SMGR's NED coordinate to Android coordinate.
3153e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung    data->readings[i].x = FX_FIXTOFLT_Q16(sensorData.Data[1]);
3163e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung    data->readings[i].y = FX_FIXTOFLT_Q16(sensorData.Data[0]);
3173e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung    data->readings[i].z = -FX_FIXTOFLT_Q16(sensorData.Data[2]);
3183e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung
3193e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung    // Convert from Gauss to micro Tesla
320ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung    if (sensorType == SensorType::GeomagneticField
321ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung        || sensorType == SensorType::UncalibratedGeomagneticField) {
3223e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung      data->readings[i].x *= kMicroTeslaPerGauss;
3233e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung      data->readings[i].y *= kMicroTeslaPerGauss;
3243e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung      data->readings[i].z *= kMicroTeslaPerGauss;
3253e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung    }
3269c8f6eb9f3429b0b8369e546ce2493b6c8829839Meng-hsuan Chung  }
327bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung}
328bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung
329bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung/**
330bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung * Populate float event data.
331bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung */
332ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chungvoid populateFloatEvent(
333ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung    SensorType sensorType, chreSensorFloatData *data,
334ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung    const sns_smgr_buffering_sample_index_s_v01& sensorIndex) {
335ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  populateSensorDataHeader(sensorType, &data->header, sensorIndex);
3363e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung
337ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  for (size_t i = 0; i < sensorIndex.SampleCount; i++) {
3383e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung    const sns_smgr_buffering_sample_s_v01& sensorData =
339ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung        gSmgrBufferingIndMsg.Samples[i + sensorIndex.FirstSampleIdx];
3403e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung
3413e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung    // TimeStampOffset has max value of < 2 sec so it will not overflow.
3423e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung    data->readings[i].timestampDelta =
3433e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung        getNanosecondsFromSmgrTicks(sensorData.TimeStampOffset);
3443e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung    data->readings[i].value = FX_FIXTOFLT_Q16(sensorData.Data[0]);
3453e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung  }
346bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung}
347bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung
348bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung/**
34990db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung * Populate byte event data.
35090db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung */
35190db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chungvoid populateByteEvent(
35290db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung    SensorType sensorType, chreSensorByteData *data,
35390db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung    const sns_smgr_buffering_sample_index_s_v01& sensorIndex) {
35490db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung  populateSensorDataHeader(sensorType, &data->header, sensorIndex);
35590db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung
35690db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung  for (size_t i = 0; i < sensorIndex.SampleCount; i++) {
35790db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung    const sns_smgr_buffering_sample_s_v01& sensorData =
35890db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung        gSmgrBufferingIndMsg.Samples[i + sensorIndex.FirstSampleIdx];
35990db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung
36090db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung    // TimeStampOffset has max value of < 2 sec so it will not overflow.
36190db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung    data->readings[i].timestampDelta =
36290db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung        getNanosecondsFromSmgrTicks(sensorData.TimeStampOffset);
36390db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung    // Zero out fields invalid and padding0.
36490db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung    data->readings[i].value = 0;
36590db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung    // SMGR reports 1 in Q16 for near, and 0 for far.
36690db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung    data->readings[i].isNear = sensorData.Data[0] ? 1 : 0;
36790db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung  }
36890db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung}
36990db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung
37090db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung/**
37169fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung * Populate occurrence event data.
37269fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung */
37369fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chungvoid populateOccurrenceEvent(
37469fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung    SensorType sensorType, chreSensorOccurrenceData *data,
37569fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung    const sns_smgr_buffering_sample_index_s_v01& sensorIndex) {
37669fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung  populateSensorDataHeader(sensorType, &data->header, sensorIndex);
37769fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung
37869fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung  for (size_t i = 0; i < sensorIndex.SampleCount; i++) {
37969fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung    const sns_smgr_buffering_sample_s_v01& sensorData =
38069fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung        gSmgrBufferingIndMsg.Samples[i + sensorIndex.FirstSampleIdx];
38169fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung
38269fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung    // TimeStampOffset has max value of < 2 sec so it will not overflow.
38369fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung    data->readings[i].timestampDelta =
38469fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung        getNanosecondsFromSmgrTicks(sensorData.TimeStampOffset);
38569fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung  }
38669fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung}
38769fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung
38869fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung/**
389bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung * Allocate event memory according to SensorType and populate event readings.
390bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung */
391ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chungvoid *allocateAndPopulateEvent(
392ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung    SensorType sensorType,
393ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung    const sns_smgr_buffering_sample_index_s_v01& sensorIndex) {
394bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung  SensorSampleType sampleType = getSensorSampleTypeFromSensorType(sensorType);
3953e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung  size_t memorySize = sizeof(chreSensorDataHeader);
396bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung  switch (sampleType) {
397bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung    case SensorSampleType::ThreeAxis: {
398ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung      memorySize += sensorIndex.SampleCount *
3993e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung          sizeof(chreSensorThreeAxisData::chreSensorThreeAxisSampleData);
4003e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung      auto *event =
4013e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung          static_cast<chreSensorThreeAxisData *>(memoryAlloc(memorySize));
402bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung      if (event != nullptr) {
403ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung        populateThreeAxisEvent(sensorType, event, sensorIndex);
404bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung      }
405bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung      return event;
406bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung    }
407bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung
408bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung    case SensorSampleType::Float: {
409ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung      memorySize += sensorIndex.SampleCount *
4103e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung          sizeof(chreSensorFloatData::chreSensorFloatSampleData);
4113e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung      auto *event =
4123e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung          static_cast<chreSensorFloatData *>(memoryAlloc(memorySize));
413bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung      if (event != nullptr) {
414ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung        populateFloatEvent(sensorType, event, sensorIndex);
415bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung      }
416bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung      return event;
417bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung    }
418bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung
41990db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung    case SensorSampleType::Byte: {
42090db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung      memorySize += sensorIndex.SampleCount *
42190db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung          sizeof(chreSensorByteData::chreSensorByteSampleData);
42290db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung      auto *event =
42390db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung          static_cast<chreSensorByteData *>(memoryAlloc(memorySize));
42490db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung      if (event != nullptr) {
42590db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung        populateByteEvent(sensorType, event, sensorIndex);
42690db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung      }
42790db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung      return event;
42890db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung    }
42990db64e2ff34e67d967abf755c9dc2dd9a715079Meng-hsuan Chung
43069fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung    case SensorSampleType::Occurrence: {
43169fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung      memorySize += sensorIndex.SampleCount *
43269fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung          sizeof(chreSensorOccurrenceData::chreSensorOccurrenceSampleData);
43369fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung      auto *event =
43469fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung          static_cast<chreSensorOccurrenceData *>(memoryAlloc(memorySize));
43569fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung      if (event != nullptr) {
43669fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung        populateOccurrenceEvent(sensorType, event, sensorIndex);
43769fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung      }
43869fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung      return event;
43969fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung    }
44069fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung
441bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung    default:
442bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung      LOGW("Unhandled sensor data %" PRIu8, sensorType);
443bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung      return nullptr;
444bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung  }
445bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung}
446bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung
44767de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chungvoid smgrSensorDataEventFree(uint16_t eventType, void *eventData) {
44867de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  // Events are allocated using the simple memoryAlloc/memoryFree platform
44967de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  // functions.
45067de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  // TODO: Consider using a MemoryPool.
45167de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  memoryFree(eventData);
45267de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung
45367de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  // Remove all requests if it's a one-shot sensor and only after data has been
45467de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  // delivered to all clients.
45567de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  SensorType sensorType = getSensorTypeForSampleEventType(eventType);
45667de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  if (sensorTypeIsOneShot(sensorType)) {
45767de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung    EventLoopManagerSingleton::get()->getSensorRequestManager()
45867de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung        .removeAllRequests(sensorType);
45967de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  }
46067de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung}
46167de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung
46267de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung/**
46367de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung * A helper function that updates the last event of a in the main thread.
46467de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung * Platform should call this function only for an on-change sensor.
46567de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung *
46667de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung * @param sensorType The SensorType of the sensor.
46767de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung * @param eventData A non-null pointer to the sensor's CHRE event data.
46867de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung */
46967de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chungvoid updateLastEvent(SensorType sensorType, const void *eventData) {
47067de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  CHRE_ASSERT(eventData);
47167de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung
47267de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  auto *header = static_cast<const chreSensorDataHeader *>(eventData);
47367de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  if (header->readingCount != 1) {
47467de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung    // TODO: better error handling when SMGR behavior changes.
47567de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung    // SMGR delivers one sample per report for on-change sensors.
47667de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung    LOGE("%" PRIu16 " samples in an event for on-change sensor %d",
47767de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung         header->readingCount, static_cast<int>(sensorType));
47867de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  } else {
47967de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung    struct CallbackData {
48067de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung      SensorType sensorType;
48167de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung      const ChreSensorData *event;
48267de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung    };
48367de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung    auto *callbackData = memoryAlloc<CallbackData>();
48467de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung    if (callbackData == nullptr) {
48567de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung      LOGE("Failed to allocate deferred callback memory");
48667de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung    } else {
48767de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung      callbackData->sensorType = sensorType;
48867de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung      callbackData->event = static_cast<const ChreSensorData *>(eventData);
48967de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung
49067de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung      auto callback = [](uint16_t /* type */, void *data) {
49167de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung        auto *cbData = static_cast<CallbackData *>(data);
49267de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung
49367de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung        Sensor *sensor = EventLoopManagerSingleton::get()
49467de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung            ->getSensorRequestManager().getSensor(cbData->sensorType);
49567de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung        if (sensor != nullptr) {
49667de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung          sensor->setLastEvent(cbData->event);
49767de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung        }
49867de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung        memoryFree(cbData);
49967de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung      };
50067de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung
50167de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung      // Schedule a deferred callback.
50267de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung      if (!EventLoopManagerSingleton::get()->deferCallback(
50367de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung          SystemCallbackType::SensorLastEventUpdate, callbackData, callback)) {
50467de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung        LOGE("Failed to schedule a deferred callback for sensorType %d",
50567de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung             static_cast<int>(sensorType));
50667de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung        memoryFree(callbackData);
50767de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung      }
50867de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung    }  // if (callbackData == nullptr)
50967de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  }
51067de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung}
51167de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung
512bf7f9e866c31f63b321172dec0a8d8037aa2460bMeng-hsuan Chung/**
51301d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung * Handles sensor data provided by the SMGR framework.
51483a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol *
51583a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * @param userHandle The userHandle is used by the QMI decode function.
51683a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * @param buffer The buffer to decode sensor data from.
51783a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * @param bufferLength The size of the buffer to decode.
51883a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol */
51983a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignolvoid handleSensorDataIndication(void *userHandle, void *buffer,
52083a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol                                unsigned int bufferLength) {
52183a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  int status = qmi_client_message_decode(
5223e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung      userHandle, QMI_IDL_INDICATION, SNS_SMGR_BUFFERING_IND_V01, buffer,
5233e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung      bufferLength, &gSmgrBufferingIndMsg,
5243e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung      sizeof(sns_smgr_buffering_ind_msg_v01));
52583a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  if (status != QMI_NO_ERR) {
52683a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol    LOGE("Error parsing sensor data indication %d", status);
52701d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  } else {
52801d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    // We only requested one sensor per request except for a secondary
529e62f9949c5aa827e175cfb239d9840d7517e8052Meng-hsuan Chung    // temperature sensor.
53001d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    bool validReport = isValidIndicesLength();
53101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    CHRE_ASSERT_LOG(validReport,
53201d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung                    "Got buffering indication from %" PRIu32
53301d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung                    " sensors with report ID %" PRIu8,
53401d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung                    gSmgrBufferingIndMsg.Indices_len,
53501d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung                    gSmgrBufferingIndMsg.ReportId);
53601d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    if (validReport) {
53701d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      // Identify the index for the desired sensor. It is always 0 except
53801d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      // possibly for a secondary temperature sensor.
53901d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      uint32_t index = 0;
54001d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      if (isSecondaryTemperature(gSmgrBufferingIndMsg.ReportId)) {
54101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung        index = (gSmgrBufferingIndMsg.Indices[0].DataType
54201d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung                 == SNS_SMGR_DATA_TYPE_SECONDARY_V01) ? 0 : 1;
54301d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      }
54401d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      const sns_smgr_buffering_sample_index_s_v01& sensorIndex =
54501d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung          gSmgrBufferingIndMsg.Indices[index];
54601d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung
54701d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      // Use ReportID to identify sensors as
54801d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      // gSmgrBufferingIndMsg.Samples[i].Flags are not populated.
54901d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      SensorType sensorType = getSensorTypeFromReportId(
55001d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung          gSmgrBufferingIndMsg.ReportId);
55101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      if (sensorType == SensorType::Unknown) {
55201d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung        LOGW("Received sensor sample for unknown sensor %" PRIu8 " %" PRIu8,
55301d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung             sensorIndex.SensorId, sensorIndex.DataType);
55467de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung      } else if (sensorIndex.SampleCount == 0) {
55567de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung        LOGW("Received sensorType %d event with 0 sample",
55667de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung             static_cast<int>(sensorType));
55783a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol      } else {
55801d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung        void *eventData = allocateAndPopulateEvent(sensorType, sensorIndex);
55901d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung        if (eventData == nullptr) {
56001d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung          LOGW("Dropping event due to allocation failure");
56101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung        } else {
56267de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung          // Schedule a deferred callback to update on-change sensor's last
56367de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung          // event in the main thread.
56467de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung          if (sensorTypeIsOnChange(sensorType)) {
56567de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung            updateLastEvent(sensorType, eventData);
56667de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung          }
56767de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung
56801d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung          EventLoopManagerSingleton::get()->postEvent(
56901d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung              getSampleEventTypeForSensorType(sensorType), eventData,
57001d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung              smgrSensorDataEventFree);
57101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung        }
57283a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol      }
573e62f9949c5aa827e175cfb239d9840d7517e8052Meng-hsuan Chung    }  // if (validReport)
57483a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  }
57583a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol}
57683a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol
57783a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol/**
57883a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * This callback is invoked by the QMI framework when an asynchronous message is
57983a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * delivered. Unhandled messages are logged. The signature is defined by the QMI
58083a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * library.
58183a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol *
58283a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * @param userHandle The userHandle is used by the QMI library.
58383a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * @param messageId The type of the message to decode.
58483a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * @param buffer The buffer to decode.
58583a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * @param bufferLength The length of the buffer to decode.
58683a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol * @param callbackData Data that is provided as a context to this callback. This
58783a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol *                     is not used in this context.
58883a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol */
58901d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chungvoid platformSensorServiceQmiIndicationCallback(void *userHandle,
59001d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung                                                unsigned int messageId,
59101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung                                                void *buffer,
59201d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung                                                unsigned int bufferLength,
59301d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung                                                void *callbackData) {
59483a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  switch (messageId) {
5953e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung    case SNS_SMGR_BUFFERING_IND_V01:
59683a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol      handleSensorDataIndication(userHandle, buffer, bufferLength);
59783a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol      break;
59883a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol    default:
59901d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      LOGW("Received unhandled sensor service message: 0x%x", messageId);
60083a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol      break;
60183a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  };
60283a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol}
60383a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol
60401d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chunguint8_t getNumClients(uint8_t sensorId) {
60501d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  for (size_t i = 0; i < gSensorStatusMonitor.size(); i++) {
60601d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    if (gSensorStatusMonitor[i].sensorId == sensorId) {
60701d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      return gSensorStatusMonitor[i].numClients;
60801d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    }
60983a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  }
61001d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  return 0;
61101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung}
61283a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol
61301d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chungvoid setNumClients(uint8_t sensorId, uint8_t numClients) {
61401d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  for (size_t i = 0; i < gSensorStatusMonitor.size(); i++) {
61501d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    if (gSensorStatusMonitor[i].sensorId == sensorId) {
61601d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      gSensorStatusMonitor[i].numClients = numClients;
61701d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    }
61801d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  }
61901d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung}
62001d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung
62101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung/**
62201d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung * Handles sensor status provided by the SMGR framework.
62301d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung *
62401d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung * @param userHandle The userHandle is used by the QMI decode function.
62501d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung * @param buffer The buffer to decode sensor data from.
62601d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung * @param bufferLength The size of the buffer to decode.
62701d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung */
62801d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chungvoid handleSensorStatusMonitorIndication(void *userHandle, void *buffer,
62901d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung                                         unsigned int bufferLength) {
63001d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  sns_smgr_sensor_status_monitor_ind_msg_v02 smgrMonitorIndMsg;
63101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung
63201d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  int status = qmi_client_message_decode(
63301d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      userHandle, QMI_IDL_INDICATION, SNS_SMGR_SENSOR_STATUS_MONITOR_IND_V02,
63401d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      buffer, bufferLength, &smgrMonitorIndMsg, sizeof(smgrMonitorIndMsg));
63583a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  if (status != QMI_NO_ERR) {
63601d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    LOGE("Error parsing sensor status monitor indication %d", status);
63701d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  } else {
63801d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    uint8_t numClients = getNumClients(smgrMonitorIndMsg.sensor_id);
63901d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    if (numClients != smgrMonitorIndMsg.num_clients) {
64069fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung      LOGD("Status: id %" PRIu64 ", num clients: curr %" PRIu8 " new %" PRIu8,
64101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung           smgrMonitorIndMsg.sensor_id, numClients,
64201d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung           smgrMonitorIndMsg.num_clients);
64301d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      setNumClients(smgrMonitorIndMsg.sensor_id,
64401d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung                    smgrMonitorIndMsg.num_clients);
64501d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung
64601d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      //TODO: add onNumClientsChange()
64701d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    }
64883a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol  }
64983a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol}
65083a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol
65101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung/**
65201d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung * This callback is invoked by the QMI framework when an asynchronous message is
65301d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung * delivered. Unhandled messages are logged. The signature is defined by the QMI
65401d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung * library.
65501d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung *
65601d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung * @param userHandle The userHandle is used by the QMI library.
65701d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung * @param messageId The type of the message to decode.
65801d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung * @param buffer The buffer to decode.
65901d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung * @param bufferLength The length of the buffer to decode.
66001d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung * @param callbackData Data that is provided as a context to this callback. This
66101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung *                     is not used in this context.
66201d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung */
66301d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chungvoid platformSensorInternalServiceQmiIndicationCallback(void *userHandle,
66401d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    unsigned int messageId, void *buffer, unsigned int bufferLength,
66501d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    void *callbackData) {
66601d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  switch (messageId) {
66701d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    case SNS_SMGR_SENSOR_STATUS_MONITOR_IND_V02:
66801d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      handleSensorStatusMonitorIndication(userHandle, buffer, bufferLength);
66901d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      break;
67001d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    default:
67101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      LOGW("Received unhandled sensor internal service message: 0x%x",
67201d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung           messageId);
67301d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      break;
67401d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  };
67501d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung}
67601d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung
67701d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chungvoid setSensorStatusMonitor(uint8_t sensorId, bool enable) {
67801d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  sns_smgr_sensor_status_monitor_req_msg_v02 monitorRequest;
67901d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  sns_smgr_sensor_status_monitor_resp_msg_v02 monitorResponse;
68001d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  monitorRequest.sensor_id = sensorId;
68101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  monitorRequest.registering = enable ? TRUE : FALSE;
68201d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung
68301d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  qmi_client_error_type status = qmi_client_send_msg_sync(
68401d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      gPlatformSensorInternalServiceQmiClientHandle,
68501d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      SNS_SMGR_SENSOR_STATUS_MONITOR_REQ_V02,
68601d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      &monitorRequest, sizeof(monitorRequest),
68701d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      &monitorResponse, sizeof(monitorResponse), kQmiTimeoutMs);
68801d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung
68901d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  if (status != QMI_NO_ERR) {
69001d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    LOGE("Error setting sensor status monitor: %d", status);
69101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  } else if (monitorResponse.resp.sns_result_t != SNS_RESULT_SUCCESS_V01) {
69201d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    LOGE("Sensor status monitor request failed with error: %" PRIu8
69301d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung         " sensor ID %" PRIu8 " enable %d",
69401d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung         monitorResponse.resp.sns_err_t, sensorId, enable);
69501d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  }
69683a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol}
69783a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol
69883a6e8255099bcbd0758c1dbe6e002bb8542ec4dAndrew Rossignol/**
699cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol * Requests the sensors for a given sensor ID and appends them to the provided
700cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol * list of sensors. If an error occurs, false is returned.
701cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol *
702cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol * @param sensorId The sensor ID to request sensor info for.
703cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol * @param sensors The list of sensors to append newly found sensors to.
704cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol * @return Returns false if an error occurs.
705cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol */
706cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignolbool getSensorsForSensorId(uint8_t sensorId,
707cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol                           DynamicVector<PlatformSensor> *sensors) {
708cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  sns_smgr_single_sensor_info_req_msg_v01 sensorInfoRequest;
709cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  sns_smgr_single_sensor_info_resp_msg_v01 sensorInfoResponse;
710cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol
711cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  sensorInfoRequest.SensorID = sensorId;
712cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol
713cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  qmi_client_error_type status = qmi_client_send_msg_sync(
71401d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      gPlatformSensorServiceQmiClientHandle, SNS_SMGR_SINGLE_SENSOR_INFO_REQ_V01,
715cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      &sensorInfoRequest, sizeof(sns_smgr_single_sensor_info_req_msg_v01),
716cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      &sensorInfoResponse, sizeof(sns_smgr_single_sensor_info_resp_msg_v01),
717cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      kQmiTimeoutMs);
718cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol
719cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  bool success = false;
720cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  if (status != QMI_NO_ERR) {
721cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    LOGE("Error requesting single sensor info: %d", status);
722cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  } else if (sensorInfoResponse.Resp.sns_result_t != SNS_RESULT_SUCCESS_V01) {
723cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    LOGE("Single sensor info request failed with error: %d",
724cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol         sensorInfoResponse.Resp.sns_err_t);
725cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  } else {
72601d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    bool isSensorIdSupported = false;
727cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    const sns_smgr_sensor_info_s_v01& sensorInfoList =
728cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol        sensorInfoResponse.SensorInfo;
729cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    for (uint32_t i = 0; i < sensorInfoList.data_type_info_len; i++) {
730e62f9949c5aa827e175cfb239d9840d7517e8052Meng-hsuan Chung      const sns_smgr_sensor_datatype_info_s_v01& sensorInfo =
731e62f9949c5aa827e175cfb239d9840d7517e8052Meng-hsuan Chung          sensorInfoList.data_type_info[i];
732ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung      LOGD("SensorID %" PRIu8 ", DataType %" PRIu8 ", MaxRate %" PRIu16
733ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung           "Hz, SensorName %s",
734e62f9949c5aa827e175cfb239d9840d7517e8052Meng-hsuan Chung           sensorInfo.SensorID, sensorInfo.DataType,
735e62f9949c5aa827e175cfb239d9840d7517e8052Meng-hsuan Chung           sensorInfo.MaxSampleRate, sensorInfo.SensorName);
736ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung
737ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung      SensorType sensorType = getSensorTypeFromSensorId(
738e62f9949c5aa827e175cfb239d9840d7517e8052Meng-hsuan Chung          sensorInfo.SensorID, sensorInfo.DataType,
739ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung          SNS_SMGR_CAL_SEL_FULL_CAL_V01);
740cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      if (sensorType != SensorType::Unknown) {
74101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung        isSensorIdSupported = true;
742e62f9949c5aa827e175cfb239d9840d7517e8052Meng-hsuan Chung        addPlatformSensor(sensorInfo, SNS_SMGR_CAL_SEL_FULL_CAL_V01, sensors);
743ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung
744ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung        // Add an uncalibrated version if defined.
745ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung        SensorType uncalibratedType = getSensorTypeFromSensorId(
746e62f9949c5aa827e175cfb239d9840d7517e8052Meng-hsuan Chung            sensorInfo.SensorID, sensorInfo.DataType,
747ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung            SNS_SMGR_CAL_SEL_FACTORY_CAL_V01);
748ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung        if (sensorType != uncalibratedType) {
749e62f9949c5aa827e175cfb239d9840d7517e8052Meng-hsuan Chung          addPlatformSensor(sensorInfo, SNS_SMGR_CAL_SEL_FACTORY_CAL_V01,
750e62f9949c5aa827e175cfb239d9840d7517e8052Meng-hsuan Chung                            sensors);
751cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol        }
752cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol      }
753cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    }
754cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol
75501d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    // If CHRE supports sensors with this sensor ID, enable its status monitor.
75601d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    if (isSensorIdSupported) {
75701d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      // Initialize monitor status before making a QMI request.
75801d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      SensorStatus sensorStatus;
75901d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      sensorStatus.sensorId = sensorId;
76001d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      sensorStatus.numClients = 0;
76101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      gSensorStatusMonitor.push_back(sensorStatus);
762cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol
76301d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      setSensorStatusMonitor(sensorId, true);
764cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol    }
76501d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    success = true;
76638bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol  }
767cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol
768cd70ffd7dc683bd0d473f98ba593362e9cc5a877Andrew Rossignol  return success;
76938bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol}
77038bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol
77180b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol/**
77280b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol * Converts a SensorMode into an SMGR request action. When the net request for
77380b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol * a sensor is considered to be active an add operation is required for the
77480b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol * SMGR request. When the sensor becomes inactive the request is deleted.
77580b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol *
77680b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol * @param mode The sensor mode.
77780b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol * @return Returns the SMGR request action given the sensor mode.
77880b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol */
77980b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignoluint8_t getSmgrRequestActionForMode(SensorMode mode) {
78080b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  if (sensorModeIsActive(mode)) {
7813e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung    return SNS_SMGR_BUFFERING_ACTION_ADD_V01;
78280b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  } else {
7833e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung    return SNS_SMGR_BUFFERING_ACTION_DELETE_V01;
78480b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  }
78580b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol}
78680b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol
787ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung/**
788ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * Populates a sns_smgr_buffering_req_msg_v01 struct to request sensor data.
789ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung *
790ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * @param request The new request to set this sensor to.
791ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * @param sensorId The sensorID as provided by the SMGR request for sensor info.
792ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * @param dataType The dataType for the sesnor as provided by the SMGR request
793ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung *                 for sensor info.
794ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * @param calType The calibration type (CAL_SEL) as defined in the SMGR API.
79569fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung * @param minInterval The minimum interval allowed by this sensor.
796ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung * @param sensorDataRequest The pointer to the data request to be populated.
797ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung */
798ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chungvoid populateSensorRequest(
79969fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung    const SensorRequest& chreRequest, uint8_t sensorId, uint8_t dataType,
80069fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung    uint8_t calType, uint64_t minInterval,
80169fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung    sns_smgr_buffering_req_msg_v01 *sensorRequest) {
80280b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  // Zero the fields in the request. All mandatory and unused fields are
80380b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  // specified to be set to false or zero so this is safe.
804ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  memset(sensorRequest, 0, sizeof(*sensorRequest));
80580b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol
80669fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung  // Reconstruts a request as CHRE API requires one-shot sensors to be
80769fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung  // requested with pre-defined interval and latency that may not be accepted
80869fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung  // by SMGR.
80969fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung  bool isOneShot = sensorTypeIsOneShot(getSensorTypeFromSensorId(
81069fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung      sensorId, dataType, calType));
81169fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung  SensorRequest request(
81269fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung      chreRequest.getMode(),
81369fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung      isOneShot ? Nanoseconds(minInterval) : chreRequest.getInterval(),
81469fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung      isOneShot ? Nanoseconds(0) : chreRequest.getLatency());
81569fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung
81680b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  // Build the request for one sensor at the requested rate. An add action for a
81780b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  // ReportID that is already in use causes a replacement of the last request.
818ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  sensorRequest->ReportId = getReportId(sensorId, dataType, calType);
819ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  sensorRequest->Action = getSmgrRequestActionForMode(request.getMode());
82069fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung  // If latency < interval, request to SMGR would fail.
8213e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung  Nanoseconds batchingInterval =
8223e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung      (request.getLatency() > request.getInterval()) ?
8233e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung      request.getLatency() : request.getInterval();
824ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  sensorRequest->ReportRate = intervalToSmgrQ16ReportRate(batchingInterval);
825ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  sensorRequest->Item_len = 1; // One sensor per request if possible.
826ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  sensorRequest->Item[0].SensorId = sensorId;
827ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  sensorRequest->Item[0].DataType = dataType;
828ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  sensorRequest->Item[0].Decimation = SNS_SMGR_DECIMATION_RECENT_SAMPLE_V01;
829ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  sensorRequest->Item[0].Calibration = calType;
830ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  sensorRequest->Item[0].SamplingRate =
8313e1892c28b41fd0b76ea86b10d00c6ef669f9354Meng-hsuan Chung      intervalToSmgrSamplingRate(request.getInterval());
83280b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol
833ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  // Add a dummy primary sensor to accompany a secondary temperature sensor.
834ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  // This is requred by the SMGR. The primary sensor is requested with the same
835ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  // (low) rate and the same latency, whose response data will be ignored.
836ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  if (isSecondaryTemperature(sensorRequest->ReportId)) {
837ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung    sensorRequest->Item_len = 2;
838ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung    sensorRequest->Item[1].SensorId = sensorId;
839ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung    sensorRequest->Item[1].DataType = SNS_SMGR_DATA_TYPE_PRIMARY_V01;
840ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung    sensorRequest->Item[1].Decimation = SNS_SMGR_DECIMATION_RECENT_SAMPLE_V01;
841ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung    sensorRequest->Item[1].Calibration = SNS_SMGR_CAL_SEL_FULL_CAL_V01;
842ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung    sensorRequest->Item[1].SamplingRate = sensorRequest->Item[0].SamplingRate;
843ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  }
844ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung}
845ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung
84601d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung}  // anonymous namespace
84701d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung
84867de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan ChungPlatformSensor::~PlatformSensor() {
84967de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  if (lastEvent != nullptr) {
85067de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung    LOGD("Releasing lastEvent: 0x%p, id %" PRIu8 ", type %" PRIu8 ", cal %"
85167de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung         PRIu8 ", size %zu",
85267de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung         lastEvent, sensorId, dataType, calType, lastEventSize);
85367de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung    memoryFree(lastEvent);
85467de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  }
85567de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung}
85667de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung
85701d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chungvoid PlatformSensor::init() {
85801d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  // sns_smgr_api_v01
85901d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  qmi_idl_service_object_type sensorServiceObject =
86001d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      SNS_SMGR_SVC_get_service_object_v01();
86101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  if (sensorServiceObject == nullptr) {
86201d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    FATAL_ERROR("Failed to obtain the SNS SMGR service instance");
86301d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  }
86401d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung
86501d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  qmi_client_os_params sensorContextOsParams;
86601d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  qmi_client_error_type status = qmi_client_init_instance(sensorServiceObject,
86701d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      QMI_CLIENT_INSTANCE_ANY, &platformSensorServiceQmiIndicationCallback,
86801d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      nullptr, &sensorContextOsParams, kQmiTimeoutMs,
86901d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      &gPlatformSensorServiceQmiClientHandle);
87001d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  if (status != QMI_NO_ERR) {
87101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    FATAL_ERROR("Failed to initialize the sensor service QMI client: %d",
87201d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung                status);
87301d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  }
87401d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung
87501d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  // sns_smgr_interal_api_v02
87601d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  sensorServiceObject = SNS_SMGR_INTERNAL_SVC_get_service_object_v02();
87701d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  if (sensorServiceObject == nullptr) {
87801d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    FATAL_ERROR("Failed to obtain the SNS SMGR internal service instance");
87901d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  }
88001d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung
88101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  status = qmi_client_init_instance(sensorServiceObject,
88201d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      QMI_CLIENT_INSTANCE_ANY,
88301d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      &platformSensorInternalServiceQmiIndicationCallback, nullptr,
88401d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      &sensorContextOsParams, kQmiTimeoutMs,
88501d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      &gPlatformSensorInternalServiceQmiClientHandle);
88601d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  if (status != QMI_NO_ERR) {
88701d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    FATAL_ERROR("Failed to initialize the sensor internal service QMI client: "
88801d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung                "%d", status);
88901d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  }
89001d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung}
89101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung
89201d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chungvoid PlatformSensor::deinit() {
89301d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  qmi_client_release(&gPlatformSensorServiceQmiClientHandle);
89401d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  gPlatformSensorServiceQmiClientHandle = nullptr;
89501d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung
89601d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  // Removing all sensor status monitor requests. Releaseing a QMI client also
89701d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  // releases all of its subscriptions.
89801d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  gSensorStatusMonitor.clear();
89901d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung
90001d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  qmi_client_release(&gPlatformSensorInternalServiceQmiClientHandle);
90101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  gPlatformSensorInternalServiceQmiClientHandle = nullptr;
90201d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung}
90301d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung
90401d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chungbool PlatformSensor::getSensors(DynamicVector<PlatformSensor> *sensors) {
90501d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  CHRE_ASSERT(sensors);
90601d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung
90701d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  sns_smgr_all_sensor_info_req_msg_v01 sensorListRequest;
90801d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  sns_smgr_all_sensor_info_resp_msg_v01 sensorListResponse;
90901d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung
91001d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  qmi_client_error_type status = qmi_client_send_msg_sync(
91101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      gPlatformSensorServiceQmiClientHandle, SNS_SMGR_ALL_SENSOR_INFO_REQ_V01,
91201d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      &sensorListRequest, sizeof(sns_smgr_all_sensor_info_req_msg_v01),
91301d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      &sensorListResponse, sizeof(sns_smgr_all_sensor_info_resp_msg_v01),
91401d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      kQmiTimeoutMs);
91501d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung
91601d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  bool success = false;
91701d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  if (status != QMI_NO_ERR) {
91801d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    LOGE("Error requesting sensor list: %d", status);
91901d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  } else if (sensorListResponse.Resp.sns_result_t != SNS_RESULT_SUCCESS_V01) {
92001d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    LOGE("Sensor list lequest failed with error: %d",
92101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung         sensorListResponse.Resp.sns_err_t);
92201d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  } else {
92301d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    success = true;
92401d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    for (uint32_t i = 0; i < sensorListResponse.SensorInfo_len; i++) {
92501d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      uint8_t sensorId = sensorListResponse.SensorInfo[i].SensorID;
92601d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      if (!getSensorsForSensorId(sensorId, sensors)) {
92701d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung        success = false;
92801d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung        break;
92901d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung      }
93001d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung    }
93101d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  }
93201d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung
93301d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung  return success;
93401d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung}
93501d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung
936ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chungbool PlatformSensor::setRequest(const SensorRequest& request) {
937ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  // Allocate request and response for the sensor request.
938ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  auto *sensorRequest = memoryAlloc<sns_smgr_buffering_req_msg_v01>();
939ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  auto *sensorResponse = memoryAlloc<sns_smgr_buffering_resp_msg_v01>();
940ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung
94180b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  bool success = false;
942ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  if (sensorRequest == nullptr || sensorResponse == nullptr) {
943ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung    LOGE("Failed to allocated sensor request/response: out of memory");
94480b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  } else {
945ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung    populateSensorRequest(request, this->sensorId, this->dataType,
94669fb1d72e0aba8aeb7b7e8adf6acddff6f2b079dMeng-hsuan Chung        this->calType, this->getMinInterval(), sensorRequest);
947ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung
948ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung    qmi_client_error_type status = qmi_client_send_msg_sync(
94901d59972774453f9b0b7b92035f2919f8b6a5b35Meng-hsuan Chung        gPlatformSensorServiceQmiClientHandle, SNS_SMGR_BUFFERING_REQ_V01,
950ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung        sensorRequest, sizeof(*sensorRequest),
951ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung        sensorResponse, sizeof(*sensorResponse),
952ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung        kQmiTimeoutMs);
953ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung
954ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung    if (status != QMI_NO_ERR) {
955ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung      LOGE("Error requesting sensor data: %d", status);
956ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung    } else if (sensorResponse->Resp.sns_result_t != SNS_RESULT_SUCCESS_V01
957ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung        || (sensorResponse->AckNak != SNS_SMGR_RESPONSE_ACK_SUCCESS_V01
958ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung            && sensorResponse->AckNak != SNS_SMGR_RESPONSE_ACK_MODIFIED_V01)) {
959ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung      LOGE("Sensor data request failed with error: %d, AckNak: %d",
960ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung           sensorResponse->Resp.sns_err_t, sensorResponse->AckNak);
96180b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol    } else {
962ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung      success = true;
96380b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol    }
96480b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  }
96580b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol
966ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  memoryFree(sensorRequest);
967ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  memoryFree(sensorResponse);
96880b6b0c6ea5ce4c72ac738c560015de82edd788dAndrew Rossignol  return success;
969f546f4c27e66dc4ea868e660cebac9ba0c31fad9Andrew Rossignol}
970f546f4c27e66dc4ea868e660cebac9ba0c31fad9Andrew Rossignol
971cb8312e5ce53430576e2343e4863af84676c93adAndrew RossignolSensorType PlatformSensor::getSensorType() const {
972ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung  return getSensorTypeFromSensorId(this->sensorId, this->dataType,
973ba02dd147fe1ab32de471743e1996b416d345a7aMeng-hsuan Chung                                   this->calType);
974cb8312e5ce53430576e2343e4863af84676c93adAndrew Rossignol}
975cb8312e5ce53430576e2343e4863af84676c93adAndrew Rossignol
9769cab6df9598abbf843a7b37eed0c7039048deba7Meng-hsuan Chunguint64_t PlatformSensor::getMinInterval() const {
9779cab6df9598abbf843a7b37eed0c7039048deba7Meng-hsuan Chung  return minInterval;
9789cab6df9598abbf843a7b37eed0c7039048deba7Meng-hsuan Chung}
9799cab6df9598abbf843a7b37eed0c7039048deba7Meng-hsuan Chung
9809cab6df9598abbf843a7b37eed0c7039048deba7Meng-hsuan Chungconst char *PlatformSensor::getSensorName() const {
9819cab6df9598abbf843a7b37eed0c7039048deba7Meng-hsuan Chung  return sensorName;
9829cab6df9598abbf843a7b37eed0c7039048deba7Meng-hsuan Chung}
9839cab6df9598abbf843a7b37eed0c7039048deba7Meng-hsuan Chung
9849cab6df9598abbf843a7b37eed0c7039048deba7Meng-hsuan ChungPlatformSensor& PlatformSensor::operator=(PlatformSensor&& other) {
9859cab6df9598abbf843a7b37eed0c7039048deba7Meng-hsuan Chung  sensorId = other.sensorId;
9869cab6df9598abbf843a7b37eed0c7039048deba7Meng-hsuan Chung  dataType = other.dataType;
9879cab6df9598abbf843a7b37eed0c7039048deba7Meng-hsuan Chung  calType = other.calType;
9889cab6df9598abbf843a7b37eed0c7039048deba7Meng-hsuan Chung  memcpy(sensorName, other.sensorName, SNS_SMGR_MAX_SENSOR_NAME_SIZE_V01);
9899cab6df9598abbf843a7b37eed0c7039048deba7Meng-hsuan Chung  minInterval = other.minInterval;
99067de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung
99167de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  lastEvent = other.lastEvent;
99267de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  other.lastEvent = nullptr;
99367de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung
99467de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  lastEventSize = other.lastEventSize;
99567de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  other.lastEventSize = 0;
9969cab6df9598abbf843a7b37eed0c7039048deba7Meng-hsuan Chung  return *this;
9979cab6df9598abbf843a7b37eed0c7039048deba7Meng-hsuan Chung}
9989cab6df9598abbf843a7b37eed0c7039048deba7Meng-hsuan Chung
99967de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan ChungChreSensorData *PlatformSensor::getLastEvent() const {
100067de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  return lastEvent;
100167de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung}
100267de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung
100367de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chungvoid PlatformSensor::setLastEvent(const ChreSensorData *event) {
100467de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung  memcpy(lastEvent, event, lastEventSize);
100567de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung}
100667de3f239af66c0d5733950a916bc5566f2017f0Meng-hsuan Chung
100738bec5401084a884b19e8523649548d6a4f7169aAndrew Rossignol}  // namespace chre
1008