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 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 102 SensorType SensorEvent::GetSensorType() const { 103 return static_cast<SensorType>( 104 GetEventType() - static_cast<uint32_t>(EventType::FirstSensorEvent)); 105 } 106 107 /* TimestampedSensorEvent *****************************************************/ 108 109 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 125 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 134 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 148 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 158 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 171 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 183 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 195 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 205 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 216 uint8_t SingleAxisSensorEvent::GetSampleDataSize() const { 217 return sizeof(struct SingleAxisDataPoint); 218 } 219 220 /* SingleAxisIntSensorEvent ***************************************************/ 221 222 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 235 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 254 uint8_t TripleAxisSensorEvent::GetSampleDataSize() const { 255 return sizeof(struct TripleAxisDataPoint); 256 } 257 258 /* CompressedTripleAxisSensorEvent ********************************************/ 259 260 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 284 uint8_t CompressedTripleAxisSensorEvent::GetSampleDataSize() const { 285 return sizeof(CompressedTripleAxisDataPoint); 286 } 287 288 } // namespace android 289