C++程序  |  288行  |  9.52 KB

/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "sensorevent.h"

#include <inttypes.h>
#include <string.h>

#include "contexthub.h"
#include "log.h"

namespace android {

constexpr float kCompressedSampleRatio(8.0f * 9.81f / 32768.0f);

/* SensorEvent ****************************************************************/

std::unique_ptr<SensorEvent> SensorEvent::FromBytes(
        const std::vector<uint8_t>& buffer) {
    SensorEvent *sensor_event = nullptr;

    SensorType sensor_type = static_cast<SensorType>(
        ReadEventResponse::EventTypeFromBuffer(buffer) -
        static_cast<uint32_t>(EventType::FirstSensorEvent));

    switch (sensor_type) {
      case SensorType::Accel:
      case SensorType::Gyro:
      case SensorType::GyroUncal:
      case SensorType::Magnetometer:
      case SensorType::MagnetometerUncal:
      case SensorType::Orientation:
      case SensorType::Gravity:
      case SensorType::LinearAccel:
      case SensorType::RotationVector:
      case SensorType::GeomagneticRotationVector:
      case SensorType::GameRotationVector:
        sensor_event = new TripleAxisSensorEvent();
        break;

      case SensorType::Barometer:
      case SensorType::Temperature:
      case SensorType::AmbientLightSensor:
      case SensorType::Proximity:
        sensor_event = new SingleAxisSensorEvent();
        break;

      // TODO: Activity uses a special struct, it should have its own class
      case SensorType::Activity:
      case SensorType::AnyMotion:
      case SensorType::NoMotion:
      case SensorType::SignificantMotion:
      case SensorType::Flat:
      case SensorType::WindowOrientation:
      case SensorType::Tilt:
      case SensorType::Hall:
      case SensorType::HeartRateECG: // Heart rates not implemented, guessing
      case SensorType::HeartRatePPG: // data type here...
      case SensorType::StepCount:
      case SensorType::StepDetect:
      case SensorType::Gesture:
      case SensorType::DoubleTwist:
      case SensorType::DoubleTap:
      case SensorType::Vsync:
      case SensorType::WristTilt:
          sensor_event = new SingleAxisIntSensorEvent();
          break;

      case SensorType::CompressedAccel:
          sensor_event = new CompressedTripleAxisSensorEvent();
          break;

    default:
        LOGW("Can't create SensorEvent for unknown/invalid sensor type %d",
             static_cast<int>(sensor_type));
    }

    if (sensor_event &&
        (!sensor_event->Populate(buffer) || !sensor_event->SizeIsValid())) {
        LOGW("Couldn't populate sensor event, or invalid size");
        delete sensor_event;
        sensor_event = nullptr;
    }

    return std::unique_ptr<SensorEvent>(sensor_event);
}

SensorType SensorEvent::GetSensorType() const {
    return static_cast<SensorType>(
        GetEventType() - static_cast<uint32_t>(EventType::FirstSensorEvent));
}

/* TimestampedSensorEvent *****************************************************/

uint8_t TimestampedSensorEvent::GetNumSamples() const {
    // Perform size check, but don't depend on SizeIsValid since it will call us
    if (event_data.size() < (sizeof(struct SensorEventHeader) +
                             sizeof(struct SensorFirstSample))) {
        LOGW("Short/invalid timestamped sensor event; length %zu",
             event_data.size());
        return 0;
    }

    const struct SensorFirstSample *first_sample_header =
        reinterpret_cast<const struct SensorFirstSample *>(
            event_data.data() + sizeof(struct SensorEventHeader));

    return first_sample_header->numSamples;
}

uint64_t TimestampedSensorEvent::GetReferenceTime() const {
    if (!SizeIsValid()) {
        return 0;
    }
    const struct SensorEventHeader *header =
        reinterpret_cast<const struct SensorEventHeader *>(event_data.data());
    return header->reference_time;
}

uint64_t TimestampedSensorEvent::GetSampleTime(uint8_t index) const {
    const SensorSampleHeader *sample;
    uint64_t sample_time = GetReferenceTime();

    // For index 0, the sample time is the reference time. For each subsequent
    // sample, sum the delta to the previous sample to get the sample time.
    for (uint8_t i = 1; i <= index; i++) {
        sample = GetSampleAtIndex(index);
        sample_time += sample->delta_time;
    }

    return sample_time;
}

std::string TimestampedSensorEvent::GetSampleTimeStr(uint8_t index) const {
    uint64_t sample_time = GetSampleTime(index);

    char buffer[32];
    snprintf(buffer, sizeof(buffer), "%" PRIu64 ".%06" PRIu64 " ms",
             sample_time / 1000000, sample_time % 1000000);

    return std::string(buffer);
}

const SensorSampleHeader *TimestampedSensorEvent::GetSampleAtIndex(
        uint8_t index) const {
    if (index >= GetNumSamples()) {
        LOGW("Requested sample at invalid index %u", index);
        return nullptr;
    }

    unsigned int offset = (sizeof(struct SensorEventHeader) +
        index * GetSampleDataSize());
    return reinterpret_cast<const struct SensorSampleHeader *>(
        event_data.data() + offset);
}

std::string TimestampedSensorEvent::ToString() const {
    uint8_t num_samples = GetNumSamples();
    char buffer[64];
    snprintf(buffer, sizeof(buffer),
             "Event from sensor %d (%s) with %d sample%s\n",
             static_cast<int>(GetSensorType()),
             ContextHub::SensorTypeToAbbrevName(GetSensorType()).c_str(),
             num_samples, (num_samples != 1) ? "s" : "");

    return std::string(buffer) + StringForAllSamples();
}

bool TimestampedSensorEvent::SizeIsValid() const {
    unsigned int min_size = (sizeof(struct SensorEventHeader) +
        GetNumSamples() * GetSampleDataSize());
    if (event_data.size() < min_size) {
        LOGW("Got short sensor event with %zu bytes, expected >= %u",
             event_data.size(), min_size);
        return false;
    }

    return true;
}

std::string TimestampedSensorEvent::StringForAllSamples() const {
    std::string str;
    for (unsigned int i = 0; i < GetNumSamples(); i++) {
        str += StringForSample(i);
    }
    return str;
}

/* SingleAxisSensorEvent ******************************************************/

std::string SingleAxisSensorEvent::StringForSample(uint8_t index) const {
    const SingleAxisDataPoint *sample =
        reinterpret_cast<const SingleAxisDataPoint *>(GetSampleAtIndex(index));

    char buffer[64];
    snprintf(buffer, sizeof(buffer), "  %f @ %s\n",
             sample->fdata, GetSampleTimeStr(index).c_str());

    return std::string(buffer);
}

uint8_t SingleAxisSensorEvent::GetSampleDataSize() const {
    return sizeof(struct SingleAxisDataPoint);
}

/* SingleAxisIntSensorEvent ***************************************************/

std::string SingleAxisIntSensorEvent::StringForSample(uint8_t index) const {
    const SingleAxisDataPoint *sample =
        reinterpret_cast<const SingleAxisDataPoint *>(GetSampleAtIndex(index));

    char buffer[64];
    snprintf(buffer, sizeof(buffer), "  %d @ %s\n",
             sample->idata, GetSampleTimeStr(index).c_str());

    return std::string(buffer);
}

/* TripleAxisSensorEvent ******************************************************/

std::string TripleAxisSensorEvent::StringForSample(uint8_t index) const {
    const TripleAxisDataPoint *sample =
        reinterpret_cast<const TripleAxisDataPoint *>(
            GetSampleAtIndex(index));

    const struct SensorFirstSample *first_sample =
        reinterpret_cast<const struct SensorFirstSample *>(
            event_data.data() + sizeof(struct SensorEventHeader));
    bool is_bias_sample = first_sample->biasPresent
        && first_sample->biasSample == index;

    char buffer[128];
    snprintf(buffer, sizeof(buffer), "  X:%f Y:%f Z:%f @ %s%s\n",
             sample->x, sample->y, sample->z, GetSampleTimeStr(index).c_str(),
             is_bias_sample ? " (Bias Sample)" : "");

    return std::string(buffer);
}

uint8_t TripleAxisSensorEvent::GetSampleDataSize() const {
    return sizeof(struct TripleAxisDataPoint);
}

/* CompressedTripleAxisSensorEvent ********************************************/

std::string CompressedTripleAxisSensorEvent::StringForSample(
        uint8_t index) const {
    const CompressedTripleAxisDataPoint *sample =
        reinterpret_cast<const CompressedTripleAxisDataPoint *>(
            GetSampleAtIndex(index));

    const struct SensorFirstSample *first_sample =
        reinterpret_cast<const struct SensorFirstSample *>(
            event_data.data() + sizeof(struct SensorEventHeader));
    bool is_bias_sample = first_sample->biasPresent
        && first_sample->biasSample == index;

    float x = sample->ix * kCompressedSampleRatio;
    float y = sample->iy * kCompressedSampleRatio;
    float z = sample->iz * kCompressedSampleRatio;

    char buffer[128];
    snprintf(buffer, sizeof(buffer), "  X:%f Y:%f Z:%f @ %s%s\n",
             x, y, z, GetSampleTimeStr(index).c_str(),
             is_bias_sample ? " (Bias Sample)" : "");

    return std::string(buffer);
}

uint8_t CompressedTripleAxisSensorEvent::GetSampleDataSize() const {
    return sizeof(CompressedTripleAxisDataPoint);
}

}  // namespace android