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         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