Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 18f37015 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes I1d41c6ed,I1e04e734,I4c2a968a

* changes:
  Refactor SensorEventsChecker
  Create SensorsHidlEnvironmentBase
  Extract SensorsHidlEnvironment
parents 7b52ab5b a60a6ae0
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ cc_test {
    name: "VtsHalSensorsV1_0TargetTest",
    defaults: ["VtsHalTargetTestDefaults"],
    srcs: [
        "SensorsHidlEnvironmentV1_0.cpp",
        "VtsHalSensorsV1_0TargetTest.cpp"
    ],
    static_libs: [
+121 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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 "SensorsHidlEnvironmentV1_0.h"

#include <log/log.h>

#include <vector>

using ::android::hardware::hidl_vec;
using ::android::hardware::sensors::V1_0::ISensors;
using ::android::hardware::sensors::V1_0::Result;
using ::android::hardware::sensors::V1_0::SensorInfo;

bool SensorsHidlEnvironmentV1_0::resetHal() {
    // wait upto 100ms * 10 = 1s for hidl service.
    constexpr auto RETRY_DELAY = std::chrono::milliseconds(100);

    std::string step;
    bool succeed = false;
    for (size_t retry = 10; retry > 0; --retry) {
        // this do ... while is for easy error handling
        do {
            step = "getService()";
            sensors = ISensors::getService(
                SensorsHidlEnvironmentV1_0::Instance()->getServiceName<ISensors>());
            if (sensors == nullptr) {
                break;
            }

            step = "poll() check";
            // Poke ISensor service. If it has lingering connection from previous generation of
            // system server, it will kill itself. There is no intention to handle the poll result,
            // which will be done since the size is 0.
            if (!sensors->poll(0, [](auto, const auto&, const auto&) {}).isOk()) {
                break;
            }

            step = "getSensorList";
            std::vector<SensorInfo> sensorList;
            if (!sensors
                     ->getSensorsList([&](const hidl_vec<SensorInfo>& list) {
                         sensorList.reserve(list.size());
                         for (size_t i = 0; i < list.size(); ++i) {
                             sensorList.push_back(list[i]);
                         }
                     })
                     .isOk()) {
                break;
            }

            // stop each sensor individually
            step = "stop each sensor";
            bool ok = true;
            for (const auto& i : sensorList) {
                if (!sensors->activate(i.sensorHandle, false).isOk()) {
                    ok = false;
                    break;
                }
            }
            if (!ok) {
                break;
            }

            // mark it done
            step = "done";
            succeed = true;
        } while (0);

        if (succeed) {
            return true;
        }

        // Delay 100ms before retry, hidl service is expected to come up in short time after crash.
        ALOGI("%s unsuccessful, try again soon (remaining retry %zu).", step.c_str(), retry - 1);
        std::this_thread::sleep_for(RETRY_DELAY);
    }

    sensors = nullptr;
    return false;
}

void SensorsHidlEnvironmentV1_0::startPollingThread() {
    stopThread = false;
    pollThread = std::thread(pollingThread, this, std::ref(stopThread));
    events.reserve(128);
}

void SensorsHidlEnvironmentV1_0::pollingThread(SensorsHidlEnvironmentV1_0* env,
                                               std::atomic_bool& stop) {
    ALOGD("polling thread start");

    while (!stop) {
        env->sensors->poll(
            64, [&](auto result, const auto& events, const auto& dynamicSensorsAdded) {
                if (result != Result::OK ||
                    (events.size() == 0 && dynamicSensorsAdded.size() == 0) || stop) {
                    stop = true;
                    return;
                }

                for (const auto& e : events) {
                    env->addEvent(e);
                }
            });
    }
    ALOGD("polling thread end");
}
 No newline at end of file
+59 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.
 */

#ifndef ANDROID_SENSORS_HIDL_ENVIRONMENT_V1_0_H
#define ANDROID_SENSORS_HIDL_ENVIRONMENT_V1_0_H

#include "sensors-vts-utils/SensorsHidlEnvironmentBase.h"

#include <android/hardware/sensors/1.0/ISensors.h>
#include <android/hardware/sensors/1.0/types.h>
#include <utils/StrongPointer.h>

#include <atomic>
#include <memory>

using ::android::sp;

class SensorsHidlTest;
class SensorsHidlEnvironmentV1_0 : public SensorsHidlEnvironmentBase {
   public:
    using Event = ::android::hardware::sensors::V1_0::Event;
    // get the test environment singleton
    static SensorsHidlEnvironmentV1_0* Instance() {
        static SensorsHidlEnvironmentV1_0* instance = new SensorsHidlEnvironmentV1_0();
        return instance;
    }

    virtual void registerTestServices() override {
        registerTestService<android::hardware::sensors::V1_0::ISensors>();
    }

   private:
    friend SensorsHidlTest;
    // sensors hidl service
    sp<android::hardware::sensors::V1_0::ISensors> sensors;

    SensorsHidlEnvironmentV1_0() {}

    bool resetHal() override;
    void startPollingThread() override;
    static void pollingThread(SensorsHidlEnvironmentV1_0* env, std::atomic_bool& stop);

    GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironmentV1_0);
};

#endif  // ANDROID_SENSORS_HIDL_ENVIRONMENT_V1_0_H
 No newline at end of file
+15 −244
Original line number Diff line number Diff line
@@ -16,7 +16,9 @@

#define LOG_TAG "sensors_hidl_hal_test"

#include "SensorsHidlEnvironmentV1_0.h"
#include "sensors-vts-utils/GrallocWrapper.h"
#include "sensors-vts-utils/SensorEventsChecker.h"

#include <VtsHalHidlTargetTestBase.h>
#include <VtsHalHidlTargetTestEnvBase.h>
@@ -47,183 +49,6 @@ using ::android::hardware::hidl_string;
using ::android::sp;
using namespace ::android::hardware::sensors::V1_0;

// Test environment for sensors
class SensorsHidlTest;
class SensorsHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
   public:
    // get the test environment singleton
    static SensorsHidlEnvironment* Instance() {
        static SensorsHidlEnvironment* instance = new SensorsHidlEnvironment;
        return instance;
    }

    virtual void HidlSetUp() override;
    virtual void HidlTearDown() override;

    virtual void registerTestServices() override { registerTestService<ISensors>(); }

    // Get and clear all events collected so far (like "cat" shell command).
    // If output is nullptr, it clears all collected events.
    void catEvents(std::vector<Event>* output);

    // set sensor event collection status
    void setCollection(bool enable);

   private:
    friend SensorsHidlTest;
    // sensors hidl service
    sp<ISensors> sensors;

    SensorsHidlEnvironment() {}

    void addEvent(const Event& ev);
    void startPollingThread();
    void resetHal();
    static void pollingThread(SensorsHidlEnvironment* env, std::shared_ptr<bool> stop);

    bool collectionEnabled;
    std::shared_ptr<bool> stopThread;
    std::thread pollThread;
    std::vector<Event> events;
    std::mutex events_mutex;

    GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironment);
};

void SensorsHidlEnvironment::HidlSetUp() {
    resetHal();

    ASSERT_NE(sensors, nullptr) << "sensors is nullptr, cannot get hidl service";

    collectionEnabled = false;
    startPollingThread();

    // In case framework just stopped for test and there is sensor events in the pipe,
    // wait some time for those events to be cleared to avoid them messing up the test.
    std::this_thread::sleep_for(std::chrono::seconds(3));
}

void SensorsHidlEnvironment::HidlTearDown() {
    if (stopThread) {
        *stopThread = true;
    }
    pollThread.detach();
}

void SensorsHidlEnvironment::resetHal() {
  // wait upto 100ms * 10 = 1s for hidl service.
  constexpr auto RETRY_DELAY = std::chrono::milliseconds(100);

  std::string step;
  bool succeed = false;
  for (size_t retry = 10; retry > 0; --retry) {
    // this do ... while is for easy error handling
    do {
      step = "getService()";
      sensors = ISensors::getService(
          SensorsHidlEnvironment::Instance()->getServiceName<ISensors>());
      if (sensors == nullptr) {
        break;
      }

      step = "poll() check";
      // Poke ISensor service. If it has lingering connection from previous generation of
      // system server, it will kill itself. There is no intention to handle the poll result,
      // which will be done since the size is 0.
      if(!sensors->poll(0, [](auto, const auto &, const auto &) {}).isOk()) {
        break;
      }

      step = "getSensorList";
      std::vector<SensorInfo> sensorList;
      if (!sensors->getSensorsList(
          [&] (const ::android::hardware::hidl_vec<SensorInfo> &list) {
            sensorList.reserve(list.size());
            for (size_t i = 0; i < list.size(); ++i) {
              sensorList.push_back(list[i]);
            }
          }).isOk()) {
        break;
      }

      // stop each sensor individually
      step = "stop each sensor";
      bool ok = true;
      for (const auto &i : sensorList) {
        if (!sensors->activate(i.sensorHandle, false).isOk()) {
          ok = false;
          break;
        }
      }
      if (!ok) {
        break;
      }

      // mark it done
      step = "done";
      succeed = true;
    } while(0);

    if (succeed) {
      return;
    }

    // Delay 100ms before retry, hidl service is expected to come up in short time after crash.
    ALOGI("%s unsuccessful, try again soon (remaining retry %zu).", step.c_str(), retry - 1);
    std::this_thread::sleep_for(RETRY_DELAY);
  }

  sensors = nullptr;
}

void SensorsHidlEnvironment::catEvents(std::vector<Event>* output) {
  std::lock_guard<std::mutex> lock(events_mutex);
  if (output) {
    output->insert(output->end(), events.begin(), events.end());
  }
  events.clear();
}

void SensorsHidlEnvironment::setCollection(bool enable) {
  std::lock_guard<std::mutex> lock(events_mutex);
  collectionEnabled = enable;
}

void SensorsHidlEnvironment::addEvent(const Event& ev) {
  std::lock_guard<std::mutex> lock(events_mutex);
  if (collectionEnabled) {
    events.push_back(ev);
  }
}

void SensorsHidlEnvironment::startPollingThread() {
  stopThread = std::shared_ptr<bool>(new bool(false));
  pollThread = std::thread(pollingThread, this, stopThread);
  events.reserve(128);
}

void SensorsHidlEnvironment::pollingThread(
    SensorsHidlEnvironment* env, std::shared_ptr<bool> stop) {
  ALOGD("polling thread start");
  bool needExit = *stop;

  while(!needExit) {
      env->sensors->poll(64, [&](auto result, const auto& events, const auto& dynamicSensorsAdded) {
          if (result != Result::OK
              || (events.size() == 0 && dynamicSensorsAdded.size() == 0)
              || *stop) {
              needExit = true;
              return;
          }

          for (const auto& e : events) {
              env->addEvent(e);
          }
      });
  }
  ALOGD("polling thread end");
}

class SensorsTestSharedMemory {
 public:
  static SensorsTestSharedMemory* create(SharedMemType type, size_t size);
@@ -425,58 +250,6 @@ SensorsTestSharedMemory* SensorsTestSharedMemory::create(SharedMemType type, siz
  return m;
}

class SensorEventsChecker {
 public:
  virtual bool check(const std::vector<Event> &events, std::string *out) const = 0;
  virtual ~SensorEventsChecker() {}
};

class NullChecker : public SensorEventsChecker {
 public:
  virtual bool check(const std::vector<Event> &, std::string *) const {
    return true;
  }
};

class SensorEventPerEventChecker : public SensorEventsChecker {
 public:
  virtual bool checkEvent(const Event &event, std::string *out) const = 0;
  virtual bool check(const std::vector<Event> &events, std::string *out) const {
    for (const auto &e : events) {
      if (!checkEvent(e, out)) {
        return false;
      }
    }
    return true;
  }
};

class Vec3NormChecker : public SensorEventPerEventChecker {
 public:
  Vec3NormChecker(float min, float max) : mRange(min, max) {}
  static Vec3NormChecker byNominal(float nominal, float allowedError) {
    return Vec3NormChecker(nominal - allowedError, nominal + allowedError);
  }

  virtual bool checkEvent(const Event &event, std::string *out) const {
    Vec3 v = event.u.vec3;
    float norm = std::sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
    if (norm < mRange.first || norm > mRange.second) {
      if (out != nullptr) {
        std::ostringstream ss;
        ss << "Event @ " << event.timestamp << " (" << v.x << ", " << v.y << ", " << v.z << ")"
           << " has norm " << norm << ", which is beyond range"
           << " [" << mRange.first << ", " << mRange.second << "]";
        *out = ss.str();
      }
      return false;
    }
    return true;
  }
 protected:
  std::pair<float, float> mRange;
};

// The main test class for SENSORS HIDL HAL.
class SensorsHidlTest : public ::testing::VtsHalHidlTargetTestBase {
 public:
@@ -541,9 +314,7 @@ class SensorsHidlTest : public ::testing::VtsHalHidlTargetTestBase {
    return S()->configDirectReport(sensorHandle, channelHandle, rate, _hidl_cb);
  }

  inline sp<ISensors>& S() {
    return SensorsHidlEnvironment::Instance()->sensors;
  }
  inline sp<ISensors>& S() { return SensorsHidlEnvironmentV1_0::Instance()->sensors; }

  inline static SensorFlagBits extractReportMode(uint64_t flag) {
    return (SensorFlagBits) (flag
@@ -629,10 +400,10 @@ std::vector<Event> SensorsHidlTest::collectEvents(useconds_t timeLimitUs, size_t
        nEventLimit, timeLimitUs, clearBeforeStart);

  if (changeCollection) {
    SensorsHidlEnvironment::Instance()->setCollection(true);
      SensorsHidlEnvironmentV1_0::Instance()->setCollection(true);
  }
  if (clearBeforeStart) {
    SensorsHidlEnvironment::Instance()->catEvents(nullptr);
      SensorsHidlEnvironmentV1_0::Instance()->catEvents(nullptr);
  }

  while (timeLimitUs > 0) {
@@ -640,7 +411,7 @@ std::vector<Event> SensorsHidlTest::collectEvents(useconds_t timeLimitUs, size_t
    usleep(duration);
    timeLimitUs -= duration;

    SensorsHidlEnvironment::Instance()->catEvents(&events);
    SensorsHidlEnvironmentV1_0::Instance()->catEvents(&events);
    if (events.size() >= nEventLimit) {
      break;
    }
@@ -649,7 +420,7 @@ std::vector<Event> SensorsHidlTest::collectEvents(useconds_t timeLimitUs, size_t
  }

  if (changeCollection) {
    SensorsHidlEnvironment::Instance()->setCollection(false);
      SensorsHidlEnvironmentV1_0::Instance()->setCollection(false);
  }
  return events;
}
@@ -1244,7 +1015,7 @@ void SensorsHidlTest::testBatchingOperation(SensorType type) {
  // since collection is not enabled all events will go down the drain
  usleep(batchingPeriodInNs / 1000 * 8 / 10);

  SensorsHidlEnvironment::Instance()->setCollection(true);
  SensorsHidlEnvironmentV1_0::Instance()->setCollection(true);
  // clean existing collections
  collectEvents(0 /*timeLimitUs*/, 0/*nEventLimit*/,
        true /*clearBeforeStart*/, false /*change collection*/);
@@ -1257,7 +1028,7 @@ void SensorsHidlTest::testBatchingOperation(SensorType type) {
  events = collectEvents(allowedBatchDeliverTimeNs / 1000,
        minFifoCount, false /*clearBeforeStart*/, false /*change collection*/);

  SensorsHidlEnvironment::Instance()->setCollection(false);
  SensorsHidlEnvironmentV1_0::Instance()->setCollection(false);
  ASSERT_EQ(activate(handle, 0), Result::OK);

  size_t nEvent = 0;
@@ -1513,9 +1284,9 @@ TEST_F(SensorsHidlTest, MagnetometerGrallocDirectReportOperationVeryFast) {
}

int main(int argc, char **argv) {
  ::testing::AddGlobalTestEnvironment(SensorsHidlEnvironment::Instance());
    ::testing::AddGlobalTestEnvironment(SensorsHidlEnvironmentV1_0::Instance());
    ::testing::InitGoogleTest(&argc, argv);
  SensorsHidlEnvironment::Instance()->init(&argc, argv);
    SensorsHidlEnvironmentV1_0::Instance()->init(&argc, argv);
    int status = RUN_ALL_TESTS();
    ALOGI("Test result = %d", status);
    return status;
+3 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ cc_library_static {
    name: "VtsHalSensorsTargetTestUtils",
    srcs: [
        "GrallocWrapper.cpp",
        "SensorsHidlEnvironmentBase.cpp",
    ],
    export_include_dirs: [
        "include",
@@ -28,6 +29,8 @@ cc_library_static {
    static_libs: [
        "android.hardware.graphics.allocator@2.0",
        "android.hardware.graphics.mapper@2.0",
        "android.hardware.sensors@1.0",
        "VtsHalHidlTargetTestBase",
    ],
}
Loading