/* * 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 GNSS_HAL_TEST_H_ #define GNSS_HAL_TEST_H_ #include <android/hardware/gnss/2.0/IGnss.h> #include <VtsHalHidlTargetTestBase.h> #include <VtsHalHidlTargetTestEnvBase.h> #include <condition_variable> #include <deque> #include <mutex> using android::hardware::hidl_vec; using android::hardware::Return; using android::hardware::Void; using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrectionsCallback; using android::hardware::gnss::V1_0::GnssLocationFlags; using android::hardware::gnss::V2_0::IGnss; using GnssLocation_1_0 = android::hardware::gnss::V1_0::GnssLocation; using GnssLocation_2_0 = android::hardware::gnss::V2_0::GnssLocation; using IGnssCallback_1_0 = android::hardware::gnss::V1_0::IGnssCallback; using IGnssCallback_2_0 = android::hardware::gnss::V2_0::IGnssCallback; using IGnssMeasurementCallback_1_0 = android::hardware::gnss::V1_0::IGnssMeasurementCallback; using IGnssMeasurementCallback_1_1 = android::hardware::gnss::V1_1::IGnssMeasurementCallback; using IGnssMeasurementCallback_2_0 = android::hardware::gnss::V2_0::IGnssMeasurementCallback; using android::sp; #define TIMEOUT_SEC 2 // for basic commands/responses // Test environment for GNSS HIDL HAL. class GnssHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { public: // get the test environment singleton static GnssHidlEnvironment* Instance() { static GnssHidlEnvironment* instance = new GnssHidlEnvironment; return instance; } virtual void registerTestServices() override { registerTestService<IGnss>(); } private: GnssHidlEnvironment() {} }; // The main test class for GNSS HAL. class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { public: virtual void SetUp() override; virtual void TearDown() override; /* Producer/consumer queue for storing/retrieving callback events from GNSS HAL */ template <class T> class CallbackQueue { public: CallbackQueue(const std::string& name) : name_(name), called_count_(0){}; ~CallbackQueue() { reset(); } /* Adds callback event to the end of the queue. */ void store(const T& event); /* * Removes the callack event at the front of the queue, stores it in event parameter * and returns true. Returns false on timeout and event is not populated. */ bool retrieve(T& event, int timeout_seconds); /* Returns the number of events pending to be retrieved from the callback event queue. */ int size() const; /* Returns the number of callback events received since last reset(). */ int calledCount() const; /* Clears the callback event queue and resets the calledCount() to 0. */ void reset(); private: CallbackQueue(const CallbackQueue&) = delete; CallbackQueue& operator=(const CallbackQueue&) = delete; std::string name_; int called_count_; mutable std::recursive_mutex mtx_; std::condition_variable_any cv_; std::deque<T> events_; }; /* Callback class for data & Event. */ class GnssCallback : public IGnssCallback_2_0 { public: IGnssCallback_1_0::GnssSystemInfo last_info_; android::hardware::hidl_string last_name_; uint32_t last_capabilities_; GnssLocation_2_0 last_location_; CallbackQueue<IGnssCallback_1_0::GnssSystemInfo> info_cbq_; CallbackQueue<android::hardware::hidl_string> name_cbq_; CallbackQueue<uint32_t> capabilities_cbq_; CallbackQueue<GnssLocation_2_0> location_cbq_; CallbackQueue<hidl_vec<IGnssCallback_2_0::GnssSvInfo>> sv_info_cbq_; GnssCallback(); virtual ~GnssCallback() = default; // Dummy callback handlers Return<void> gnssStatusCb(const IGnssCallback_1_0::GnssStatusValue /* status */) override { return Void(); } Return<void> gnssNmeaCb(int64_t /* timestamp */, const android::hardware::hidl_string& /* nmea */) override { return Void(); } Return<void> gnssAcquireWakelockCb() override { return Void(); } Return<void> gnssReleaseWakelockCb() override { return Void(); } Return<void> gnssRequestLocationCb(bool /* independentFromGnss */) override { return Void(); } Return<void> gnssRequestTimeCb() override { return Void(); } // Actual (test) callback handlers Return<void> gnssNameCb(const android::hardware::hidl_string& name) override; Return<void> gnssLocationCb(const GnssLocation_1_0& location) override; Return<void> gnssSetCapabilitesCb(uint32_t capabilities) override; Return<void> gnssSetSystemInfoCb(const IGnssCallback_1_0::GnssSystemInfo& info) override; Return<void> gnssSvStatusCb(const IGnssCallback_1_0::GnssSvStatus& svStatus) override; // New in v2.0 Return<void> gnssLocationCb_2_0(const GnssLocation_2_0& location) override; Return<void> gnssRequestLocationCb_2_0(bool /* independentFromGnss */, bool /* isUserEmergency */) override { return Void(); } Return<void> gnssSetCapabilitiesCb_2_0(uint32_t capabilities) override; Return<void> gnssSvStatusCb_2_0( const hidl_vec<IGnssCallback_2_0::GnssSvInfo>& svInfoList) override; private: Return<void> gnssLocationCbImpl(const GnssLocation_2_0& location); }; /* Callback class for GnssMeasurement. */ class GnssMeasurementCallback : public IGnssMeasurementCallback_2_0 { public: CallbackQueue<IGnssMeasurementCallback_2_0::GnssData> measurement_cbq_; GnssMeasurementCallback() : measurement_cbq_("measurement"){}; virtual ~GnssMeasurementCallback() = default; // Methods from V1_0::IGnssMeasurementCallback follow. Return<void> GnssMeasurementCb(const IGnssMeasurementCallback_1_0::GnssData&) override { return Void(); } // Methods from V1_1::IGnssMeasurementCallback follow. Return<void> gnssMeasurementCb(const IGnssMeasurementCallback_1_1::GnssData&) override { return Void(); } // Methods from V2_0::IGnssMeasurementCallback follow. Return<void> gnssMeasurementCb_2_0(const IGnssMeasurementCallback_2_0::GnssData&) override; }; /* Callback class for GnssMeasurementCorrections. */ class GnssMeasurementCorrectionsCallback : public IMeasurementCorrectionsCallback { public: uint32_t last_capabilities_; CallbackQueue<uint32_t> capabilities_cbq_; GnssMeasurementCorrectionsCallback() : capabilities_cbq_("capabilities"){}; virtual ~GnssMeasurementCorrectionsCallback() = default; // Methods from V1_0::IMeasurementCorrectionsCallback follow. Return<void> setCapabilitiesCb(uint32_t capabilities) override; }; /* * SetUpGnssCallback: * Set GnssCallback and verify the result. */ void SetUpGnssCallback(); /* * StartAndCheckFirstLocation: * Helper function to start location, and check the first one. * * <p> Note this leaves the Location request active, to enable Stop call vs. other call * reordering tests. * * returns true if a location was successfully generated */ bool StartAndCheckFirstLocation(); /* * CheckLocation: * Helper function to vet Location fields * * check_speed: true if speed related fields are also verified. */ void CheckLocation(const GnssLocation_2_0& location, const bool check_speed); /* * StartAndCheckLocations: * Helper function to collect, and check a number of * normal ~1Hz locations. * * Note this leaves the Location request active, to enable Stop call vs. other call * reordering tests. */ void StartAndCheckLocations(int count); /* * StopAndClearLocations: * Helper function to stop locations, and clear any remaining notifications */ void StopAndClearLocations(); /* * SetPositionMode: * Helper function to set positioning mode and verify output */ void SetPositionMode(const int min_interval_msec, const bool low_power_mode); sp<IGnss> gnss_hal_; // GNSS HAL to call into sp<GnssCallback> gnss_cb_; // Primary callback interface }; template <class T> void GnssHalTest::CallbackQueue<T>::store(const T& event) { std::unique_lock<std::recursive_mutex> lock(mtx_); events_.push_back(event); ++called_count_; lock.unlock(); cv_.notify_all(); } template <class T> bool GnssHalTest::CallbackQueue<T>::retrieve(T& event, int timeout_seconds) { std::unique_lock<std::recursive_mutex> lock(mtx_); cv_.wait_for(lock, std::chrono::seconds(timeout_seconds), [&] { return !events_.empty(); }); if (events_.empty()) { return false; } event = events_.front(); events_.pop_front(); return true; } template <class T> int GnssHalTest::CallbackQueue<T>::size() const { std::unique_lock<std::recursive_mutex> lock(mtx_); return events_.size(); } template <class T> int GnssHalTest::CallbackQueue<T>::calledCount() const { std::unique_lock<std::recursive_mutex> lock(mtx_); return called_count_; } template <class T> void GnssHalTest::CallbackQueue<T>::reset() { std::unique_lock<std::recursive_mutex> lock(mtx_); if (!events_.empty()) { ALOGW("%u unprocessed events discarded in callback queue %s", (unsigned int)events_.size(), name_.c_str()); } events_.clear(); called_count_ = 0; } #endif // GNSS_HAL_TEST_H_