Acquire and Release Wake Lock
Acquire a wake lock in the Sensors 2.0 Default implementation whenever there are outstanding WAKE_UP events. Release the wake lock whenever the number of oustanding WAKE_UP events is zero or at least SensorTimeout::WAKE_LOCK_SECONDS seconds have elapsed since the previous WAKE_UP event was written to the Event FMQ. Bug: 111070257 Test: Builds, wake lock is acquired and released as expected. Change-Id: I7c57724430144fd4022646d1fef1b1fa8bc4235d
This commit is contained in:
parent
26427a6bca
commit
f2aca3b487
5 changed files with 133 additions and 15 deletions
|
@ -32,6 +32,7 @@ cc_binary {
|
|||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"liblog",
|
||||
"libpower",
|
||||
"libutils",
|
||||
],
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ Result Sensor::flush() {
|
|||
ev.sensorType = SensorType::ADDITIONAL_INFO;
|
||||
ev.u.meta.what = MetaDataEventType::META_DATA_FLUSH_COMPLETE;
|
||||
std::vector<Event> 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<uint32_t>(SensorFlagBits::WAKE_UP);
|
||||
}
|
||||
|
||||
std::vector<Event> Sensor::readEvents() {
|
||||
std::vector<Event> 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>{event});
|
||||
mCallback->postEvents(std::vector<Event>{event}, isWakeUpSensor());
|
||||
} else {
|
||||
result = Result::BAD_VALUE;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace implementation {
|
|||
class ISensorsEventCallback {
|
||||
public:
|
||||
virtual ~ISensorsEventCallback(){};
|
||||
virtual void postEvents(const std::vector<Event>& events) = 0;
|
||||
virtual void postEvents(const std::vector<Event>& events, bool wakeup) = 0;
|
||||
};
|
||||
|
||||
class Sensor {
|
||||
|
@ -62,6 +62,8 @@ class Sensor {
|
|||
virtual std::vector<Event> readEvents();
|
||||
static void startThread(Sensor* sensor);
|
||||
|
||||
bool isWakeUpSensor();
|
||||
|
||||
bool mIsEnabled;
|
||||
int64_t mSamplingPeriodNs;
|
||||
int64_t mLastSampleTimeNs;
|
||||
|
|
|
@ -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<AccelSensor> accel =
|
||||
std::make_shared<AccelSensor>(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<Result> 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<void> Sensors::configDirectReport(int32_t /* sensorHandle */, int32_t /*
|
|||
return Return<void>();
|
||||
}
|
||||
|
||||
void Sensors::postEvents(const std::vector<Event>& events) {
|
||||
std::lock_guard<std::mutex> l(mLock);
|
||||
void Sensors::postEvents(const std::vector<Event>& events, bool wakeup) {
|
||||
std::lock_guard<std::mutex> lock(mWriteLock);
|
||||
if (mEventQueue->write(events.data(), events.size())) {
|
||||
mEventQueueFlag->wake(static_cast<uint32_t>(EventQueueFlagBits::READ_AND_PROCESS));
|
||||
|
||||
// TODO: read events from the Wake Lock FMQ in the right place
|
||||
std::vector<uint32_t> 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<uint32_t>(EventQueueFlagBits::READ_AND_PROCESS));
|
||||
void Sensors::updateWakeLock(int32_t eventsWritten, int32_t eventsHandled) {
|
||||
std::lock_guard<std::mutex> 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<uint32_t>(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() {
|
||||
|
|
|
@ -21,10 +21,13 @@
|
|||
|
||||
#include <android/hardware/sensors/2.0/ISensors.h>
|
||||
#include <fmq/MessageQueue.h>
|
||||
#include <hardware_legacy/power.h>
|
||||
#include <hidl/MQDescriptor.h>
|
||||
#include <hidl/Status.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
|
@ -80,7 +83,7 @@ struct Sensors : public ISensors, public ISensorsEventCallback {
|
|||
Return<void> configDirectReport(int32_t sensorHandle, int32_t channelHandle, RateLevel rate,
|
||||
configDirectReport_cb _hidl_cb) override;
|
||||
|
||||
void postEvents(const std::vector<Event>& events) override;
|
||||
void postEvents(const std::vector<Event>& 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<Event, kSynchronizedReadWrite>;
|
||||
using WakeLockMessageQueue = MessageQueue<uint32_t, kSynchronizedReadWrite>;
|
||||
|
||||
|
@ -117,9 +132,39 @@ struct Sensors : public ISensors, public ISensorsEventCallback {
|
|||
std::map<int32_t, std::shared_ptr<Sensor>> 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
|
||||
|
|
Loading…
Reference in a new issue