mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 16:50:18 +00:00
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:
@@ -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",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -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)++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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\"",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user