Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2aca3b4 authored by Brian Stack's avatar Brian Stack
Browse files

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
parent 26427a6b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ cc_binary {
        "libhidlbase",
        "libhidltransport",
        "liblog",
        "libpower",
        "libutils",
    ],
}
+7 −3
Original line number Diff line number Diff line
@@ -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;
    }
+3 −1
Original line number Diff line number Diff line
@@ -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;
+74 −8
Original line number Diff line number Diff line
@@ -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() {
+48 −3
Original line number Diff line number Diff line
@@ -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 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
     */
    std::mutex mLock;
    bool mHasWakeLock;
};

}  // namespace implementation