Home | History | Annotate | Download | only in nanotool
      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