• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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