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 "sensorevent.h"
18
19 #include <inttypes.h>
20 #include <string.h>
21
22 #include "contexthub.h"
23 #include "log.h"
24
25 namespace android {
26
27 constexpr float kCompressedAccelSampleRatio(8.0f * 9.81f / 32768.0f);
28 constexpr float kCompressedMagSampleRatio(0.15f); //For AK09915
29 //constexpr float kCompressedMagSampleRatio(0.0625f); //For BMM150
30
31 /* SensorEvent ****************************************************************/
32
FromBytes(const std::vector<uint8_t> & buffer)33 std::unique_ptr<SensorEvent> SensorEvent::FromBytes(
34 const std::vector<uint8_t>& buffer) {
35 SensorEvent *sensor_event = nullptr;
36
37 SensorType sensor_type = static_cast<SensorType>(
38 ReadEventResponse::EventTypeFromBuffer(buffer) -
39 static_cast<uint32_t>(EventType::FirstSensorEvent));
40
41 switch (sensor_type) {
42 case SensorType::Accel:
43 case SensorType::Gyro:
44 case SensorType::GyroUncal:
45 case SensorType::Magnetometer:
46 case SensorType::MagnetometerUncal:
47 case SensorType::Orientation:
48 case SensorType::Gravity:
49 case SensorType::LinearAccel:
50 case SensorType::RotationVector:
51 case SensorType::GeomagneticRotationVector:
52 case SensorType::GameRotationVector:
53 sensor_event = new TripleAxisSensorEvent();
54 break;
55
56 case SensorType::Barometer:
57 case SensorType::Temperature:
58 case SensorType::AmbientLightSensor:
59 case SensorType::Proximity:
60 case SensorType::Humidity:
61 sensor_event = new SingleAxisSensorEvent();
62 break;
63
64 // TODO: Activity uses a special struct, it should have its own class
65 case SensorType::Activity:
66 case SensorType::AnyMotion:
67 case SensorType::NoMotion:
68 case SensorType::SignificantMotion:
69 case SensorType::Flat:
70 case SensorType::WindowOrientation:
71 case SensorType::Tilt:
72 case SensorType::Hall:
73 case SensorType::HeartRateECG: // Heart rates not implemented, guessing
74 case SensorType::HeartRatePPG: // data type here...
75 case SensorType::StepCount:
76 case SensorType::StepDetect:
77 case SensorType::Gesture:
78 case SensorType::DoubleTwist:
79 case SensorType::DoubleTap:
80 case SensorType::Vsync:
81 case SensorType::WristTilt:
82 sensor_event = new SingleAxisIntSensorEvent();
83 break;
84
85 case SensorType::CompressedAccel:
86 case SensorType::CompressedMag:
87 sensor_event = new CompressedTripleAxisSensorEvent();
88 break;
89
90 default:
91 LOGW("Can't create SensorEvent for unknown/invalid sensor type %d",
92 static_cast<int>(sensor_type));
93 }
94
95 if (sensor_event &&
96 (!sensor_event->Populate(buffer) || !sensor_event->SizeIsValid())) {
97 LOGW("Couldn't populate sensor event, or invalid size");
98 delete sensor_event;
99 sensor_event = nullptr;
100 }
101
102 return std::unique_ptr<SensorEvent>(sensor_event);
103 }
104
GetSensorType() const105 SensorType SensorEvent::GetSensorType() const {
106 return static_cast<SensorType>(
107 GetEventType() - static_cast<uint32_t>(EventType::FirstSensorEvent));
108 }
109
110 /* TimestampedSensorEvent *****************************************************/
111
GetNumSamples() const112 uint8_t TimestampedSensorEvent::GetNumSamples() const {
113 // Perform size check, but don't depend on SizeIsValid since it will call us
114 if (event_data.size() < (sizeof(struct SensorEventHeader) +
115 sizeof(struct SensorFirstSample))) {
116 LOGW("Short/invalid timestamped sensor event; length %zu",
117 event_data.size());
118 return 0;
119 }
120
121 const struct SensorFirstSample *first_sample_header =
122 reinterpret_cast<const struct SensorFirstSample *>(
123 event_data.data() + sizeof(struct SensorEventHeader));
124
125 return first_sample_header->numSamples;
126 }
127
GetReferenceTime() const128 uint64_t TimestampedSensorEvent::GetReferenceTime() const {
129 if (!SizeIsValid()) {
130 return 0;
131 }
132 const struct SensorEventHeader *header =
133 reinterpret_cast<const struct SensorEventHeader *>(event_data.data());
134 return header->reference_time;
135 }
136
GetSampleTime(uint8_t index) const137 uint64_t TimestampedSensorEvent::GetSampleTime(uint8_t index) const {
138 const SensorSampleHeader *sample;
139 uint64_t sample_time = GetReferenceTime();
140
141 // For index 0, the sample time is the reference time. For each subsequent
142 // sample, sum the delta to the previous sample to get the sample time.
143 for (uint8_t i = 1; i <= index; i++) {
144 sample = GetSampleAtIndex(index);
145 sample_time += sample->delta_time;
146 }
147
148 return sample_time;
149 }
150
GetSampleTimeStr(uint8_t index) const151 std::string TimestampedSensorEvent::GetSampleTimeStr(uint8_t index) const {
152 uint64_t sample_time = GetSampleTime(index);
153
154 char buffer[32];
155 snprintf(buffer, sizeof(buffer), "%" PRIu64 ".%06" PRIu64 " ms",
156 sample_time / 1000000, sample_time % 1000000);
157
158 return std::string(buffer);
159 }
160
GetSampleAtIndex(uint8_t index) const161 const SensorSampleHeader *TimestampedSensorEvent::GetSampleAtIndex(
162 uint8_t index) const {
163 if (index >= GetNumSamples()) {
164 LOGW("Requested sample at invalid index %u", index);
165 return nullptr;
166 }
167
168 unsigned int offset = (sizeof(struct SensorEventHeader) +
169 index * GetSampleDataSize());
170 return reinterpret_cast<const struct SensorSampleHeader *>(
171 event_data.data() + offset);
172 }
173
ToString() const174 std::string TimestampedSensorEvent::ToString() const {
175 uint8_t num_samples = GetNumSamples();
176 char buffer[64];
177 snprintf(buffer, sizeof(buffer),
178 "Event from sensor %d (%s) with %d sample%s\n",
179 static_cast<int>(GetSensorType()),
180 ContextHub::SensorTypeToAbbrevName(GetSensorType()).c_str(),
181 num_samples, (num_samples != 1) ? "s" : "");
182
183 return std::string(buffer) + StringForAllSamples();
184 }
185
SizeIsValid() const186 bool TimestampedSensorEvent::SizeIsValid() const {
187 unsigned int min_size = (sizeof(struct SensorEventHeader) +
188 GetNumSamples() * GetSampleDataSize());
189 if (event_data.size() < min_size) {
190 LOGW("Got short sensor event with %zu bytes, expected >= %u",
191 event_data.size(), min_size);
192 return false;
193 }
194
195 return true;
196 }
197
StringForAllSamples() const198 std::string TimestampedSensorEvent::StringForAllSamples() const {
199 std::string str;
200 for (unsigned int i = 0; i < GetNumSamples(); i++) {
201 str += StringForSample(i);
202 }
203 return str;
204 }
205
206 /* SingleAxisSensorEvent ******************************************************/
207
StringForSample(uint8_t index) const208 std::string SingleAxisSensorEvent::StringForSample(uint8_t index) const {
209 const SingleAxisDataPoint *sample =
210 reinterpret_cast<const SingleAxisDataPoint *>(GetSampleAtIndex(index));
211
212 char buffer[64];
213 snprintf(buffer, sizeof(buffer), " %f @ %s\n",
214 sample->fdata, GetSampleTimeStr(index).c_str());
215
216 return std::string(buffer);
217 }
218
GetSampleDataSize() const219 uint8_t SingleAxisSensorEvent::GetSampleDataSize() const {
220 return sizeof(struct SingleAxisDataPoint);
221 }
222
223 /* SingleAxisIntSensorEvent ***************************************************/
224
StringForSample(uint8_t index) const225 std::string SingleAxisIntSensorEvent::StringForSample(uint8_t index) const {
226 const SingleAxisDataPoint *sample =
227 reinterpret_cast<const SingleAxisDataPoint *>(GetSampleAtIndex(index));
228
229 char buffer[64];
230 snprintf(buffer, sizeof(buffer), " %d @ %s\n",
231 sample->idata, GetSampleTimeStr(index).c_str());
232
233 return std::string(buffer);
234 }
235
236 /* TripleAxisSensorEvent ******************************************************/
237
StringForSample(uint8_t index) const238 std::string TripleAxisSensorEvent::StringForSample(uint8_t index) const {
239 const TripleAxisDataPoint *sample =
240 reinterpret_cast<const TripleAxisDataPoint *>(
241 GetSampleAtIndex(index));
242
243 const struct SensorFirstSample *first_sample =
244 reinterpret_cast<const struct SensorFirstSample *>(
245 event_data.data() + sizeof(struct SensorEventHeader));
246 bool is_bias_sample = first_sample->biasPresent
247 && first_sample->biasSample == index;
248
249 char buffer[128];
250 snprintf(buffer, sizeof(buffer), " X:%f Y:%f Z:%f @ %s%s\n",
251 sample->x, sample->y, sample->z, GetSampleTimeStr(index).c_str(),
252 is_bias_sample ? " (Bias Sample)" : "");
253
254 return std::string(buffer);
255 }
256
GetSampleDataSize() const257 uint8_t TripleAxisSensorEvent::GetSampleDataSize() const {
258 return sizeof(struct TripleAxisDataPoint);
259 }
260
261 /* CompressedTripleAxisSensorEvent ********************************************/
262
StringForSample(uint8_t index) const263 std::string CompressedTripleAxisSensorEvent::StringForSample(
264 uint8_t index) const {
265 float compressedSampleRatio;
266 const CompressedTripleAxisDataPoint *sample =
267 reinterpret_cast<const CompressedTripleAxisDataPoint *>(
268 GetSampleAtIndex(index));
269
270 const struct SensorFirstSample *first_sample =
271 reinterpret_cast<const struct SensorFirstSample *>(
272 event_data.data() + sizeof(struct SensorEventHeader));
273 bool is_bias_sample = first_sample->biasPresent
274 && first_sample->biasSample == index;
275
276 switch(GetSensorType())
277 {
278 case SensorType::CompressedAccel:
279 compressedSampleRatio = kCompressedAccelSampleRatio;
280 break;
281 case SensorType::CompressedMag:
282 compressedSampleRatio = kCompressedMagSampleRatio;
283 break;
284 default:
285 LOGW("Unsupported compressed sensor type");
286 compressedSampleRatio = 1.0;
287 }
288
289 float x = sample->ix * compressedSampleRatio;
290 float y = sample->iy * compressedSampleRatio;
291 float z = sample->iz * compressedSampleRatio;
292
293 char buffer[128];
294 snprintf(buffer, sizeof(buffer), " X:%f Y:%f Z:%f @ %s%s\n",
295 x, y, z, GetSampleTimeStr(index).c_str(),
296 is_bias_sample ? " (Bias Sample)" : "");
297
298 return std::string(buffer);
299 }
300
GetSampleDataSize() const301 uint8_t CompressedTripleAxisSensorEvent::GetSampleDataSize() const {
302 return sizeof(CompressedTripleAxisDataPoint);
303 }
304
305 } // namespace android
306