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 case SensorType::Humidity:
59 sensor_event = new SingleAxisSensorEvent();
60 break;
61
62 // TODO: Activity uses a special struct, it should have its own class
63 case SensorType::Activity:
64 case SensorType::AnyMotion:
65 case SensorType::NoMotion:
66 case SensorType::SignificantMotion:
67 case SensorType::Flat:
68 case SensorType::WindowOrientation:
69 case SensorType::Tilt:
70 case SensorType::Hall:
71 case SensorType::HeartRateECG: // Heart rates not implemented, guessing
72 case SensorType::HeartRatePPG: // data type here...
73 case SensorType::StepCount:
74 case SensorType::StepDetect:
75 case SensorType::Gesture:
76 case SensorType::DoubleTwist:
77 case SensorType::DoubleTap:
78 case SensorType::Vsync:
79 case SensorType::WristTilt:
80 sensor_event = new SingleAxisIntSensorEvent();
81 break;
82
83 case SensorType::CompressedAccel:
84 sensor_event = new CompressedTripleAxisSensorEvent();
85 break;
86
87 default:
88 LOGW("Can't create SensorEvent for unknown/invalid sensor type %d",
89 static_cast<int>(sensor_type));
90 }
91
92 if (sensor_event &&
93 (!sensor_event->Populate(buffer) || !sensor_event->SizeIsValid())) {
94 LOGW("Couldn't populate sensor event, or invalid size");
95 delete sensor_event;
96 sensor_event = nullptr;
97 }
98
99 return std::unique_ptr<SensorEvent>(sensor_event);
100 }
101
GetSensorType() const102 SensorType SensorEvent::GetSensorType() const {
103 return static_cast<SensorType>(
104 GetEventType() - static_cast<uint32_t>(EventType::FirstSensorEvent));
105 }
106
107 /* TimestampedSensorEvent *****************************************************/
108
GetNumSamples() const109 uint8_t TimestampedSensorEvent::GetNumSamples() const {
110 // Perform size check, but don't depend on SizeIsValid since it will call us
111 if (event_data.size() < (sizeof(struct SensorEventHeader) +
112 sizeof(struct SensorFirstSample))) {
113 LOGW("Short/invalid timestamped sensor event; length %zu",
114 event_data.size());
115 return 0;
116 }
117
118 const struct SensorFirstSample *first_sample_header =
119 reinterpret_cast<const struct SensorFirstSample *>(
120 event_data.data() + sizeof(struct SensorEventHeader));
121
122 return first_sample_header->numSamples;
123 }
124
GetReferenceTime() const125 uint64_t TimestampedSensorEvent::GetReferenceTime() const {
126 if (!SizeIsValid()) {
127 return 0;
128 }
129 const struct SensorEventHeader *header =
130 reinterpret_cast<const struct SensorEventHeader *>(event_data.data());
131 return header->reference_time;
132 }
133
GetSampleTime(uint8_t index) const134 uint64_t TimestampedSensorEvent::GetSampleTime(uint8_t index) const {
135 const SensorSampleHeader *sample;
136 uint64_t sample_time = GetReferenceTime();
137
138 // For index 0, the sample time is the reference time. For each subsequent
139 // sample, sum the delta to the previous sample to get the sample time.
140 for (uint8_t i = 1; i <= index; i++) {
141 sample = GetSampleAtIndex(index);
142 sample_time += sample->delta_time;
143 }
144
145 return sample_time;
146 }
147
GetSampleTimeStr(uint8_t index) const148 std::string TimestampedSensorEvent::GetSampleTimeStr(uint8_t index) const {
149 uint64_t sample_time = GetSampleTime(index);
150
151 char buffer[32];
152 snprintf(buffer, sizeof(buffer), "%" PRIu64 ".%06" PRIu64 " ms",
153 sample_time / 1000000, sample_time % 1000000);
154
155 return std::string(buffer);
156 }
157
GetSampleAtIndex(uint8_t index) const158 const SensorSampleHeader *TimestampedSensorEvent::GetSampleAtIndex(
159 uint8_t index) const {
160 if (index >= GetNumSamples()) {
161 LOGW("Requested sample at invalid index %u", index);
162 return nullptr;
163 }
164
165 unsigned int offset = (sizeof(struct SensorEventHeader) +
166 index * GetSampleDataSize());
167 return reinterpret_cast<const struct SensorSampleHeader *>(
168 event_data.data() + offset);
169 }
170
ToString() const171 std::string TimestampedSensorEvent::ToString() const {
172 uint8_t num_samples = GetNumSamples();
173 char buffer[64];
174 snprintf(buffer, sizeof(buffer),
175 "Event from sensor %d (%s) with %d sample%s\n",
176 static_cast<int>(GetSensorType()),
177 ContextHub::SensorTypeToAbbrevName(GetSensorType()).c_str(),
178 num_samples, (num_samples != 1) ? "s" : "");
179
180 return std::string(buffer) + StringForAllSamples();
181 }
182
SizeIsValid() const183 bool TimestampedSensorEvent::SizeIsValid() const {
184 unsigned int min_size = (sizeof(struct SensorEventHeader) +
185 GetNumSamples() * GetSampleDataSize());
186 if (event_data.size() < min_size) {
187 LOGW("Got short sensor event with %zu bytes, expected >= %u",
188 event_data.size(), min_size);
189 return false;
190 }
191
192 return true;
193 }
194
StringForAllSamples() const195 std::string TimestampedSensorEvent::StringForAllSamples() const {
196 std::string str;
197 for (unsigned int i = 0; i < GetNumSamples(); i++) {
198 str += StringForSample(i);
199 }
200 return str;
201 }
202
203 /* SingleAxisSensorEvent ******************************************************/
204
StringForSample(uint8_t index) const205 std::string SingleAxisSensorEvent::StringForSample(uint8_t index) const {
206 const SingleAxisDataPoint *sample =
207 reinterpret_cast<const SingleAxisDataPoint *>(GetSampleAtIndex(index));
208
209 char buffer[64];
210 snprintf(buffer, sizeof(buffer), " %f @ %s\n",
211 sample->fdata, GetSampleTimeStr(index).c_str());
212
213 return std::string(buffer);
214 }
215
GetSampleDataSize() const216 uint8_t SingleAxisSensorEvent::GetSampleDataSize() const {
217 return sizeof(struct SingleAxisDataPoint);
218 }
219
220 /* SingleAxisIntSensorEvent ***************************************************/
221
StringForSample(uint8_t index) const222 std::string SingleAxisIntSensorEvent::StringForSample(uint8_t index) const {
223 const SingleAxisDataPoint *sample =
224 reinterpret_cast<const SingleAxisDataPoint *>(GetSampleAtIndex(index));
225
226 char buffer[64];
227 snprintf(buffer, sizeof(buffer), " %d @ %s\n",
228 sample->idata, GetSampleTimeStr(index).c_str());
229
230 return std::string(buffer);
231 }
232
233 /* TripleAxisSensorEvent ******************************************************/
234
StringForSample(uint8_t index) const235 std::string TripleAxisSensorEvent::StringForSample(uint8_t index) const {
236 const TripleAxisDataPoint *sample =
237 reinterpret_cast<const TripleAxisDataPoint *>(
238 GetSampleAtIndex(index));
239
240 const struct SensorFirstSample *first_sample =
241 reinterpret_cast<const struct SensorFirstSample *>(
242 event_data.data() + sizeof(struct SensorEventHeader));
243 bool is_bias_sample = first_sample->biasPresent
244 && first_sample->biasSample == index;
245
246 char buffer[128];
247 snprintf(buffer, sizeof(buffer), " X:%f Y:%f Z:%f @ %s%s\n",
248 sample->x, sample->y, sample->z, GetSampleTimeStr(index).c_str(),
249 is_bias_sample ? " (Bias Sample)" : "");
250
251 return std::string(buffer);
252 }
253
GetSampleDataSize() const254 uint8_t TripleAxisSensorEvent::GetSampleDataSize() const {
255 return sizeof(struct TripleAxisDataPoint);
256 }
257
258 /* CompressedTripleAxisSensorEvent ********************************************/
259
StringForSample(uint8_t index) const260 std::string CompressedTripleAxisSensorEvent::StringForSample(
261 uint8_t index) const {
262 const CompressedTripleAxisDataPoint *sample =
263 reinterpret_cast<const CompressedTripleAxisDataPoint *>(
264 GetSampleAtIndex(index));
265
266 const struct SensorFirstSample *first_sample =
267 reinterpret_cast<const struct SensorFirstSample *>(
268 event_data.data() + sizeof(struct SensorEventHeader));
269 bool is_bias_sample = first_sample->biasPresent
270 && first_sample->biasSample == index;
271
272 float x = sample->ix * kCompressedSampleRatio;
273 float y = sample->iy * kCompressedSampleRatio;
274 float z = sample->iz * kCompressedSampleRatio;
275
276 char buffer[128];
277 snprintf(buffer, sizeof(buffer), " X:%f Y:%f Z:%f @ %s%s\n",
278 x, y, z, GetSampleTimeStr(index).c_str(),
279 is_bias_sample ? " (Bias Sample)" : "");
280
281 return std::string(buffer);
282 }
283
GetSampleDataSize() const284 uint8_t CompressedTripleAxisSensorEvent::GetSampleDataSize() const {
285 return sizeof(CompressedTripleAxisDataPoint);
286 }
287
288 } // namespace android
289