1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <algorithm>
18
19#include "chre/core/sensor_request.h"
20#include "chre/platform/assert.h"
21#include "chre/platform/fatal_error.h"
22
23namespace chre {
24
25const char *getSensorTypeName(SensorType sensorType) {
26  switch (sensorType) {
27    case SensorType::Unknown:
28      return "Unknown";
29    case SensorType::Accelerometer:
30      return "Accelerometer";
31    case SensorType::InstantMotion:
32      return "Instant Motion";
33    case SensorType::StationaryDetect:
34      return "Stationary Detect";
35    case SensorType::Gyroscope:
36      return "Gyroscope";
37    case SensorType::GeomagneticField:
38      return "Geomagnetic Field";
39    case SensorType::Pressure:
40      return "Pressure";
41    case SensorType::Light:
42      return "Light";
43    case SensorType::Proximity:
44      return "Proximity";
45    case SensorType::AccelerometerTemperature:
46      return "Accelerometer Temp";
47    case SensorType::GyroscopeTemperature:
48      return "Gyroscope Temp";
49    case SensorType::UncalibratedAccelerometer:
50      return "Uncal Accelerometer";
51    case SensorType::UncalibratedGyroscope:
52      return "Uncal Gyroscope";
53    case SensorType::UncalibratedGeomagneticField:
54      return "Uncal Geomagnetic Field";
55    default:
56      CHRE_ASSERT(false);
57      return "";
58  }
59}
60
61uint16_t getSampleEventTypeForSensorType(SensorType sensorType) {
62  if (sensorType == SensorType::Unknown) {
63    FATAL_ERROR("Tried to obtain the sensor sample event index for an unknown "
64                "sensor type");
65  }
66
67  // The enum values of SensorType may not map to the defined values in the
68  // CHRE API.
69  uint8_t sensorTypeValue = getUnsignedIntFromSensorType(sensorType);
70  return CHRE_EVENT_SENSOR_DATA_EVENT_BASE + sensorTypeValue;
71}
72
73SensorType getSensorTypeForSampleEventType(uint16_t eventType) {
74  return getSensorTypeFromUnsignedInt(
75      eventType - CHRE_EVENT_SENSOR_DATA_EVENT_BASE);
76}
77
78SensorType getSensorTypeFromUnsignedInt(uint8_t sensorType) {
79  switch (sensorType) {
80    case CHRE_SENSOR_TYPE_ACCELEROMETER:
81      return SensorType::Accelerometer;
82    case CHRE_SENSOR_TYPE_INSTANT_MOTION_DETECT:
83      return SensorType::InstantMotion;
84    case CHRE_SENSOR_TYPE_STATIONARY_DETECT:
85      return SensorType::StationaryDetect;
86    case CHRE_SENSOR_TYPE_GYROSCOPE:
87      return SensorType::Gyroscope;
88    case CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD:
89      return SensorType::GeomagneticField;
90    case CHRE_SENSOR_TYPE_PRESSURE:
91      return SensorType::Pressure;
92    case CHRE_SENSOR_TYPE_LIGHT:
93      return SensorType::Light;
94    case CHRE_SENSOR_TYPE_PROXIMITY:
95      return SensorType::Proximity;
96    case CHRE_SENSOR_TYPE_ACCELEROMETER_TEMPERATURE:
97      return SensorType::AccelerometerTemperature;
98    case CHRE_SENSOR_TYPE_GYROSCOPE_TEMPERATURE:
99      return SensorType::GyroscopeTemperature;
100    case CHRE_SENSOR_TYPE_UNCALIBRATED_ACCELEROMETER:
101      return SensorType::UncalibratedAccelerometer;
102    case CHRE_SENSOR_TYPE_UNCALIBRATED_GYROSCOPE:
103      return SensorType::UncalibratedGyroscope;
104    case CHRE_SENSOR_TYPE_UNCALIBRATED_GEOMAGNETIC_FIELD:
105      return SensorType::UncalibratedGeomagneticField;
106    default:
107      return SensorType::Unknown;
108  }
109}
110
111uint8_t getUnsignedIntFromSensorType(SensorType sensorType) {
112  switch (sensorType) {
113    case SensorType::Accelerometer:
114      return CHRE_SENSOR_TYPE_ACCELEROMETER;
115    case SensorType::InstantMotion:
116      return CHRE_SENSOR_TYPE_INSTANT_MOTION_DETECT;
117    case SensorType::StationaryDetect:
118      return CHRE_SENSOR_TYPE_STATIONARY_DETECT;
119    case SensorType::Gyroscope:
120      return CHRE_SENSOR_TYPE_GYROSCOPE;
121    case SensorType::GeomagneticField:
122      return CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD;
123    case SensorType::Pressure:
124      return CHRE_SENSOR_TYPE_PRESSURE;
125    case SensorType::Light:
126      return CHRE_SENSOR_TYPE_LIGHT;
127    case SensorType::Proximity:
128      return CHRE_SENSOR_TYPE_PROXIMITY;
129    case SensorType::AccelerometerTemperature:
130      return CHRE_SENSOR_TYPE_ACCELEROMETER_TEMPERATURE;
131    case SensorType::GyroscopeTemperature:
132      return CHRE_SENSOR_TYPE_GYROSCOPE_TEMPERATURE;
133    case SensorType::UncalibratedAccelerometer:
134      return CHRE_SENSOR_TYPE_UNCALIBRATED_ACCELEROMETER;
135    case SensorType::UncalibratedGyroscope:
136      return CHRE_SENSOR_TYPE_UNCALIBRATED_GYROSCOPE;
137    case SensorType::UncalibratedGeomagneticField:
138      return CHRE_SENSOR_TYPE_UNCALIBRATED_GEOMAGNETIC_FIELD;
139    default:
140      // Update implementation to prevent undefined or SensorType::Unknown from
141      // being used.
142      CHRE_ASSERT(false);
143      return 0;
144  }
145}
146
147SensorSampleType getSensorSampleTypeFromSensorType(SensorType sensorType) {
148  switch (sensorType) {
149    case SensorType::Accelerometer:
150    case SensorType::Gyroscope:
151    case SensorType::GeomagneticField:
152    case SensorType::UncalibratedAccelerometer:
153    case SensorType::UncalibratedGyroscope:
154    case SensorType::UncalibratedGeomagneticField:
155      return SensorSampleType::ThreeAxis;
156    case SensorType::Pressure:
157    case SensorType::Light:
158    case SensorType::AccelerometerTemperature:
159    case SensorType::GyroscopeTemperature:
160      return SensorSampleType::Float;
161    case SensorType::InstantMotion:
162    case SensorType::StationaryDetect:
163      return SensorSampleType::Occurrence;
164    case SensorType::Proximity:
165      return SensorSampleType::Byte;
166    default:
167      CHRE_ASSERT(false);
168      return SensorSampleType::Unknown;
169  }
170}
171
172SensorMode getSensorModeFromEnum(enum chreSensorConfigureMode enumSensorMode) {
173  switch (enumSensorMode) {
174    case CHRE_SENSOR_CONFIGURE_MODE_DONE:
175      return SensorMode::Off;
176    case CHRE_SENSOR_CONFIGURE_MODE_CONTINUOUS:
177      return SensorMode::ActiveContinuous;
178    case CHRE_SENSOR_CONFIGURE_MODE_ONE_SHOT:
179      return SensorMode::ActiveOneShot;
180    case CHRE_SENSOR_CONFIGURE_MODE_PASSIVE_CONTINUOUS:
181      return SensorMode::PassiveContinuous;
182    case CHRE_SENSOR_CONFIGURE_MODE_PASSIVE_ONE_SHOT:
183      return SensorMode::PassiveOneShot;
184    default:
185      // Default to off since it is the least harmful and has no power impact.
186      return SensorMode::Off;
187  }
188}
189
190bool sensorTypeIsOneShot(SensorType sensorType) {
191  return (sensorType == SensorType::InstantMotion ||
192          sensorType == SensorType::StationaryDetect);
193}
194
195bool sensorTypeIsOnChange(SensorType sensorType) {
196  return (sensorType == SensorType::Light ||
197          sensorType == SensorType::Proximity);
198}
199
200SensorRequest::SensorRequest()
201    : SensorRequest(SensorMode::Off,
202                    Nanoseconds(CHRE_SENSOR_INTERVAL_DEFAULT),
203                    Nanoseconds(CHRE_SENSOR_LATENCY_DEFAULT)) {}
204
205SensorRequest::SensorRequest(SensorMode mode,
206                             Nanoseconds interval,
207                             Nanoseconds latency)
208    : mInterval(interval), mLatency(latency), mMode(mode) {}
209
210SensorRequest::SensorRequest(Nanoapp *nanoapp, SensorMode mode,
211                             Nanoseconds interval,
212                             Nanoseconds latency)
213    : mNanoapp(nanoapp), mInterval(interval), mLatency(latency), mMode(mode) {}
214
215bool SensorRequest::isEquivalentTo(const SensorRequest& request) const {
216  return (mMode == request.mMode
217      && mInterval == request.mInterval
218      && mLatency == request.mLatency);
219}
220
221bool SensorRequest::mergeWith(const SensorRequest& request) {
222  bool attributesChanged = false;
223
224  if (request.mInterval < mInterval) {
225    mInterval = request.mInterval;
226    attributesChanged = true;
227  }
228
229  if (request.mLatency < mLatency) {
230    mLatency = request.mLatency;
231    attributesChanged = true;
232  }
233
234  // Compute the highest priority mode. Active continuous is the highest
235  // priority and passive one-shot is the lowest.
236  SensorMode maximalSensorMode = SensorMode::Off;
237  if (mMode == SensorMode::ActiveContinuous
238      || request.mMode == SensorMode::ActiveContinuous) {
239    maximalSensorMode = SensorMode::ActiveContinuous;
240  } else if (mMode == SensorMode::ActiveOneShot
241      || request.mMode == SensorMode::ActiveOneShot) {
242    maximalSensorMode = SensorMode::ActiveOneShot;
243  } else if (mMode == SensorMode::PassiveContinuous
244      || request.mMode == SensorMode::PassiveContinuous) {
245    maximalSensorMode = SensorMode::PassiveContinuous;
246  } else if (mMode == SensorMode::PassiveOneShot
247      || request.mMode == SensorMode::PassiveOneShot) {
248    maximalSensorMode = SensorMode::PassiveOneShot;
249  } else {
250    CHRE_ASSERT(false);
251  }
252
253  if (mMode != maximalSensorMode) {
254    mMode = maximalSensorMode;
255    attributesChanged = true;
256  }
257
258  return attributesChanged;
259}
260
261Nanoseconds SensorRequest::getInterval() const {
262  return mInterval;
263}
264
265Nanoseconds SensorRequest::getLatency() const {
266  return mLatency;
267}
268
269SensorMode SensorRequest::getMode() const {
270  return mMode;
271}
272
273Nanoapp *SensorRequest::getNanoapp() const {
274  return mNanoapp;
275}
276
277}  // namespace chre
278