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