MH2 | Implement wakelock processing thread

Bug: 136511617
Test: Unit tests cannot be written for this change. Integration testing
will be performed later.

Change-Id: I651b5fde77c6017b3270413de896a947d95ff5f8
This commit is contained in:
Stan Rokita
2019-09-26 13:17:01 -07:00
parent 5bd809c5f3
commit 75cc7bf2fe
7 changed files with 305 additions and 91 deletions

View File

@@ -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",
],
}

View File

@@ -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)++;
}
}

View File

@@ -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);
}
}

View File

@@ -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.
@@ -250,6 +263,31 @@ class HalProxy : public ISensors, public IScopedWakelockRefCounter {
//! Handles the pending writes on events to eventqueue.
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
@@ -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.
*

View File

@@ -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;

View File

@@ -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\"",
],
}

View File

@@ -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;