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 sensor_event = new SingleAxisIntSensorEvent();
79 break;
80
81 case SensorType::CompressedAccel:
82 sensor_event = new CompressedTripleAxisSensorEvent();
83 break;
84
85 default:
86 LOGW("Can't create SensorEvent for unknown/invalid sensor type %d",
87 static_cast<int>(sensor_type));
88 }
89
90 if (sensor_event &&
91 (!sensor_event->Populate(buffer) || !sensor_event->SizeIsValid())) {
92 LOGW("Couldn't populate sensor event, or invalid size");
93 delete sensor_event;
94 sensor_event = nullptr;
95 }
96
97 return std::unique_ptr<SensorEvent>(sensor_event);
98 }
99
GetSensorType() const100 SensorType SensorEvent::GetSensorType() const {
101 return static_cast<SensorType>(
102 GetEventType() - static_cast<uint32_t>(EventType::FirstSensorEvent));
103 }
104
105 /* TimestampedSensorEvent *****************************************************/
106
GetNumSamples() const107 uint8_t TimestampedSensorEvent::GetNumSamples() const {
108 // Perform size check, but don't depend on SizeIsValid since it will call us
109 if (event_data.size() < (sizeof(struct SensorEventHeader) +
110 sizeof(struct SensorFirstSample))) {
111 LOGW("Short/invalid timestamped sensor event; length %zu",
112 event_data.size());
113 return 0;
114 }
115
116 const struct SensorFirstSample *first_sample_header =
117 reinterpret_cast<const struct SensorFirstSample *>(
118 event_data.data() + sizeof(struct SensorEventHeader));
119
120 return first_sample_header->numSamples;
121 }
122
GetReferenceTime() const123 uint64_t TimestampedSensorEvent::GetReferenceTime() const {
124 if (!SizeIsValid()) {
125 return 0;
126 }
127 const struct SensorEventHeader *header =
128 reinterpret_cast<const struct SensorEventHeader *>(event_data.data());
129 return header->reference_time;
130 }
131
GetSampleTime(uint8_t index) const132 uint64_t TimestampedSensorEvent::GetSampleTime(uint8_t index) const {
133 const SensorSampleHeader *sample;
134 uint64_t sample_time = GetReferenceTime();
135
136 // For index 0, the sample time is the reference time. For each subsequent
137 // sample, sum the delta to the previous sample to get the sample time.
138 for (uint8_t i = 1; i <= index; i++) {
139 sample = GetSampleAtIndex(index);
140 sample_time += sample->delta_time;
141 }
142
143 return sample_time;
144 }
145
GetSampleTimeStr(uint8_t index) const146 std::string TimestampedSensorEvent::GetSampleTimeStr(uint8_t index) const {
147 uint64_t sample_time = GetSampleTime(index);
148
149 char buffer[32];
150 snprintf(buffer, sizeof(buffer), "%" PRIu64 ".%06" PRIu64 " ms",
151 sample_time / 1000000, sample_time % 1000000);
152
153 return std::string(buffer);
154 }
155
GetSampleAtIndex(uint8_t index) const156 const SensorSampleHeader *TimestampedSensorEvent::GetSampleAtIndex(
157 uint8_t index) const {
158 if (index >= GetNumSamples()) {
159 LOGW("Requested sample at invalid index %u", index);
160 return nullptr;
161 }
162
163 unsigned int offset = (sizeof(struct SensorEventHeader) +
164 index * GetSampleDataSize());
165 return reinterpret_cast<const struct SensorSampleHeader *>(
166 event_data.data() + offset);
167 }
168
ToString() const169 std::string TimestampedSensorEvent::ToString() const {
170 uint8_t num_samples = GetNumSamples();
171 char buffer[64];
172 snprintf(buffer, sizeof(buffer),
173 "Event from sensor %d (%s) with %d sample%s\n",
174 static_cast<int>(GetSensorType()),
175 ContextHub::SensorTypeToAbbrevName(GetSensorType()).c_str(),
176 num_samples, (num_samples != 1) ? "s" : "");
177
178 return std::string(buffer) + StringForAllSamples();
179 }
180
SizeIsValid() const181 bool TimestampedSensorEvent::SizeIsValid() const {
182 unsigned int min_size = (sizeof(struct SensorEventHeader) +
183 GetNumSamples() * GetSampleDataSize());
184 if (event_data.size() < min_size) {
185 LOGW("Got short sensor event with %zu bytes, expected >= %u",
186 event_data.size(), min_size);
187 return false;
188 }
189
190 return true;
191 }
192
StringForAllSamples() const193 std::string TimestampedSensorEvent::StringForAllSamples() const {
194 std::string str;
195 for (unsigned int i = 0; i < GetNumSamples(); i++) {
196 str += StringForSample(i);
197 }
198 return str;
199 }
200
201 /* SingleAxisSensorEvent ******************************************************/
202
StringForSample(uint8_t index) const203 std::string SingleAxisSensorEvent::StringForSample(uint8_t index) const {
204 const SingleAxisDataPoint *sample =
205 reinterpret_cast<const SingleAxisDataPoint *>(GetSampleAtIndex(index));
206
207 char buffer[64];
208 snprintf(buffer, sizeof(buffer), " %f @ %s\n",
209 sample->fdata, GetSampleTimeStr(index).c_str());
210
211 return std::string(buffer);
212 }
213
GetSampleDataSize() const214 uint8_t SingleAxisSensorEvent::GetSampleDataSize() const {
215 return sizeof(struct SingleAxisDataPoint);
216 }
217
218 /* SingleAxisIntSensorEvent ***************************************************/
219
StringForSample(uint8_t index) const220 std::string SingleAxisIntSensorEvent::StringForSample(uint8_t index) const {
221 const SingleAxisDataPoint *sample =
222 reinterpret_cast<const SingleAxisDataPoint *>(GetSampleAtIndex(index));
223
224 char buffer[64];
225 snprintf(buffer, sizeof(buffer), " %d @ %s\n",
226 sample->idata, GetSampleTimeStr(index).c_str());
227
228 return std::string(buffer);
229 }
230
231 /* TripleAxisSensorEvent ******************************************************/
232
StringForSample(uint8_t index) const233 std::string TripleAxisSensorEvent::StringForSample(uint8_t index) const {
234 const TripleAxisDataPoint *sample =
235 reinterpret_cast<const TripleAxisDataPoint *>(
236 GetSampleAtIndex(index));
237
238 const struct SensorFirstSample *first_sample =
239 reinterpret_cast<const struct SensorFirstSample *>(
240 event_data.data() + sizeof(struct SensorEventHeader));
241 bool is_bias_sample = first_sample->biasPresent
242 && first_sample->biasSample == index;
243
244 char buffer[128];
245 snprintf(buffer, sizeof(buffer), " X:%f Y:%f Z:%f @ %s%s\n",
246 sample->x, sample->y, sample->z, GetSampleTimeStr(index).c_str(),
247 is_bias_sample ? " (Bias Sample)" : "");
248
249 return std::string(buffer);
250 }
251
GetSampleDataSize() const252 uint8_t TripleAxisSensorEvent::GetSampleDataSize() const {
253 return sizeof(struct TripleAxisDataPoint);
254 }
255
256 /* CompressedTripleAxisSensorEvent ********************************************/
257
StringForSample(uint8_t index) const258 std::string CompressedTripleAxisSensorEvent::StringForSample(
259 uint8_t index) const {
260 const CompressedTripleAxisDataPoint *sample =
261 reinterpret_cast<const CompressedTripleAxisDataPoint *>(
262 GetSampleAtIndex(index));
263
264 const struct SensorFirstSample *first_sample =
265 reinterpret_cast<const struct SensorFirstSample *>(
266 event_data.data() + sizeof(struct SensorEventHeader));
267 bool is_bias_sample = first_sample->biasPresent
268 && first_sample->biasSample == index;
269
270 float x = sample->ix * kCompressedSampleRatio;
271 float y = sample->iy * kCompressedSampleRatio;
272 float z = sample->iz * kCompressedSampleRatio;
273
274 char buffer[128];
275 snprintf(buffer, sizeof(buffer), " X:%f Y:%f Z:%f @ %s%s\n",
276 x, y, z, GetSampleTimeStr(index).c_str(),
277 is_bias_sample ? " (Bias Sample)" : "");
278
279 return std::string(buffer);
280 }
281
GetSampleDataSize() const282 uint8_t CompressedTripleAxisSensorEvent::GetSampleDataSize() const {
283 return sizeof(CompressedTripleAxisDataPoint);
284 }
285
286 } // namespace android
287