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 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 100 SensorType SensorEvent::GetSensorType() const { 101 return static_cast<SensorType>( 102 GetEventType() - static_cast<uint32_t>(EventType::FirstSensorEvent)); 103 } 104 105 /* TimestampedSensorEvent *****************************************************/ 106 107 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 123 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 132 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 146 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 156 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 169 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 181 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 193 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 203 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 214 uint8_t SingleAxisSensorEvent::GetSampleDataSize() const { 215 return sizeof(struct SingleAxisDataPoint); 216 } 217 218 /* SingleAxisIntSensorEvent ***************************************************/ 219 220 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 233 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 252 uint8_t TripleAxisSensorEvent::GetSampleDataSize() const { 253 return sizeof(struct TripleAxisDataPoint); 254 } 255 256 /* CompressedTripleAxisSensorEvent ********************************************/ 257 258 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 282 uint8_t CompressedTripleAxisSensorEvent::GetSampleDataSize() const { 283 return sizeof(CompressedTripleAxisDataPoint); 284 } 285 286 } // namespace android 287