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