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