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

Commit 76dfac18 authored by Ana Krulec's avatar Ana Krulec Committed by Android (Google) Code Review
Browse files

Merge "SF: Adding Idle Timer, to detect when devices are idle."

parents aa9eb2da fb77282e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -139,6 +139,7 @@ filegroup {
        "Scheduler/DispSyncSource.cpp",
        "Scheduler/EventControlThread.cpp",
        "Scheduler/EventThread.cpp",
        "Scheduler/IdleTimer.cpp",
        "Scheduler/LayerHistory.cpp",
        "Scheduler/MessageQueue.cpp",
        "Scheduler/Scheduler.cpp",
+10 −3
Original line number Diff line number Diff line
@@ -48,10 +48,14 @@ EventThread::~EventThread() = default;
namespace impl {

EventThread::EventThread(std::unique_ptr<VSyncSource> src,
                         ResyncWithRateLimitCallback resyncWithRateLimitCallback,
                         InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName)
                         const ResyncWithRateLimitCallback& resyncWithRateLimitCallback,
                         const InterceptVSyncsCallback& interceptVSyncsCallback,
                         const ResetIdleTimerCallback& resetIdleTimerCallback,
                         const char* threadName)
      : EventThread(nullptr, std::move(src), resyncWithRateLimitCallback, interceptVSyncsCallback,
                    threadName) {}
                    threadName) {
    mResetIdleTimer = resetIdleTimerCallback;
}

EventThread::EventThread(VSyncSource* src, ResyncWithRateLimitCallback resyncWithRateLimitCallback,
                         InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName)
@@ -150,6 +154,9 @@ void EventThread::setVsyncRate(uint32_t count, const sp<EventThread::Connection>

void EventThread::requestNextVsync(const sp<EventThread::Connection>& connection) {
    std::lock_guard<std::mutex> lock(mMutex);
    if (mResetIdleTimer) {
        mResetIdleTimer();
    }

    if (mResyncWithRateLimitCallback) {
        mResyncWithRateLimitCallback();
+7 −2
Original line number Diff line number Diff line
@@ -107,13 +107,15 @@ class EventThread : public android::EventThread, private VSyncSource::Callback {
public:
    using ResyncWithRateLimitCallback = std::function<void()>;
    using InterceptVSyncsCallback = std::function<void(nsecs_t)>;
    using ResetIdleTimerCallback = std::function<void()>;

    // TODO(b/113612090): Once the Scheduler is complete this constructor will become obsolete.
    EventThread(VSyncSource* src, ResyncWithRateLimitCallback resyncWithRateLimitCallback,
                InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName);
    EventThread(std::unique_ptr<VSyncSource> src,
                ResyncWithRateLimitCallback resyncWithRateLimitCallback,
                InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName);
                const ResyncWithRateLimitCallback& resyncWithRateLimitCallback,
                const InterceptVSyncsCallback& interceptVSyncsCallback,
                const ResetIdleTimerCallback& resetIdleTimerCallback, const char* threadName);
    ~EventThread();

    sp<BnDisplayEventConnection> createEventConnection() const override;
@@ -177,6 +179,9 @@ private:

    // for debugging
    bool mDebugVsyncEnabled GUARDED_BY(mMutex) = false;

    // Callback that resets the idle timer when the next vsync is received.
    ResetIdleTimerCallback mResetIdleTimer;
};

// ---------------------------------------------------------------------------
+79 −0
Original line number Diff line number Diff line
/*
 * Copyright 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "IdleTimer.h"

#include <chrono>
#include <thread>

namespace android {
namespace scheduler {

IdleTimer::IdleTimer(const Interval& interval, const TimeoutCallback& timeoutCallback)
      : mInterval(interval), mTimeoutCallback(timeoutCallback) {}

IdleTimer::~IdleTimer() {
    stop();
}

void IdleTimer::start() {
    {
        std::lock_guard<std::mutex> lock(mMutex);
        mState = TimerState::RESET;
    }
    mThread = std::thread(&IdleTimer::loop, this);
}

void IdleTimer::stop() {
    {
        std::lock_guard<std::mutex> lock(mMutex);
        mState = TimerState::STOPPED;
    }
    mCondition.notify_all();
    if (mThread.joinable()) {
        mThread.join();
    }
}

void IdleTimer::loop() {
    std::lock_guard<std::mutex> lock(mMutex);
    while (mState != TimerState::STOPPED) {
        if (mState == TimerState::IDLE) {
            mCondition.wait(mMutex);
        } else if (mState == TimerState::RESET) {
            mState = TimerState::WAITING;
            if (mCondition.wait_for(mMutex, mInterval) == std::cv_status::timeout) {
                if (mTimeoutCallback) {
                    mTimeoutCallback();
                }
            }
            if (mState == TimerState::WAITING) {
                mState = TimerState::IDLE;
            }
        }
    }
}

void IdleTimer::reset() {
    {
        std::lock_guard<std::mutex> lock(mMutex);
        mState = TimerState::RESET;
    }
    mCondition.notify_all();
}

} // namespace scheduler
} // namespace android
+70 −0
Original line number Diff line number Diff line
/*
 * Copyright 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <chrono>
#include <condition_variable>
#include <thread>

#include <android-base/thread_annotations.h>

namespace android {
namespace scheduler {

/*
 * Class that sets off a timer for a given interval, and fires a callback when the
 * interval expires.
 */
class IdleTimer {
public:
    using Interval = std::chrono::milliseconds;
    using TimeoutCallback = std::function<void()>;

    IdleTimer(const Interval& interval, const TimeoutCallback& timeoutCallback);
    ~IdleTimer();

    void start();
    void stop();
    void reset();

private:
    // Enum to track in what state is the timer.
    enum class TimerState { STOPPED = 0, RESET = 1, WAITING = 2, IDLE = 3 };

    // Function that loops until the condition for stopping is met.
    void loop();

    // Thread waiting for timer to expire.
    std::thread mThread;

    // Condition used to notify mThread.
    std::condition_variable_any mCondition;

    // Lock used for synchronizing the waiting thread with the application thread.
    std::mutex mMutex;

    TimerState mState GUARDED_BY(mMutex) = TimerState::RESET;

    // Interval after which timer expires.
    const Interval mInterval;

    // Callback that happens when timer expires.
    const TimeoutCallback mTimeoutCallback;
};

} // namespace scheduler
} // namespace android
Loading