diff --git a/sensors/2.0/default/Android.bp b/sensors/2.0/default/Android.bp index 11612d3479..db0b14881e 100644 --- a/sensors/2.0/default/Android.bp +++ b/sensors/2.0/default/Android.bp @@ -32,6 +32,7 @@ cc_binary { "libhidlbase", "libhidltransport", "liblog", + "libpower", "libutils", ], } diff --git a/sensors/2.0/default/Sensor.cpp b/sensors/2.0/default/Sensor.cpp index 17337e21b0..168b40219c 100644 --- a/sensors/2.0/default/Sensor.cpp +++ b/sensors/2.0/default/Sensor.cpp @@ -86,7 +86,7 @@ Result Sensor::flush() { ev.sensorType = SensorType::ADDITIONAL_INFO; ev.u.meta.what = MetaDataEventType::META_DATA_FLUSH_COMPLETE; std::vector evs{ev}; - mCallback->postEvents(evs); + mCallback->postEvents(evs, isWakeUpSensor()); return Result::OK; } @@ -113,7 +113,7 @@ void Sensor::run() { if (now >= nextSampleTime) { mLastSampleTimeNs = now; nextSampleTime = mLastSampleTimeNs + mSamplingPeriodNs; - mCallback->postEvents(readEvents()); + mCallback->postEvents(readEvents(), isWakeUpSensor()); } mWaitCV.wait_for(runLock, std::chrono::nanoseconds(nextSampleTime - now)); @@ -121,6 +121,10 @@ void Sensor::run() { } } +bool Sensor::isWakeUpSensor() { + return mSensorInfo.flags & static_cast(SensorFlagBits::WAKE_UP); +} + std::vector Sensor::readEvents() { std::vector events; Event event; @@ -155,7 +159,7 @@ Result Sensor::injectEvent(const Event& event) { } else if (!supportsDataInjection()) { result = Result::INVALID_OPERATION; } else if (mMode == OperationMode::DATA_INJECTION) { - mCallback->postEvents(std::vector{event}); + mCallback->postEvents(std::vector{event}, isWakeUpSensor()); } else { result = Result::BAD_VALUE; } diff --git a/sensors/2.0/default/Sensor.h b/sensors/2.0/default/Sensor.h index 7fb927a1b6..3ab2299a23 100644 --- a/sensors/2.0/default/Sensor.h +++ b/sensors/2.0/default/Sensor.h @@ -40,7 +40,7 @@ namespace implementation { class ISensorsEventCallback { public: virtual ~ISensorsEventCallback(){}; - virtual void postEvents(const std::vector& events) = 0; + virtual void postEvents(const std::vector& events, bool wakeup) = 0; }; class Sensor { @@ -62,6 +62,8 @@ class Sensor { virtual std::vector readEvents(); static void startThread(Sensor* sensor); + bool isWakeUpSensor(); + bool mIsEnabled; int64_t mSamplingPeriodNs; int64_t mLastSampleTimeNs; diff --git a/sensors/2.0/default/Sensors.cpp b/sensors/2.0/default/Sensors.cpp index 4346ee1ebf..18240dab4a 100644 --- a/sensors/2.0/default/Sensors.cpp +++ b/sensors/2.0/default/Sensors.cpp @@ -30,8 +30,16 @@ using ::android::hardware::sensors::V1_0::OperationMode; using ::android::hardware::sensors::V1_0::RateLevel; using ::android::hardware::sensors::V1_0::Result; using ::android::hardware::sensors::V1_0::SharedMemInfo; +using ::android::hardware::sensors::V2_0::SensorTimeout; -Sensors::Sensors() : mEventQueueFlag(nullptr) { +constexpr const char* kWakeLockName = "SensorsHAL_WAKEUP"; + +Sensors::Sensors() + : mEventQueueFlag(nullptr), + mOutstandingWakeUpEvents(0), + mReadWakeLockQueueRun(false), + mAutoReleaseWakeLockTime(0), + mHasWakeLock(false) { std::shared_ptr accel = std::make_shared(1 /* sensorHandle */, this /* callback */); mSensors[accel->getSensorInfo().sensorHandle] = accel; @@ -39,6 +47,8 @@ Sensors::Sensors() : mEventQueueFlag(nullptr) { Sensors::~Sensors() { deleteEventFlag(); + mReadWakeLockQueueRun = false; + mWakeLockThread.join(); } // Methods from ::android::hardware::sensors::V2_0::ISensors follow. @@ -101,6 +111,10 @@ Return Sensors::initialize( result = Result::BAD_VALUE; } + // Start the thread to read events from the Wake Lock FMQ + mReadWakeLockQueueRun = true; + mWakeLockThread = std::thread(startReadWakeLockThread, this); + return result; } @@ -147,15 +161,67 @@ Return Sensors::configDirectReport(int32_t /* sensorHandle */, int32_t /* return Return(); } -void Sensors::postEvents(const std::vector& events) { - std::lock_guard l(mLock); +void Sensors::postEvents(const std::vector& events, bool wakeup) { + std::lock_guard lock(mWriteLock); + if (mEventQueue->write(events.data(), events.size())) { + mEventQueueFlag->wake(static_cast(EventQueueFlagBits::READ_AND_PROCESS)); - // TODO: read events from the Wake Lock FMQ in the right place - std::vector tmp(mWakeLockQueue->availableToRead()); - mWakeLockQueue->read(tmp.data(), mWakeLockQueue->availableToRead()); + if (wakeup) { + // Keep track of the number of outstanding WAKE_UP events in order to properly hold + // a wake lock until the framework has secured a wake lock + updateWakeLock(events.size(), 0 /* eventsHandled */); + } + } +} - mEventQueue->write(events.data(), events.size()); - mEventQueueFlag->wake(static_cast(EventQueueFlagBits::READ_AND_PROCESS)); +void Sensors::updateWakeLock(int32_t eventsWritten, int32_t eventsHandled) { + std::lock_guard lock(mWakeLockLock); + int32_t newVal = mOutstandingWakeUpEvents + eventsWritten - eventsHandled; + if (newVal < 0) { + mOutstandingWakeUpEvents = 0; + } else { + mOutstandingWakeUpEvents = newVal; + } + + if (eventsWritten > 0) { + // Update the time at which the last WAKE_UP event was sent + mAutoReleaseWakeLockTime = ::android::uptimeMillis() + + static_cast(SensorTimeout::WAKE_LOCK_SECONDS) * 1000; + } + + if (!mHasWakeLock && mOutstandingWakeUpEvents > 0 && + acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLockName) == 0) { + mHasWakeLock = true; + } else if (mHasWakeLock) { + // Check if the wake lock should be released automatically if + // SensorTimeout::WAKE_LOCK_SECONDS has elapsed since the last WAKE_UP event was written to + // the Wake Lock FMQ. + if (::android::uptimeMillis() > mAutoReleaseWakeLockTime) { + ALOGD("No events read from wake lock FMQ for %d seconds, auto releasing wake lock", + SensorTimeout::WAKE_LOCK_SECONDS); + mOutstandingWakeUpEvents = 0; + } + + if (mOutstandingWakeUpEvents == 0 && release_wake_lock(kWakeLockName) == 0) { + mHasWakeLock = false; + } + } +} + +void Sensors::readWakeLockFMQ() { + while (mReadWakeLockQueueRun.load()) { + constexpr int64_t kReadTimeoutNs = 500 * 1000 * 1000; // 500 ms + uint32_t eventsHandled = 0; + + // Read events from the Wake Lock FMQ. Timeout after a reasonable amount of time to ensure + // that any held wake lock is able to be released if it is held for too long. + mWakeLockQueue->readBlocking(&eventsHandled, 1 /* count */, kReadTimeoutNs); + updateWakeLock(0 /* eventsWritten */, eventsHandled); + } +} + +void Sensors::startReadWakeLockThread(Sensors* sensors) { + sensors->readWakeLockFMQ(); } void Sensors::deleteEventFlag() { diff --git a/sensors/2.0/default/Sensors.h b/sensors/2.0/default/Sensors.h index f543935c01..eba3f97a08 100644 --- a/sensors/2.0/default/Sensors.h +++ b/sensors/2.0/default/Sensors.h @@ -21,10 +21,13 @@ #include #include +#include #include #include +#include #include +#include namespace android { namespace hardware { @@ -80,7 +83,7 @@ struct Sensors : public ISensors, public ISensorsEventCallback { Return configDirectReport(int32_t sensorHandle, int32_t channelHandle, RateLevel rate, configDirectReport_cb _hidl_cb) override; - void postEvents(const std::vector& events) override; + void postEvents(const std::vector& events, bool wakeup) override; private: /** @@ -88,6 +91,18 @@ struct Sensors : public ISensors, public ISensorsEventCallback { */ void deleteEventFlag(); + /** + * Function to read the Wake Lock FMQ and release the wake lock when appropriate + */ + void readWakeLockFMQ(); + + static void startReadWakeLockThread(Sensors* sensors); + + /** + * Responsible for acquiring and releasing a wake lock when there are unhandled WAKE_UP events + */ + void updateWakeLock(int32_t eventsWritten, int32_t eventsHandled); + using EventMessageQueue = MessageQueue; using WakeLockMessageQueue = MessageQueue; @@ -117,9 +132,39 @@ struct Sensors : public ISensors, public ISensorsEventCallback { std::map> mSensors; /** - * Lock to protect writes and reads to the FMQs + * Lock to protect writes to the FMQs */ - std::mutex mLock; + std::mutex mWriteLock; + + /** + * Lock to protect acquiring and releasing the wake lock + */ + std::mutex mWakeLockLock; + + /** + * Track the number of WAKE_UP events that have not been handled by the framework + */ + uint32_t mOutstandingWakeUpEvents; + + /** + * A thread to read the Wake Lock FMQ + */ + std::thread mWakeLockThread; + + /** + * Flag to indicate that the Wake Lock Thread should continue to run + */ + std::atomic_bool mReadWakeLockQueueRun; + + /** + * Track the time when the wake lock should automatically be released + */ + int64_t mAutoReleaseWakeLockTime; + + /** + * Flag to indicate if a wake lock has been acquired + */ + bool mHasWakeLock; }; } // namespace implementation