Merge "SF: Fix thread safety for scheduler callbacks"
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index 91ae087..5d9cfde 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -100,8 +100,10 @@
} // namespace
EventThreadConnection::EventThreadConnection(EventThread* eventThread,
- ResyncCallback resyncCallback)
+ ResyncCallback resyncCallback,
+ ResetIdleTimerCallback resetIdleTimerCallback)
: resyncCallback(std::move(resyncCallback)),
+ resetIdleTimerCallback(std::move(resetIdleTimerCallback)),
mEventThread(eventThread),
mChannel(gui::BitTube::DefaultSize) {}
@@ -147,22 +149,18 @@
namespace impl {
EventThread::EventThread(std::unique_ptr<VSyncSource> src,
- const InterceptVSyncsCallback& interceptVSyncsCallback,
- const ResetIdleTimerCallback& resetIdleTimerCallback,
- const char* threadName)
- : EventThread(nullptr, std::move(src), interceptVSyncsCallback, threadName) {
- mResetIdleTimer = resetIdleTimerCallback;
-}
+ InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName)
+ : EventThread(nullptr, std::move(src), std::move(interceptVSyncsCallback), threadName) {}
EventThread::EventThread(VSyncSource* src, InterceptVSyncsCallback interceptVSyncsCallback,
const char* threadName)
- : EventThread(src, nullptr, interceptVSyncsCallback, threadName) {}
+ : EventThread(src, nullptr, std::move(interceptVSyncsCallback), threadName) {}
EventThread::EventThread(VSyncSource* src, std::unique_ptr<VSyncSource> uniqueSrc,
InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName)
: mVSyncSource(src),
mVSyncSourceUnique(std::move(uniqueSrc)),
- mInterceptVSyncsCallback(interceptVSyncsCallback),
+ mInterceptVSyncsCallback(std::move(interceptVSyncsCallback)),
mThreadName(threadName) {
if (src == nullptr) {
mVSyncSource = mVSyncSourceUnique.get();
@@ -205,8 +203,10 @@
mVSyncSource->setPhaseOffset(phaseOffset);
}
-sp<EventThreadConnection> EventThread::createEventConnection(ResyncCallback resyncCallback) const {
- return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback));
+sp<EventThreadConnection> EventThread::createEventConnection(
+ ResyncCallback resyncCallback, ResetIdleTimerCallback resetIdleTimerCallback) const {
+ return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback),
+ std::move(resetIdleTimerCallback));
}
status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) {
@@ -249,9 +249,9 @@
}
void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection, bool reset) {
- if (mResetIdleTimer && reset) {
+ if (connection->resetIdleTimerCallback && reset) {
ATRACE_NAME("resetIdleTimer");
- mResetIdleTimer();
+ connection->resetIdleTimerCallback();
}
if (connection->resyncCallback) {
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index 62b6a8b..b275183 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -45,6 +45,7 @@
// ---------------------------------------------------------------------------
using ResyncCallback = std::function<void()>;
+using ResetIdleTimerCallback = std::function<void()>;
enum class VSyncRequest {
None = -1,
@@ -69,7 +70,7 @@
class EventThreadConnection : public BnDisplayEventConnection {
public:
- EventThreadConnection(EventThread* eventThread, ResyncCallback resyncCallback);
+ EventThreadConnection(EventThread*, ResyncCallback, ResetIdleTimerCallback);
virtual ~EventThreadConnection();
virtual status_t postEvent(const DisplayEventReceiver::Event& event);
@@ -83,6 +84,7 @@
// Called in response to requestNextVsync.
const ResyncCallback resyncCallback;
+ const ResetIdleTimerCallback resetIdleTimerCallback;
VSyncRequest vsyncRequest = VSyncRequest::None;
@@ -96,8 +98,8 @@
public:
virtual ~EventThread();
- virtual sp<EventThreadConnection> createEventConnection(
- ResyncCallback resyncCallback) const = 0;
+ virtual sp<EventThreadConnection> createEventConnection(ResyncCallback,
+ ResetIdleTimerCallback) const = 0;
// called before the screen is turned off from main thread
virtual void onScreenReleased() = 0;
@@ -124,17 +126,14 @@
class EventThread : public android::EventThread, private VSyncSource::Callback {
public:
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, InterceptVSyncsCallback interceptVSyncsCallback,
- const char* threadName);
- EventThread(std::unique_ptr<VSyncSource> src,
- const InterceptVSyncsCallback& interceptVSyncsCallback,
- const ResetIdleTimerCallback& resetIdleTimerCallback, const char* threadName);
+ EventThread(VSyncSource*, InterceptVSyncsCallback, const char* threadName);
+ EventThread(std::unique_ptr<VSyncSource>, InterceptVSyncsCallback, const char* threadName);
~EventThread();
- sp<EventThreadConnection> createEventConnection(ResyncCallback resyncCallback) const override;
+ sp<EventThreadConnection> createEventConnection(ResyncCallback,
+ ResetIdleTimerCallback) const override;
status_t registerDisplayEventConnection(const sp<EventThreadConnection>& connection) override;
void setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& connection) override;
@@ -220,9 +219,6 @@
State mState GUARDED_BY(mMutex) = State::Idle;
static const char* toCString(State);
-
- // Callback that resets the idle timer when the next vsync is received.
- ResetIdleTimerCallback mResetIdleTimer;
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp
index 75a410b..1f18ead 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.cpp
+++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp
@@ -96,7 +96,8 @@
}
mEventThread = eventThread;
- mEvents = eventThread->createEventConnection(std::move(resyncCallback));
+ mEvents =
+ eventThread->createEventConnection(std::move(resyncCallback), ResetIdleTimerCallback());
mEvents->stealReceiveChannel(&mEventTube);
mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver,
this);
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 3060f1d..2f581d2 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -87,6 +87,7 @@
sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
const char* connectionName, int64_t phaseOffsetNs, ResyncCallback resyncCallback,
+ ResetIdleTimerCallback resetIdleTimerCallback,
impl::EventThread::InterceptVSyncsCallback interceptCallback) {
const int64_t id = sNextId++;
ALOGV("Creating a connection handle with ID: %" PRId64 "\n", id);
@@ -94,12 +95,14 @@
std::unique_ptr<EventThread> eventThread =
makeEventThread(connectionName, mPrimaryDispSync.get(), phaseOffsetNs,
std::move(interceptCallback));
- auto connection = std::make_unique<Connection>(new ConnectionHandle(id),
- eventThread->createEventConnection(
- std::move(resyncCallback)),
- std::move(eventThread));
- mConnections.insert(std::make_pair(id, std::move(connection)));
+ auto eventThreadConnection =
+ createConnectionInternal(eventThread.get(), std::move(resyncCallback),
+ std::move(resetIdleTimerCallback));
+ mConnections.emplace(id,
+ std::make_unique<Connection>(new ConnectionHandle(id),
+ eventThreadConnection,
+ std::move(eventThread)));
return mConnections[id]->handle;
}
@@ -109,14 +112,29 @@
std::unique_ptr<VSyncSource> eventThreadSource =
std::make_unique<DispSyncSource>(dispSync, phaseOffsetNs, true, connectionName);
return std::make_unique<impl::EventThread>(std::move(eventThreadSource),
- std::move(interceptCallback),
- [this] { resetIdleTimer(); }, connectionName);
+ std::move(interceptCallback), connectionName);
+}
+
+sp<EventThreadConnection> Scheduler::createConnectionInternal(
+ EventThread* eventThread, ResyncCallback&& resyncCallback,
+ ResetIdleTimerCallback&& resetIdleTimerCallback) {
+ return eventThread->createEventConnection(std::move(resyncCallback),
+ [this,
+ resetIdleTimerCallback =
+ std::move(resetIdleTimerCallback)] {
+ resetIdleTimer();
+ if (resetIdleTimerCallback) {
+ resetIdleTimerCallback();
+ }
+ });
}
sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
- const sp<Scheduler::ConnectionHandle>& handle, ResyncCallback resyncCallback) {
+ const sp<Scheduler::ConnectionHandle>& handle, ResyncCallback resyncCallback,
+ ResetIdleTimerCallback resetIdleTimerCallback) {
RETURN_VALUE_IF_INVALID(nullptr);
- return mConnections[handle->id]->thread->createEventConnection(std::move(resyncCallback));
+ return createConnectionInternal(mConnections[handle->id]->thread.get(),
+ std::move(resyncCallback), std::move(resetIdleTimerCallback));
}
EventThread* Scheduler::getEventThread(const sp<Scheduler::ConnectionHandle>& handle) {
@@ -241,11 +259,6 @@
mExpiredTimerCallback = expiredTimerCallback;
}
-void Scheduler::setResetIdleTimerCallback(const ResetIdleTimerCallback& resetTimerCallback) {
- std::lock_guard<std::mutex> lock(mCallbackLock);
- mResetTimerCallback = resetTimerCallback;
-}
-
void Scheduler::updateFrameSkipping(const int64_t skipCount) {
ATRACE_INT("FrameSkipCount", skipCount);
if (mSkipCount != skipCount) {
@@ -336,11 +349,6 @@
mIdleTimer->reset();
ATRACE_INT("ExpiredIdleTimer", 0);
}
-
- std::lock_guard<std::mutex> lock(mCallbackLock);
- if (mResetTimerCallback) {
- mResetTimerCallback();
- }
}
void Scheduler::expiredTimerCallback() {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index e77dc06..4abf027 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -37,7 +37,6 @@
class Scheduler {
public:
using ExpiredIdleTimerCallback = std::function<void()>;
- using ResetIdleTimerCallback = std::function<void()>;
// Enum to indicate whether to start the transaction early, or at vsync time.
enum class TransactionStart { EARLY, NORMAL };
@@ -72,12 +71,13 @@
virtual ~Scheduler();
/** Creates an EventThread connection. */
- sp<ConnectionHandle> createConnection(
- const char* connectionName, int64_t phaseOffsetNs, ResyncCallback resyncCallback,
- impl::EventThread::InterceptVSyncsCallback interceptCallback);
+ sp<ConnectionHandle> createConnection(const char* connectionName, int64_t phaseOffsetNs,
+ ResyncCallback, ResetIdleTimerCallback,
+ impl::EventThread::InterceptVSyncsCallback);
sp<IDisplayEventConnection> createDisplayEventConnection(const sp<ConnectionHandle>& handle,
- ResyncCallback resyncCallback);
+ ResyncCallback,
+ ResetIdleTimerCallback);
// Getter methods.
EventThread* getEventThread(const sp<ConnectionHandle>& handle);
@@ -116,8 +116,6 @@
void incrementFrameCounter();
// Callback that gets invoked once the idle timer expires.
void setExpiredIdleTimerCallback(const ExpiredIdleTimerCallback& expiredTimerCallback);
- // Callback that gets invoked once the idle timer is reset.
- void setResetIdleTimerCallback(const ResetIdleTimerCallback& resetTimerCallback);
// Returns relevant information about Scheduler for dumpsys purposes.
std::string doDump();
@@ -127,6 +125,10 @@
impl::EventThread::InterceptVSyncsCallback interceptCallback);
private:
+ // Creates a connection on the given EventThread and forwards the given callbacks.
+ sp<EventThreadConnection> createConnectionInternal(EventThread*, ResyncCallback&&,
+ ResetIdleTimerCallback&&);
+
nsecs_t calculateAverage() const;
void updateFrameSkipping(const int64_t skipCount);
// Collects the statistical mean (average) and median between timestamp
@@ -184,7 +186,6 @@
std::mutex mCallbackLock;
ExpiredIdleTimerCallback mExpiredTimerCallback GUARDED_BY(mCallbackLock);
- ResetIdleTimerCallback mResetTimerCallback GUARDED_BY(mCallbackLock);
};
} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 51eb6ba..5f8de83 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -120,6 +120,7 @@
using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
using namespace android::sysprop;
+
using base::StringAppendF;
using ui::ColorMode;
using ui::Dataspace;
@@ -127,6 +128,8 @@
using ui::Hdr;
using ui::RenderIntent;
+using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType;
+
namespace {
#pragma clang diagnostic push
@@ -211,6 +214,9 @@
constexpr float kSrgbWhiteY = 1.0000f;
constexpr float kSrgbWhiteZ = 1.0891f;
+constexpr float kDefaultRefreshRate = 60.f;
+constexpr float kPerformanceRefreshRate = 90.f;
+
// ---------------------------------------------------------------------------
int64_t SurfaceFlinger::dispSyncPresentTimeOffset;
bool SurfaceFlinger::useHwcForRgbToYuv;
@@ -627,13 +633,17 @@
mPhaseOffsets->setRefreshRateType(
scheduler::RefreshRateConfigs::RefreshRateType::PERFORMANCE);
+ auto resetIdleTimerCallback =
+ std::bind(&SurfaceFlinger::setRefreshRateTo, this, RefreshRateType::PERFORMANCE);
+
mAppConnectionHandle =
mScheduler->createConnection("appConnection", mPhaseOffsets->getCurrentAppOffset(),
- resyncCallback,
+ resyncCallback, resetIdleTimerCallback,
impl::EventThread::InterceptVSyncsCallback());
mSfConnectionHandle =
mScheduler->createConnection("sfConnection", mPhaseOffsets->getCurrentSfOffset(),
- resyncCallback, [this](nsecs_t timestamp) {
+ resyncCallback, resetIdleTimerCallback,
+ [this](nsecs_t timestamp) {
mInterceptor->saveVSyncEvent(timestamp);
});
@@ -731,20 +741,11 @@
}
if (mUseScheduler) {
- mScheduler->setExpiredIdleTimerCallback([this]() {
- mPhaseOffsets->setRefreshRateType(
- scheduler::RefreshRateConfigs::RefreshRateType::DEFAULT);
- const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
- mVsyncModulator.setPhaseOffsets(early, gl, late);
- setRefreshRateTo(60.f /* fps */);
+ mScheduler->setExpiredIdleTimerCallback([this] {
+ Mutex::Autolock lock(mStateLock);
+ setRefreshRateTo(RefreshRateType::DEFAULT);
});
- mScheduler->setResetIdleTimerCallback([this]() {
- mPhaseOffsets->setRefreshRateType(
- scheduler::RefreshRateConfigs::RefreshRateType::PERFORMANCE);
- const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
- mVsyncModulator.setPhaseOffsets(early, gl, late);
- setRefreshRateTo(90.f /* fps */);
- });
+
mRefreshRateStats =
std::make_unique<scheduler::RefreshRateStats>(getHwComposer().getConfigs(
*display->getId()),
@@ -956,13 +957,6 @@
return display->getActiveConfig();
}
-status_t SurfaceFlinger::setActiveConfigAsync(const sp<IBinder>& displayToken, int mode) {
- ATRACE_NAME("setActiveConfigAsync");
- postMessageAsync(new LambdaMessage(
- [=]() NO_THREAD_SAFETY_ANALYSIS { setActiveConfigInternal(displayToken, mode); }));
- return NO_ERROR;
-}
-
status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mode) {
ATRACE_NAME("setActiveConfigSync");
postMessageSync(new LambdaMessage(
@@ -1269,16 +1263,21 @@
});
if (mUseScheduler) {
- if (vsyncSource == eVsyncSourceSurfaceFlinger) {
- return mScheduler->createDisplayEventConnection(mSfConnectionHandle, resyncCallback);
- } else {
- return mScheduler->createDisplayEventConnection(mAppConnectionHandle, resyncCallback);
- }
+ auto resetIdleTimerCallback = [this] {
+ Mutex::Autolock lock(mStateLock);
+ setRefreshRateTo(RefreshRateType::PERFORMANCE);
+ };
+
+ const auto& handle = vsyncSource == eVsyncSourceSurfaceFlinger ? mSfConnectionHandle
+ : mAppConnectionHandle;
+
+ return mScheduler->createDisplayEventConnection(handle, std::move(resyncCallback),
+ std::move(resetIdleTimerCallback));
} else {
if (vsyncSource == eVsyncSourceSurfaceFlinger) {
- return mSFEventThread->createEventConnection(resyncCallback);
+ return mSFEventThread->createEventConnection(resyncCallback, ResetIdleTimerCallback());
} else {
- return mEventThread->createEventConnection(resyncCallback);
+ return mEventThread->createEventConnection(resyncCallback, ResetIdleTimerCallback());
}
}
}
@@ -1440,12 +1439,16 @@
*compositorTiming = getBE().mCompositorTiming;
}
-// TODO(b/123715322): Fix thread safety.
-void SurfaceFlinger::setRefreshRateTo(float newFps) NO_THREAD_SAFETY_ANALYSIS {
- const auto display = getDefaultDisplayDeviceLocked();
- if (!display || mBootStage != BootStage::FINISHED) {
+void SurfaceFlinger::setRefreshRateTo(RefreshRateType refreshRate) {
+ mPhaseOffsets->setRefreshRateType(refreshRate);
+
+ const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
+ mVsyncModulator.setPhaseOffsets(early, gl, late);
+
+ if (mBootStage != BootStage::FINISHED) {
return;
}
+
// TODO(b/113612090): There should be a message queue flush here. Because this esentially
// runs on a mainthread, we cannot call postMessageSync. This can be resolved in a better
// manner, once the setActiveConfig is synchronous, and is executed at a known time in a
@@ -1456,14 +1459,20 @@
if (currentVsyncPeriod == 0) {
return;
}
+
// TODO(b/113612090): Consider having an enum value for correct refresh rates, rather than
// floating numbers.
const float currentFps = 1e9 / currentVsyncPeriod;
+ const float newFps = refreshRate == RefreshRateType::PERFORMANCE ? kPerformanceRefreshRate
+ : kDefaultRefreshRate;
if (std::abs(currentFps - newFps) <= 1) {
return;
}
- auto configs = getHwComposer().getConfigs(*display->getId());
+ const auto displayId = getInternalDisplayIdLocked();
+ LOG_ALWAYS_FATAL_IF(!displayId);
+
+ auto configs = getHwComposer().getConfigs(*displayId);
for (int i = 0; i < configs.size(); i++) {
const nsecs_t vsyncPeriod = configs.at(i)->getVsyncPeriod();
if (vsyncPeriod == 0) {
@@ -1473,12 +1482,7 @@
// TODO(b/113612090): There should be a better way at determining which config
// has the right refresh rate.
if (std::abs(fps - newFps) <= 1) {
- const sp<IBinder> token = display->getDisplayToken().promote();
- LOG_ALWAYS_FATAL_IF(token == nullptr);
-
- // This is posted in async function to avoid deadlock when getDisplayDevice
- // requires mStateLock.
- setActiveConfigAsync(token, i);
+ setActiveConfigInternal(getInternalDisplayTokenLocked(), i);
ATRACE_INT("FPS", newFps);
}
}
@@ -5386,8 +5390,8 @@
DisplayRenderArea renderArea(display, sourceCrop, reqWidth, reqHeight, reqDataspace,
renderAreaRotation);
- auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this,
- display, std::placeholders::_1);
+ auto traverseLayers = std::bind(&SurfaceFlinger::traverseLayersInDisplay, this, display,
+ std::placeholders::_1);
return captureScreenCommon(renderArea, traverseLayers, outBuffer, reqPixelFormat,
useIdentityTransform);
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index c404ef2..6546973 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -60,6 +60,7 @@
#include "Scheduler/EventThread.h"
#include "Scheduler/MessageQueue.h"
#include "Scheduler/PhaseOffsets.h"
+#include "Scheduler/RefreshRateConfigs.h"
#include "Scheduler/RefreshRateStats.h"
#include "Scheduler/Scheduler.h"
#include "Scheduler/VSyncModulator.h"
@@ -502,8 +503,6 @@
// called on the main thread in response to initializeDisplays()
void onInitializeDisplays() REQUIRES(mStateLock);
- // setActiveConfigInternal() posted on a main thread for async execution
- status_t setActiveConfigAsync(const sp<IBinder>& displayToken, int mode);
// called on the main thread in response to setActiveConfig()
void setActiveConfigInternal(const sp<IBinder>& displayToken, int mode) REQUIRES(mStateLock);
// called on the main thread in response to setPowerMode()
@@ -770,9 +769,9 @@
void resyncToHardwareVsync(bool makeAvailable, nsecs_t period);
void disableHardwareVsync(bool makeUnavailable);
- // Sets the refresh rate to newFps by switching active configs, if they are available for
+ // Sets the refresh rate by switching active configs, if they are available for
// the desired refresh rate.
- void setRefreshRateTo(float newFps);
+ void setRefreshRateTo(scheduler::RefreshRateConfigs::RefreshRateType) REQUIRES(mStateLock);
using GetVsyncPeriod = std::function<nsecs_t()>;
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index fa5bb26..3a7cfba 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -53,8 +53,10 @@
class MockEventThreadConnection : public EventThreadConnection {
public:
MockEventThreadConnection(android::impl::EventThread* eventThread,
- ResyncCallback&& resyncCallback)
- : EventThreadConnection(eventThread, std::move(resyncCallback)) {}
+ ResyncCallback&& resyncCallback,
+ ResetIdleTimerCallback&& resetIdleTimerCallback)
+ : EventThreadConnection(eventThread, std::move(resyncCallback),
+ std::move(resetIdleTimerCallback)) {}
MOCK_METHOD1(postEvent, status_t(const DisplayEventReceiver::Event& event));
};
@@ -82,6 +84,7 @@
AsyncCallRecorder<void (*)(VSyncSource::Callback*)> mVSyncSetCallbackCallRecorder;
AsyncCallRecorder<void (*)(nsecs_t)> mVSyncSetPhaseOffsetCallRecorder;
AsyncCallRecorder<void (*)()> mResyncCallRecorder;
+ AsyncCallRecorder<void (*)()> mResetIdleTimerCallRecorder;
AsyncCallRecorder<void (*)(nsecs_t)> mInterceptVSyncCallRecorder;
ConnectionEventRecorder mConnectionEventCallRecorder{0};
@@ -136,7 +139,8 @@
sp<EventThreadTest::MockEventThreadConnection> EventThreadTest::createConnection(
ConnectionEventRecorder& recorder) {
sp<MockEventThreadConnection> connection =
- new MockEventThreadConnection(mThread.get(), mResyncCallRecorder.getInvocable());
+ new MockEventThreadConnection(mThread.get(), mResyncCallRecorder.getInvocable(),
+ mResetIdleTimerCallRecorder.getInvocable());
EXPECT_CALL(*connection, postEvent(_)).WillRepeatedly(Invoke(recorder.getInvocable()));
return connection;
}
@@ -207,6 +211,7 @@
EXPECT_FALSE(mVSyncSetCallbackCallRecorder.waitForCall(0us).has_value());
EXPECT_FALSE(mVSyncSetPhaseOffsetCallRecorder.waitForCall(0us).has_value());
EXPECT_FALSE(mResyncCallRecorder.waitForCall(0us).has_value());
+ EXPECT_FALSE(mResetIdleTimerCallRecorder.waitForCall(0us).has_value());
EXPECT_FALSE(mInterceptVSyncCallRecorder.waitForCall(0us).has_value());
EXPECT_FALSE(mConnectionEventCallRecorder.waitForCall(0us).has_value());
}
@@ -224,9 +229,10 @@
TEST_F(EventThreadTest, requestNextVsyncPostsASingleVSyncEventToTheConnection) {
// Signal that we want the next vsync event to be posted to the connection
- mThread->requestNextVsync(mConnection, false);
+ mThread->requestNextVsync(mConnection, true);
- // EventThread should immediately request a resync.
+ // EventThread should immediately reset the idle timer and request a resync.
+ EXPECT_TRUE(mResetIdleTimerCallRecorder.waitForCall().has_value());
EXPECT_TRUE(mResyncCallRecorder.waitForCall().has_value());
// EventThread should enable vsync callbacks.
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 0db96d9..26b6d0c 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -25,7 +25,7 @@
class MockEventThreadConnection : public android::EventThreadConnection {
public:
explicit MockEventThreadConnection(EventThread* eventThread)
- : EventThreadConnection(eventThread, ResyncCallback()) {}
+ : EventThreadConnection(eventThread, ResyncCallback(), ResetIdleTimerCallback()) {}
~MockEventThreadConnection() = default;
MOCK_METHOD1(stealReceiveChannel, status_t(gui::BitTube* outChannel));
@@ -78,10 +78,11 @@
// createConnection call to scheduler makes a createEventConnection call to EventThread. Make
// sure that call gets executed and returns an EventThread::Connection object.
- EXPECT_CALL(*mEventThread, createEventConnection(_))
+ EXPECT_CALL(*mEventThread, createEventConnection(_, _))
.WillRepeatedly(Return(mEventThreadConnection));
mConnectionHandle = mScheduler->createConnection("appConnection", 16, ResyncCallback(),
+ ResetIdleTimerCallback(),
impl::EventThread::InterceptVSyncsCallback());
EXPECT_TRUE(mConnectionHandle != nullptr);
}
@@ -102,7 +103,8 @@
// exceptions, just gracefully continues.
sp<IDisplayEventConnection> returnedValue;
ASSERT_NO_FATAL_FAILURE(
- returnedValue = mScheduler->createDisplayEventConnection(nullptr, ResyncCallback()));
+ returnedValue = mScheduler->createDisplayEventConnection(nullptr, ResyncCallback(),
+ ResetIdleTimerCallback()));
EXPECT_TRUE(returnedValue == nullptr);
EXPECT_TRUE(mScheduler->getEventThread(nullptr) == nullptr);
EXPECT_TRUE(mScheduler->getEventConnection(nullptr) == nullptr);
@@ -123,7 +125,8 @@
sp<IDisplayEventConnection> returnedValue;
ASSERT_NO_FATAL_FAILURE(
returnedValue =
- mScheduler->createDisplayEventConnection(connectionHandle, ResyncCallback()));
+ mScheduler->createDisplayEventConnection(connectionHandle, ResyncCallback(),
+ ResetIdleTimerCallback()));
EXPECT_TRUE(returnedValue == nullptr);
EXPECT_TRUE(mScheduler->getEventThread(connectionHandle) == nullptr);
EXPECT_TRUE(mScheduler->getEventConnection(connectionHandle) == nullptr);
@@ -152,7 +155,8 @@
sp<IDisplayEventConnection> returnedValue;
ASSERT_NO_FATAL_FAILURE(
returnedValue =
- mScheduler->createDisplayEventConnection(mConnectionHandle, ResyncCallback()));
+ mScheduler->createDisplayEventConnection(mConnectionHandle, ResyncCallback(),
+ ResetIdleTimerCallback()));
EXPECT_TRUE(returnedValue != nullptr);
ASSERT_EQ(returnedValue, mEventThreadConnection);
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
index aaf67e9..589237d 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
@@ -28,7 +28,8 @@
EventThread();
~EventThread() override;
- MOCK_CONST_METHOD1(createEventConnection, sp<EventThreadConnection>(ResyncCallback));
+ MOCK_CONST_METHOD2(createEventConnection,
+ sp<EventThreadConnection>(ResyncCallback, ResetIdleTimerCallback));
MOCK_METHOD0(onScreenReleased, void());
MOCK_METHOD0(onScreenAcquired, void());
MOCK_METHOD2(onHotplugReceived, void(PhysicalDisplayId, bool));