Address GNSS VTS code duplication (part 1)
-Moved GNSS callback event queue class from VTS 2.0 code
into common library that is shared with all GNSS VTS tests.
-Modified VTS 1.1 code to reuse GNSS callback event queue in
order to address potential issues noted in b/131869042 and
also to later extract common code from VTS 1.1 and VTS 2.0
into common library.
Bug: 136515339
Test: atest VtsHalGnssV2_0TargetTest
atest VtsHalGnssV1_1TargetTest
Change-Id: I9356e7653f9784a9149b2c2bd6307750e9cc56b3
diff --git a/gnss/common/utils/vts/include/GnssCallbackEventQueue.h b/gnss/common/utils/vts/include/GnssCallbackEventQueue.h
new file mode 100644
index 0000000..b1d8ed4
--- /dev/null
+++ b/gnss/common/utils/vts/include/GnssCallbackEventQueue.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2019 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_hardware_gnss_common_vts_GnssCallbackEventQueue_H_
+#define android_hardware_gnss_common_vts_GnssCallbackEventQueue_H_
+
+#include <log/log.h>
+
+#include <condition_variable>
+#include <deque>
+#include <list>
+#include <mutex>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+/*
+ * Producer/consumer queue for storing/retrieving callback events from GNSS HAL.
+ */
+template <class T>
+class GnssCallbackEventQueue {
+ public:
+ GnssCallbackEventQueue(const std::string& name) : name_(name), called_count_(0){};
+ ~GnssCallbackEventQueue() { 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);
+
+ /*
+ * Removes parameter count number of callack events at the front of the queue, stores
+ * them in event_list parameter and returns the number of events retrieved. Waits up to
+ * timeout_seconds to retrieve each event. If timeout occurs, it returns the number of
+ * items retrieved which will be less than count.
+ */
+ int retrieve(list<T>& event_list, int count, 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:
+ GnssCallbackEventQueue(const GnssCallbackEventQueue&) = delete;
+ GnssCallbackEventQueue& operator=(const GnssCallbackEventQueue&) = delete;
+
+ std::string name_;
+ int called_count_;
+ mutable std::recursive_mutex mtx_;
+ std::condition_variable_any cv_;
+ std::deque<T> events_;
+};
+
+template <class T>
+void GnssCallbackEventQueue<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 GnssCallbackEventQueue<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 GnssCallbackEventQueue<T>::retrieve(list<T>& event_list, int count, int timeout_seconds) {
+ for (int i = 0; i < count; ++i) {
+ T event;
+ if (!retrieve(event, timeout_seconds)) {
+ return i;
+ }
+ event_list.push_back(event);
+ }
+
+ return count;
+}
+
+template <class T>
+int GnssCallbackEventQueue<T>::size() const {
+ std::unique_lock<std::recursive_mutex> lock(mtx_);
+ return events_.size();
+}
+
+template <class T>
+int GnssCallbackEventQueue<T>::calledCount() const {
+ std::unique_lock<std::recursive_mutex> lock(mtx_);
+ return called_count_;
+}
+
+template <class T>
+void GnssCallbackEventQueue<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;
+}
+
+} // namespace common
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_gnss_common_vts_GnssCallbackEventQueue_H_