diff options
-rw-r--r-- | sensors/2.0/multihal/Android.bp | 5 | ||||
-rw-r--r-- | sensors/2.0/multihal/HalProxy.cpp | 155 | ||||
-rw-r--r-- | sensors/2.0/multihal/ScopedWakelock.cpp | 12 | ||||
-rw-r--r-- | sensors/2.0/multihal/include/HalProxy.h | 124 | ||||
-rw-r--r-- | sensors/2.0/multihal/include/ScopedWakelock.h | 35 | ||||
-rw-r--r-- | sensors/2.0/multihal/tests/Android.bp | 6 | ||||
-rw-r--r-- | sensors/2.0/multihal/tests/HalProxy_test.cpp | 59 |
7 files changed, 305 insertions, 91 deletions
diff --git a/sensors/2.0/multihal/Android.bp b/sensors/2.0/multihal/Android.bp index 710835f84d..5c6767671e 100644 --- a/sensors/2.0/multihal/Android.bp +++ b/sensors/2.0/multihal/Android.bp @@ -28,6 +28,7 @@ cc_defaults { "libpower", "libutils", ], + cflags: ["-DLOG_TAG=\"SensorsMultiHal\""], } cc_binary { @@ -45,7 +46,6 @@ cc_binary { ], init_rc: ["android.hardware.sensors@2.0-service-multihal.rc"], vintf_fragments: ["android.hardware.sensors@2.0-multihal.xml"], - cflags: ["-DLOG_TAG=\"SensorsMultiHal\""], } cc_library_headers { @@ -66,4 +66,7 @@ cc_test_library { export_header_lib_headers: [ "android.hardware.sensors@2.0-multihal.header", ], + shared_libs: [ + "libutils", + ], } diff --git a/sensors/2.0/multihal/HalProxy.cpp b/sensors/2.0/multihal/HalProxy.cpp index 5aa3b3d22b..d66721866c 100644 --- a/sensors/2.0/multihal/HalProxy.cpp +++ b/sensors/2.0/multihal/HalProxy.cpp @@ -24,6 +24,7 @@ #include <dlfcn.h> +#include <cinttypes> #include <fstream> #include <functional> #include <thread> @@ -35,6 +36,9 @@ namespace V2_0 { namespace implementation { using ::android::hardware::sensors::V2_0::EventQueueFlagBits; +using ::android::hardware::sensors::V2_0::WakeLockQueueFlagBits; +using ::android::hardware::sensors::V2_0::implementation::getTimeNow; +using ::android::hardware::sensors::V2_0::implementation::kWakelockTimeoutNs; typedef ISensorsSubHal*(SensorsHalGetSubHalFunc)(uint32_t*); @@ -53,23 +57,23 @@ uint32_t setSubHalIndex(uint32_t sensorHandle, size_t subHalIndex) { HalProxy::HalProxy() { const char* kMultiHalConfigFile = "/vendor/etc/sensors/hals.conf"; initializeSubHalListFromConfigFile(kMultiHalConfigFile); - initializeSubHalCallbacksAndSensorList(); + init(); } HalProxy::HalProxy(std::vector<ISensorsSubHal*>& subHalList) : mSubHalList(subHalList) { - initializeSubHalCallbacksAndSensorList(); + init(); } HalProxy::~HalProxy() { - { - std::lock_guard<std::mutex> lockGuard(mEventQueueWriteMutex); - mPendingWritesRun = false; - mEventQueueWriteCV.notify_one(); - } + mThreadsRun.store(false); + mWakelockCV.notify_one(); + mEventQueueWriteCV.notify_one(); if (mPendingWritesThread.joinable()) { mPendingWritesThread.join(); } - // TODO: Cleanup wakeup thread once it is implemented + if (mWakelockThread.joinable()) { + mWakelockThread.join(); + } } Return<void> HalProxy::getSensorsList(getSensorsList_cb _hidl_cb) { @@ -140,7 +144,7 @@ Return<Result> HalProxy::initialize( } mPendingWritesThread = std::thread(startPendingWritesThread, this); - // TODO: start threads to read wake locks. + mWakelockThread = std::thread(startWakelockThread, this); for (size_t i = 0; i < mSubHalList.size(); i++) { auto subHal = mSubHalList[i]; @@ -322,7 +326,7 @@ void HalProxy::initializeSensorList() { } } -void HalProxy::initializeSubHalCallbacksAndSensorList() { +void HalProxy::init() { initializeSubHalCallbacks(); initializeSensorList(); } @@ -334,11 +338,12 @@ void HalProxy::startPendingWritesThread(HalProxy* halProxy) { void HalProxy::handlePendingWrites() { // TODO: Find a way to optimize locking strategy maybe using two mutexes instead of one. std::unique_lock<std::mutex> lock(mEventQueueWriteMutex); - while (mPendingWritesRun) { + while (mThreadsRun.load()) { mEventQueueWriteCV.wait( - lock, [&] { return !mPendingWriteEventsQueue.empty() || !mPendingWritesRun; }); - if (!mPendingWriteEventsQueue.empty() && mPendingWritesRun) { - std::vector<Event>& pendingWriteEvents = mPendingWriteEventsQueue.front(); + lock, [&] { return !mPendingWriteEventsQueue.empty() || !mThreadsRun.load(); }); + if (mThreadsRun.load()) { + std::vector<Event>& pendingWriteEvents = mPendingWriteEventsQueue.front().first; + size_t numWakeupEvents = mPendingWriteEventsQueue.front().second; size_t eventQueueSize = mEventQueue->getQuantumCount(); size_t numToWrite = std::min(pendingWriteEvents.size(), eventQueueSize); lock.unlock(); @@ -348,10 +353,16 @@ void HalProxy::handlePendingWrites() { pendingWriteEvents.data(), numToWrite, static_cast<uint32_t>(EventQueueFlagBits::EVENTS_READ), static_cast<uint32_t>(EventQueueFlagBits::READ_AND_PROCESS), - kWakelockTimeoutNs, mEventQueueFlag)) { + kPendingWriteTimeoutNs, mEventQueueFlag)) { ALOGE("Dropping %zu events after blockingWrite failed.", numToWrite); - } else { - mEventQueueFlag->wake(static_cast<uint32_t>(EventQueueFlagBits::READ_AND_PROCESS)); + if (numWakeupEvents > 0) { + if (pendingWriteEvents.size() > eventQueueSize) { + decrementRefCountAndMaybeReleaseWakelock( + countNumWakeupEvents(pendingWriteEvents, eventQueueSize)); + } else { + decrementRefCountAndMaybeReleaseWakelock(numWakeupEvents); + } + } } lock.lock(); if (pendingWriteEvents.size() > eventQueueSize) { @@ -366,9 +377,60 @@ void HalProxy::handlePendingWrites() { } } -void HalProxy::postEventsToMessageQueue(const std::vector<Event>& events) { +void HalProxy::startWakelockThread(HalProxy* halProxy) { + halProxy->handleWakelocks(); +} + +void HalProxy::handleWakelocks() { + std::unique_lock<std::recursive_mutex> lock(mWakelockMutex); + while (mThreadsRun.load()) { + mWakelockCV.wait(lock, [&] { return mWakelockRefCount > 0 || !mThreadsRun.load(); }); + if (mThreadsRun.load()) { + int64_t timeLeft; + if (sharedWakelockDidTimeout(&timeLeft)) { + resetSharedWakelock(); + } else { + uint32_t numWakeLocksProcessed; + lock.unlock(); + bool success = mWakeLockQueue->readBlocking( + &numWakeLocksProcessed, 1, 0, + static_cast<uint32_t>(WakeLockQueueFlagBits::DATA_WRITTEN), timeLeft); + lock.lock(); + if (success) { + decrementRefCountAndMaybeReleaseWakelock( + static_cast<size_t>(numWakeLocksProcessed)); + } + } + } + } + resetSharedWakelock(); +} + +bool HalProxy::sharedWakelockDidTimeout(int64_t* timeLeft) { + bool didTimeout; + int64_t duration = getTimeNow() - mWakelockTimeoutStartTime; + if (duration > kWakelockTimeoutNs) { + didTimeout = true; + } else { + didTimeout = false; + *timeLeft = kWakelockTimeoutNs - duration; + } + return didTimeout; +} + +void HalProxy::resetSharedWakelock() { + std::lock_guard<std::recursive_mutex> lockGuard(mWakelockMutex); + decrementRefCountAndMaybeReleaseWakelock(mWakelockRefCount); + mWakelockTimeoutResetTime = getTimeNow(); +} + +void HalProxy::postEventsToMessageQueue(const std::vector<Event>& events, size_t numWakeupEvents, + ScopedWakelock wakelock) { size_t numToWrite = 0; std::lock_guard<std::mutex> lock(mEventQueueWriteMutex); + if (wakelock.isLocked()) { + incrementRefCountAndMaybeAcquireWakelock(numWakeupEvents); + } if (mPendingWriteEventsQueue.empty()) { numToWrite = std::min(events.size(), mEventQueue->availableToWrite()); if (numToWrite > 0) { @@ -384,28 +446,37 @@ void HalProxy::postEventsToMessageQueue(const std::vector<Event>& events) { if (numToWrite < events.size()) { // TODO: Bound the mPendingWriteEventsQueue so that we do not trigger OOMs if framework // stalls - mPendingWriteEventsQueue.push( - std::vector<Event>(events.begin() + numToWrite, events.end())); + std::vector<Event> eventsLeft(events.begin() + numToWrite, events.end()); + mPendingWriteEventsQueue.push({eventsLeft, numWakeupEvents}); mEventQueueWriteCV.notify_one(); } } -// TODO: Implement the wakelock timeout in these next two methods. Also pass in the subhal -// index for better tracking. - -void HalProxy::incrementRefCountAndMaybeAcquireWakelock() { - std::lock_guard<std::mutex> lockGuard(mWakelockRefCountMutex); +bool HalProxy::incrementRefCountAndMaybeAcquireWakelock(size_t delta, + int64_t* timeoutStart /* = nullptr */) { + if (!mThreadsRun.load()) return false; + std::lock_guard<std::recursive_mutex> lockGuard(mWakelockMutex); if (mWakelockRefCount == 0) { - acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLockName); + acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakelockName); + mWakelockCV.notify_one(); } - mWakelockRefCount++; + mWakelockTimeoutStartTime = getTimeNow(); + mWakelockRefCount += delta; + if (timeoutStart != nullptr) { + *timeoutStart = mWakelockTimeoutStartTime; + } + return true; } -void HalProxy::decrementRefCountAndMaybeReleaseWakelock() { - std::lock_guard<std::mutex> lockGuard(mWakelockRefCountMutex); - mWakelockRefCount--; +void HalProxy::decrementRefCountAndMaybeReleaseWakelock(size_t delta, + int64_t timeoutStart /* = -1 */) { + if (!mThreadsRun.load()) return; + std::lock_guard<std::recursive_mutex> lockGuard(mWakelockMutex); + if (timeoutStart == -1) timeoutStart = mWakelockTimeoutResetTime; + if (mWakelockRefCount == 0 || timeoutStart < mWakelockTimeoutResetTime) return; + mWakelockRefCount -= std::min(mWakelockRefCount, delta); if (mWakelockRefCount == 0) { - release_wake_lock(kWakeLockName); + release_wake_lock(kWakelockName); } } @@ -427,6 +498,17 @@ ISensorsSubHal* HalProxy::getSubHalForSensorHandle(uint32_t sensorHandle) { return mSubHalList[static_cast<size_t>(sensorHandle >> 24)]; } +size_t HalProxy::countNumWakeupEvents(const std::vector<Event>& events, size_t n) { + size_t numWakeupEvents = 0; + for (size_t i = 0; i < n; i++) { + int32_t sensorHandle = events[i].sensorHandle; + if (mSensors[sensorHandle].flags & static_cast<uint32_t>(V1_0::SensorFlagBits::WAKE_UP)) { + numWakeupEvents++; + } + } + return numWakeupEvents; +} + uint32_t HalProxy::clearSubHalIndex(uint32_t sensorHandle) { return sensorHandle & (~kSensorHandleSubHalIndexMask); } @@ -436,7 +518,7 @@ bool HalProxy::subHalIndexIsClear(uint32_t sensorHandle) { } void HalProxyCallback::postEvents(const std::vector<Event>& events, ScopedWakelock wakelock) { - (void)wakelock; + if (events.empty() || !mHalProxy->areThreadsRunning()) return; size_t numWakeupEvents; std::vector<Event> processedEvents = processEvents(events, &numWakeupEvents); if (numWakeupEvents > 0) { @@ -450,8 +532,7 @@ void HalProxyCallback::postEvents(const std::vector<Event>& events, ScopedWakelo " w/ index %zu.", mSubHalIndex); } - - mHalProxy->postEventsToMessageQueue(processedEvents); + mHalProxy->postEventsToMessageQueue(events, numWakeupEvents, std::move(wakelock)); } ScopedWakelock HalProxyCallback::createScopedWakelock(bool lock) { @@ -461,13 +542,13 @@ ScopedWakelock HalProxyCallback::createScopedWakelock(bool lock) { std::vector<Event> HalProxyCallback::processEvents(const std::vector<Event>& events, size_t* numWakeupEvents) const { - std::vector<Event> eventsOut; *numWakeupEvents = 0; + std::vector<Event> eventsOut; for (Event event : events) { event.sensorHandle = setSubHalIndex(event.sensorHandle, mSubHalIndex); eventsOut.push_back(event); - if ((mHalProxy->getSensorInfo(event.sensorHandle).flags & V1_0::SensorFlagBits::WAKE_UP) != - 0) { + const SensorInfo& sensor = mHalProxy->getSensorInfo(event.sensorHandle); + if ((sensor.flags & V1_0::SensorFlagBits::WAKE_UP) != 0) { (*numWakeupEvents)++; } } diff --git a/sensors/2.0/multihal/ScopedWakelock.cpp b/sensors/2.0/multihal/ScopedWakelock.cpp index 0430fa393e..d85d4a7891 100644 --- a/sensors/2.0/multihal/ScopedWakelock.cpp +++ b/sensors/2.0/multihal/ScopedWakelock.cpp @@ -22,18 +22,22 @@ namespace sensors { namespace V2_0 { namespace implementation { +int64_t getTimeNow() { + return std::chrono::duration_cast<std::chrono::nanoseconds>( + std::chrono::system_clock::now().time_since_epoch()) + .count(); +} + ScopedWakelock::ScopedWakelock(IScopedWakelockRefCounter* refCounter, bool locked) : mRefCounter(refCounter), mLocked(locked) { - // TODO: Move this implementation into HalProxy object instead if (mLocked) { - mRefCounter->incrementRefCountAndMaybeAcquireWakelock(); + mLocked = mRefCounter->incrementRefCountAndMaybeAcquireWakelock(1, &mCreatedAtTimeNs); } } ScopedWakelock::~ScopedWakelock() { - // TODO: Move this implementation into HalProxy object instead if (mLocked) { - mRefCounter->decrementRefCountAndMaybeReleaseWakelock(); + mRefCounter->decrementRefCountAndMaybeReleaseWakelock(1, mCreatedAtTimeNs); } } diff --git a/sensors/2.0/multihal/include/HalProxy.h b/sensors/2.0/multihal/include/HalProxy.h index 47571a6368..6592afef96 100644 --- a/sensors/2.0/multihal/include/HalProxy.h +++ b/sensors/2.0/multihal/include/HalProxy.h @@ -16,9 +16,11 @@ #pragma once +#include "ScopedWakelock.h" #include "SubHal.h" #include <android/hardware/sensors/2.0/ISensors.h> +#include <android/hardware/sensors/2.0/types.h> #include <fmq/MessageQueue.h> #include <hardware_legacy/power.h> #include <hidl/MQDescriptor.h> @@ -30,6 +32,7 @@ #include <mutex> #include <queue> #include <thread> +#include <utility> namespace android { namespace hardware { @@ -100,45 +103,41 @@ class HalProxy : public ISensors, public IScopedWakelockRefCounter { Return<void> onDynamicSensorsDisconnected(const hidl_vec<int32_t>& dynamicSensorHandlesRemoved, int32_t subHalIndex); - // Below methods follow IScopedWakelockRefCounter - - /** - * Increment ref count and maybe acquire wakelock. - */ - void incrementRefCountAndMaybeAcquireWakelock() override; - - /** - * Decrement ref count and maybe release wakelock. - */ - void decrementRefCountAndMaybeReleaseWakelock() override; - // Below methods are for HalProxyCallback /** * Post events to the event message queue if there is room to write them. Otherwise post the - * remaining events to a background thread for a blocking write with a 5 second timeout. + * remaining events to a background thread for a blocking write with a kPendingWriteTimeoutNs + * timeout. * * @param events The list of events to post to the message queue. + * @param numWakeupEvents The number of wakeup events in events. + * @param wakelock The wakelock associated with this post of events. */ - void postEventsToMessageQueue(const std::vector<Event>& events); + void postEventsToMessageQueue(const std::vector<Event>& events, size_t numWakeupEvents, + ScopedWakelock wakelock); /** - * Get the SensorInfo object associated with the sensorHandle. + * Get the sensor info associated with that sensorHandle. * - * @param sensorHandle The sensorHandle for the sensor. + * @param sensorHandle The sensor handle. * - * @return The sensor info for the sensor. + * @return The sensor info object in the mapping. */ - const SensorInfo& getSensorInfo(uint32_t sensorHandle) const { - return mSensors.at(sensorHandle); - } + const SensorInfo& getSensorInfo(uint32_t sensorHandle) { return mSensors[sensorHandle]; } + + bool areThreadsRunning() { return mThreadsRun.load(); } + + // Below methods are from IScopedWakelockRefCounter interface + bool incrementRefCountAndMaybeAcquireWakelock(size_t delta, + int64_t* timeoutStart = nullptr) override; + + void decrementRefCountAndMaybeReleaseWakelock(size_t delta, int64_t timeoutStart = -1) override; private: using EventMessageQueue = MessageQueue<Event, kSynchronizedReadWrite>; using WakeLockMessageQueue = MessageQueue<uint32_t, kSynchronizedReadWrite>; - const char* kWakeLockName = "SensorsHAL_WAKEUP"; - /** * The Event FMQ where sensor events are written */ @@ -185,23 +184,17 @@ class HalProxy : public ISensors, public IScopedWakelockRefCounter { //! The single subHal that supports directChannel reporting. ISensorsSubHal* mDirectChannelSubHal = nullptr; - //! The mutex for the event queue. - std::mutex mEventQueueMutex; - //! The timeout for each pending write on background thread for events. - static const int64_t kWakelockTimeoutNs = 5 * INT64_C(1000000000) /* 5 seconds */; - - //! The scoped wakelock ref count. - size_t mWakelockRefCount = 0; - - //! The mutex guarding the mWakelockRefCount variable - std::mutex mWakelockRefCountMutex; + static const int64_t kPendingWriteTimeoutNs = 5 * INT64_C(1000000000) /* 5 seconds */; //! The bit mask used to get the subhal index from a sensor handle. static constexpr uint32_t kSensorHandleSubHalIndexMask = 0xFF000000; - //! The events that were not able to be written to fmq right away - std::queue<std::vector<Event>> mPendingWriteEventsQueue; + /** + * A FIFO queue of pairs of vector of events and the number of wakeup events in that vector + * which are waiting to be written to the events fmq in the background thread. + */ + std::queue<std::pair<std::vector<Event>, size_t>> mPendingWriteEventsQueue; //! The mutex protecting writing to the fmq and the pending events queue std::mutex mEventQueueWriteMutex; @@ -212,12 +205,32 @@ class HalProxy : public ISensors, public IScopedWakelockRefCounter { //! The thread object ptr that handles pending writes std::thread mPendingWritesThread; - //! The bool indicating whether to end the pending writes background thread or not - bool mPendingWritesRun = true; + //! The thread object that handles wakelocks + std::thread mWakelockThread; + + //! The bool indicating whether to end the threads started in initialize + std::atomic_bool mThreadsRun = true; //! The mutex protecting access to the dynamic sensors added and removed methods. std::mutex mDynamicSensorsMutex; + // WakelockRefCount membar vars below + + //! The mutex protecting the wakelock refcount and subsequent wakelock releases and + //! acquisitions + std::recursive_mutex mWakelockMutex; + + std::condition_variable_any mWakelockCV; + + //! The refcount of how many ScopedWakelocks and pending wakeup events are active + size_t mWakelockRefCount = 0; + + int64_t mWakelockTimeoutStartTime = getTimeNow(); + + int64_t mWakelockTimeoutResetTime = getTimeNow(); + + const char* kWakelockName = "SensorsMultiHal"; + /** * Initialize the list of SubHal objects in mSubHalList by reading from dynamic libraries * listed in a config file. @@ -236,9 +249,9 @@ class HalProxy : public ISensors, public IScopedWakelockRefCounter { void initializeSensorList(); /** - * Calls the above two helper methods which are shared in both ctors. + * Calls the helper methods that all ctors use. */ - void initializeSubHalCallbacksAndSensorList(); + void init(); /** * Starts the thread that handles pending writes to event fmq. @@ -251,6 +264,31 @@ class HalProxy : public ISensors, public IScopedWakelockRefCounter { void handlePendingWrites(); /** + * Starts the thread that handles decrementing the ref count on wakeup events processed by the + * framework and timing out wakelocks. + * + * @param halProxy The HalProxy object pointer. + */ + static void startWakelockThread(HalProxy* halProxy); + + //! Handles the wakelocks. + void handleWakelocks(); + + /** + * @param timeLeft The variable that should be set to the timeleft before timeout will occur or + * unmodified if timeout occurred. + * + * @return true if the shared wakelock has been held passed the timeout and should be released + */ + bool sharedWakelockDidTimeout(int64_t* timeLeft); + + /** + * Reset all the member variables associated with the wakelock ref count and maybe release + * the shared wakelock. + */ + void resetSharedWakelock(); + + /** * Clear direct channel flags if the HalProxy has already chosen a subhal as its direct channel * subhal. Set the directChannelSubHal pointer to the subHal passed in if this is the first * direct channel enabled sensor seen. @@ -269,6 +307,16 @@ class HalProxy : public ISensors, public IScopedWakelockRefCounter { */ ISensorsSubHal* getSubHalForSensorHandle(uint32_t sensorHandle); + /** + * Count the number of wakeup events in the first n events of the vector. + * + * @param events The vector of Event objects. + * @param n The end index not inclusive of events to consider. + * + * @return The number of wakeup events of the considered events. + */ + size_t countNumWakeupEvents(const std::vector<Event>& events, size_t n); + /* * Clear out the subhal index bytes from a sensorHandle. * diff --git a/sensors/2.0/multihal/include/ScopedWakelock.h b/sensors/2.0/multihal/include/ScopedWakelock.h index a151f1566f..aa6d9db3d4 100644 --- a/sensors/2.0/multihal/include/ScopedWakelock.h +++ b/sensors/2.0/multihal/include/ScopedWakelock.h @@ -16,7 +16,7 @@ #pragma once -#include <mutex> +#include <android/hardware/sensors/2.0/types.h> namespace android { namespace hardware { @@ -24,10 +24,36 @@ namespace sensors { namespace V2_0 { namespace implementation { -class IScopedWakelockRefCounter { +using ::android::hardware::sensors::V2_0::SensorTimeout; + +const int64_t kWakelockTimeoutNs = + static_cast<int64_t>(SensorTimeout::WAKE_LOCK_SECONDS) * INT64_C(1000000000); + +int64_t getTimeNow(); + +class IScopedWakelockRefCounter : public RefBase { public: - virtual void incrementRefCountAndMaybeAcquireWakelock() = 0; - virtual void decrementRefCountAndMaybeReleaseWakelock() = 0; + /** + * Increment the wakelock ref count and maybe acquire the shared wakelock if incrementing + * from 0 then return the time of incrementing back to caller. + * + * @param delta The amount to change ref count by. + * @param timeoutStart The ptr to the timestamp in ns that the increment occurred which will be + * set in the function or nullptr if not specified. + * + * @return true if successfully incremented the wakelock ref count. + */ + virtual bool incrementRefCountAndMaybeAcquireWakelock(size_t delta, + int64_t* timeoutStart = nullptr) = 0; + /** + * Decrement the wakelock ref count and maybe release wakelock if ref count ends up 0. + * + * @param delta The amount to change ref count by. + * @param timeoutStart The timestamp in ns that the calling context kept track of when + * incrementing the ref count or -1 by default + */ + virtual void decrementRefCountAndMaybeReleaseWakelock(size_t delta, + int64_t timeoutStart = -1) = 0; // Virtual dtor needed for compilation success virtual ~IScopedWakelockRefCounter(){}; }; @@ -64,6 +90,7 @@ class ScopedWakelock { private: friend class HalProxyCallback; IScopedWakelockRefCounter* mRefCounter; + int64_t mCreatedAtTimeNs; bool mLocked; ScopedWakelock(IScopedWakelockRefCounter* refCounter, bool locked); ScopedWakelock(const ScopedWakelock&) = delete; diff --git a/sensors/2.0/multihal/tests/Android.bp b/sensors/2.0/multihal/tests/Android.bp index aa44687590..e3a4af1e5a 100644 --- a/sensors/2.0/multihal/tests/Android.bp +++ b/sensors/2.0/multihal/tests/Android.bp @@ -35,6 +35,9 @@ cc_defaults { static_libs: [ "android.hardware.sensors@2.0-HalProxy", ], + cflags: [ + "-DLOG_TAG=\"FakeSubHal\"" + ], } cc_library { @@ -87,4 +90,7 @@ cc_test { "libutils", ], test_suites: ["device-tests"], + cflags: [ + "-DLOG_TAG=\"HalProxyUnitTests\"", + ], } diff --git a/sensors/2.0/multihal/tests/HalProxy_test.cpp b/sensors/2.0/multihal/tests/HalProxy_test.cpp index c8fbb730f6..ad1b96fc78 100644 --- a/sensors/2.0/multihal/tests/HalProxy_test.cpp +++ b/sensors/2.0/multihal/tests/HalProxy_test.cpp @@ -29,6 +29,7 @@ namespace { +using ::android::hardware::EventFlag; using ::android::hardware::hidl_vec; using ::android::hardware::MessageQueue; using ::android::hardware::Return; @@ -36,7 +37,9 @@ using ::android::hardware::sensors::V1_0::EventPayload; using ::android::hardware::sensors::V1_0::SensorFlagBits; using ::android::hardware::sensors::V1_0::SensorInfo; using ::android::hardware::sensors::V1_0::SensorType; +using ::android::hardware::sensors::V2_0::EventQueueFlagBits; using ::android::hardware::sensors::V2_0::ISensorsCallback; +using ::android::hardware::sensors::V2_0::WakeLockQueueFlagBits; using ::android::hardware::sensors::V2_0::implementation::HalProxy; using ::android::hardware::sensors::V2_0::implementation::HalProxyCallback; using ::android::hardware::sensors::V2_0::subhal::implementation::AddAndRemoveDynamicSensorsSubHal; @@ -123,6 +126,12 @@ void testSensorsListFromProxyAndSubHal(const std::vector<SensorInfo>& proxySenso void testSensorsListForOneDirectChannelEnabledSubHal(const std::vector<SensorInfo>& sensorsList, size_t enabledSubHalIndex); +void ackWakeupEventsToHalProxy(size_t numEvents, std::unique_ptr<WakeupMessageQueue>& wakelockQueue, + EventFlag* wakelockQueueFlag); + +bool readEventsOutOfQueue(size_t numEvents, std::unique_ptr<EventMessageQueue>& eventQueue, + EventFlag* eventQueueFlag); + /** * Construct and return a HIDL Event type thats sensorHandle refers to a proximity sensor * which is a wakeup type sensor. @@ -313,10 +322,19 @@ TEST(HalProxyTest, PostSingleWakeupEvent) { ::android::sp<ISensorsCallback> callback = new SensorsCallback(); proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback); + EventFlag* eventQueueFlag; + EventFlag::createEventFlag(eventQueue->getEventFlagWord(), &eventQueueFlag); + + EventFlag* wakelockQueueFlag; + EventFlag::createEventFlag(wakeLockQueue->getEventFlagWord(), &wakelockQueueFlag); + std::vector<Event> events{makeProximityEvent()}; subHal.postEvents(events, true /* wakeup */); EXPECT_EQ(eventQueue->availableToRead(), 1); + + readEventsOutOfQueue(1, eventQueue, eventQueueFlag); + ackWakeupEventsToHalProxy(1, wakeLockQueue, wakelockQueueFlag); } TEST(HalProxyTest, PostMultipleWakeupEvents) { @@ -332,10 +350,19 @@ TEST(HalProxyTest, PostMultipleWakeupEvents) { ::android::sp<ISensorsCallback> callback = new SensorsCallback(); proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback); + EventFlag* eventQueueFlag; + EventFlag::createEventFlag(eventQueue->getEventFlagWord(), &eventQueueFlag); + + EventFlag* wakelockQueueFlag; + EventFlag::createEventFlag(wakeLockQueue->getEventFlagWord(), &wakelockQueueFlag); + std::vector<Event> events = makeMultipleProximityEvents(kNumEvents); subHal.postEvents(events, true /* wakeup */); EXPECT_EQ(eventQueue->availableToRead(), kNumEvents); + + readEventsOutOfQueue(kNumEvents, eventQueue, eventQueueFlag); + ackWakeupEventsToHalProxy(kNumEvents, wakeLockQueue, wakelockQueueFlag); } TEST(HalProxyTest, PostEventsMultipleSubhals) { @@ -374,20 +401,21 @@ TEST(HalProxyTest, PostEventsDelayedWrite) { ::android::sp<ISensorsCallback> callback = new SensorsCallback(); proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback); + EventFlag* eventQueueFlag; + EventFlag::createEventFlag(eventQueue->getEventFlagWord(), &eventQueueFlag); + std::vector<Event> events = makeMultipleAccelerometerEvents(kNumEvents); subHal1.postEvents(events, false /* wakeup */); EXPECT_EQ(eventQueue->availableToRead(), kQueueSize); - Event eventOut; - // writeblock 1 event out of queue, timeout for half a second - EXPECT_TRUE(eventQueue->readBlocking(&eventOut, 1, 500000000)); + // readblock a full queue size worth of events out of queue, timeout for half a second + EXPECT_TRUE(readEventsOutOfQueue(kQueueSize, eventQueue, eventQueueFlag)); - // Sleep for a half second so that blocking write has time complete in background thread - std::this_thread::sleep_for(std::chrono::milliseconds(500)); + // proxy background thread should have wrote remaining events when it saw space + EXPECT_TRUE(readEventsOutOfQueue(kNumEvents - kQueueSize, eventQueue, eventQueueFlag)); - // proxy background thread should have wrote last event when it saw space - EXPECT_EQ(eventQueue->availableToRead(), kQueueSize); + EXPECT_EQ(eventQueue->availableToRead(), 0); } TEST(HalProxyTest, PostEventsMultipleSubhalsThreaded) { @@ -548,6 +576,23 @@ void testSensorsListForOneDirectChannelEnabledSubHal(const std::vector<SensorInf } } +void ackWakeupEventsToHalProxy(size_t numEvents, std::unique_ptr<WakeupMessageQueue>& wakelockQueue, + EventFlag* wakelockQueueFlag) { + uint32_t numEventsUInt32 = static_cast<uint32_t>(numEvents); + wakelockQueue->write(&numEventsUInt32); + wakelockQueueFlag->wake(static_cast<uint32_t>(WakeLockQueueFlagBits::DATA_WRITTEN)); +} + +bool readEventsOutOfQueue(size_t numEvents, std::unique_ptr<EventMessageQueue>& eventQueue, + EventFlag* eventQueueFlag) { + constexpr int64_t kReadBlockingTimeout = INT64_C(500000000); + std::vector<Event> events(numEvents); + return eventQueue->readBlocking(events.data(), numEvents, + static_cast<uint32_t>(EventQueueFlagBits::EVENTS_READ), + static_cast<uint32_t>(EventQueueFlagBits::READ_AND_PROCESS), + kReadBlockingTimeout, eventQueueFlag); +} + Event makeProximityEvent() { Event event; event.timestamp = 0xFF00FF00; |