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