SurfaceFlinger: Add DISPLAY_EVENT_FRAME_RATE_OVERRIDE
Add a new event to DisplayEventReceiver that conveys a list
of apps whose frame rates have been overriden.
This event is processed by the DisplayManager to advertise the
new frame rate to the overridden app.
Change-Id: I89fce8b5b4d9db65ec5db7dd2393c384c0fcfd82
Bug: 169271059
Bug: 169271062
Bug: 170503758
Test: manual test using SF backdoor
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 560459b..a8c0500 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -14,6 +14,7 @@
libs/graphicsenv/
libs/gui/
libs/input/
+ libs/nativedisplay/
libs/renderengine/
libs/ui/
libs/vr/
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index a0e9cbf..af9ef06 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -237,6 +237,10 @@
"libnativebase_headers",
],
+ include_dirs: [
+ "frameworks/native/include",
+ ],
+
export_shared_lib_headers: [
"libEGL",
"libnativewindow",
diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp
index abfee61..c6c9a8f 100644
--- a/libs/gui/DisplayEventDispatcher.cpp
+++ b/libs/gui/DisplayEventDispatcher.cpp
@@ -33,10 +33,10 @@
// using just a few large reads.
static const size_t EVENT_BUFFER_SIZE = 100;
-DisplayEventDispatcher::DisplayEventDispatcher(const sp<Looper>& looper,
- ISurfaceComposer::VsyncSource vsyncSource,
- ISurfaceComposer::ConfigChanged configChanged)
- : mLooper(looper), mReceiver(vsyncSource, configChanged), mWaitingForVsync(false) {
+DisplayEventDispatcher::DisplayEventDispatcher(
+ const sp<Looper>& looper, ISurfaceComposer::VsyncSource vsyncSource,
+ ISurfaceComposer::EventRegistrationFlags eventRegistration)
+ : mLooper(looper), mReceiver(vsyncSource, eventRegistration), mWaitingForVsync(false) {
ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this);
}
@@ -139,6 +139,7 @@
ssize_t n;
while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
ALOGV("dispatcher %p ~ Read %d events.", this, int(n));
+ mFrameRateOverrides.reserve(n);
for (ssize_t i = 0; i < n; i++) {
const DisplayEventReceiver::Event& ev = buf[i];
switch (ev.header.type) {
@@ -162,6 +163,13 @@
case DisplayEventReceiver::DISPLAY_EVENT_NULL:
dispatchNullEvent(ev.header.timestamp, ev.header.displayId);
break;
+ case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE:
+ mFrameRateOverrides.emplace_back(ev.frameRateOverride);
+ break;
+ case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH:
+ dispatchFrameRateOverrides(ev.header.timestamp, ev.header.displayId,
+ std::move(mFrameRateOverrides));
+ break;
default:
ALOGW("dispatcher %p ~ ignoring unknown event type %#x", this, ev.header.type);
break;
diff --git a/libs/gui/DisplayEventReceiver.cpp b/libs/gui/DisplayEventReceiver.cpp
index f2b0962..03b33c7 100644
--- a/libs/gui/DisplayEventReceiver.cpp
+++ b/libs/gui/DisplayEventReceiver.cpp
@@ -32,11 +32,12 @@
// ---------------------------------------------------------------------------
-DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource,
- ISurfaceComposer::ConfigChanged configChanged) {
+DisplayEventReceiver::DisplayEventReceiver(
+ ISurfaceComposer::VsyncSource vsyncSource,
+ ISurfaceComposer::EventRegistrationFlags eventRegistration) {
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
if (sf != nullptr) {
- mEventConnection = sf->createDisplayEventConnection(vsyncSource, configChanged);
+ mEventConnection = sf->createDisplayEventConnection(vsyncSource, eventRegistration);
if (mEventConnection != nullptr) {
mDataChannel = std::make_unique<gui::BitTube>();
mEventConnection->stealReceiveChannel(mDataChannel.get());
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index a9fe5bf..e46a415 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -223,8 +223,8 @@
return NO_ERROR;
}
- virtual sp<IDisplayEventConnection> createDisplayEventConnection(VsyncSource vsyncSource,
- ConfigChanged configChanged) {
+ virtual sp<IDisplayEventConnection> createDisplayEventConnection(
+ VsyncSource vsyncSource, EventRegistrationFlags eventRegistration) {
Parcel data, reply;
sp<IDisplayEventConnection> result;
int err = data.writeInterfaceToken(
@@ -233,7 +233,7 @@
return result;
}
data.writeInt32(static_cast<int32_t>(vsyncSource));
- data.writeInt32(static_cast<int32_t>(configChanged));
+ data.writeUint32(eventRegistration.get());
err = remote()->transact(
BnSurfaceComposer::CREATE_DISPLAY_EVENT_CONNECTION,
data, &reply);
@@ -1373,10 +1373,11 @@
case CREATE_DISPLAY_EVENT_CONNECTION: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
auto vsyncSource = static_cast<ISurfaceComposer::VsyncSource>(data.readInt32());
- auto configChanged = static_cast<ISurfaceComposer::ConfigChanged>(data.readInt32());
+ EventRegistrationFlags eventRegistration =
+ static_cast<EventRegistration>(data.readUint32());
sp<IDisplayEventConnection> connection(
- createDisplayEventConnection(vsyncSource, configChanged));
+ createDisplayEventConnection(vsyncSource, eventRegistration));
reply->writeStrongBinder(IInterface::asBinder(connection));
return NO_ERROR;
}
diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h
index c65618b..5587acf 100644
--- a/libs/gui/include/gui/DisplayEventDispatcher.h
+++ b/libs/gui/include/gui/DisplayEventDispatcher.h
@@ -19,6 +19,7 @@
#include <utils/Looper.h>
namespace android {
+using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride;
struct VsyncEventData {
// The Vsync Id corresponsing to this vsync event. This will be used to
@@ -36,8 +37,7 @@
explicit DisplayEventDispatcher(
const sp<Looper>& looper,
ISurfaceComposer::VsyncSource vsyncSource = ISurfaceComposer::eVsyncSourceApp,
- ISurfaceComposer::ConfigChanged configChanged =
- ISurfaceComposer::eConfigChangedSuppress);
+ ISurfaceComposer::EventRegistrationFlags eventRegistration = {});
status_t initialize();
void dispose();
@@ -54,6 +54,8 @@
DisplayEventReceiver mReceiver;
bool mWaitingForVsync;
+ std::vector<FrameRateOverride> mFrameRateOverrides;
+
virtual void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count,
VsyncEventData vsyncEventData) = 0;
virtual void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId,
@@ -64,6 +66,9 @@
// can be properly poked.
virtual void dispatchNullEvent(nsecs_t timestamp, PhysicalDisplayId displayId) = 0;
+ virtual void dispatchFrameRateOverrides(nsecs_t timestamp, PhysicalDisplayId displayId,
+ std::vector<FrameRateOverride> overrides) = 0;
+
bool processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId,
uint32_t* outCount, VsyncEventData* outVsyncEventData);
};
diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h
index df3118f..3191fc9 100644
--- a/libs/gui/include/gui/DisplayEventReceiver.h
+++ b/libs/gui/include/gui/DisplayEventReceiver.h
@@ -54,6 +54,8 @@
DISPLAY_EVENT_HOTPLUG = fourcc('p', 'l', 'u', 'g'),
DISPLAY_EVENT_CONFIG_CHANGED = fourcc('c', 'o', 'n', 'f'),
DISPLAY_EVENT_NULL = fourcc('n', 'u', 'l', 'l'),
+ DISPLAY_EVENT_FRAME_RATE_OVERRIDE = fourcc('r', 'a', 't', 'e'),
+ DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH = fourcc('f', 'l', 's', 'h'),
};
struct Event {
@@ -85,11 +87,17 @@
nsecs_t vsyncPeriod __attribute__((aligned(8)));
};
+ struct FrameRateOverride {
+ uid_t uid __attribute__((aligned(8)));
+ float frameRateHz __attribute__((aligned(8)));
+ };
+
Header header;
union {
VSync vsync;
Hotplug hotplug;
Config config;
+ FrameRateOverride frameRateOverride;
};
};
@@ -98,13 +106,12 @@
* DisplayEventReceiver creates and registers an event connection with
* SurfaceFlinger. VSync events are disabled by default. Call setVSyncRate
* or requestNextVsync to receive them.
- * To receive Config Changed events specify this in the constructor.
- * Other events start being delivered immediately.
+ * To receive ConfigChanged and/or FrameRateOverrides events specify this in
+ * the constructor. Other events start being delivered immediately.
*/
explicit DisplayEventReceiver(
ISurfaceComposer::VsyncSource vsyncSource = ISurfaceComposer::eVsyncSourceApp,
- ISurfaceComposer::ConfigChanged configChanged =
- ISurfaceComposer::eConfigChangedSuppress);
+ ISurfaceComposer::EventRegistrationFlags eventRegistration = {});
/*
* ~DisplayEventReceiver severs the connection with SurfaceFlinger, new events
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 9e96b79..86e3a25 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -26,6 +26,8 @@
#include <gui/IScreenCaptureListener.h>
#include <gui/ITransactionCompletedListener.h>
+#include <input/Flags.h>
+
#include <math/vec4.h>
#include <ui/ConfigStoreTypes.h>
@@ -107,7 +109,12 @@
eVsyncSourceSurfaceFlinger = 1
};
- enum ConfigChanged { eConfigChangedSuppress = 0, eConfigChangedDispatch = 1 };
+ enum class EventRegistration {
+ configChanged = 1 << 0,
+ frameRateOverride = 1 << 1,
+ };
+
+ using EventRegistrationFlags = Flags<EventRegistration>;
// Needs to be in sync with android.graphics.FrameInfo.INVALID_VSYNC_ID in java
static constexpr int64_t INVALID_VSYNC_ID = -1;
@@ -120,7 +127,7 @@
/* return an IDisplayEventConnection */
virtual sp<IDisplayEventConnection> createDisplayEventConnection(
VsyncSource vsyncSource = eVsyncSourceApp,
- ConfigChanged configChanged = eConfigChangedSuppress) = 0;
+ EventRegistrationFlags eventRegistration = {}) = 0;
/* create a virtual display
* requires ACCESS_SURFACE_FLINGER permission.
diff --git a/libs/gui/tests/DisplayEventStructLayout_test.cpp b/libs/gui/tests/DisplayEventStructLayout_test.cpp
index 7210910..c5093e2 100644
--- a/libs/gui/tests/DisplayEventStructLayout_test.cpp
+++ b/libs/gui/tests/DisplayEventStructLayout_test.cpp
@@ -40,6 +40,9 @@
CHECK_OFFSET(DisplayEventReceiver::Event::Config, configId, 0);
CHECK_OFFSET(DisplayEventReceiver::Event::Config, vsyncPeriod, 8);
+
+ CHECK_OFFSET(DisplayEventReceiver::Event::FrameRateOverride, uid, 0);
+ CHECK_OFFSET(DisplayEventReceiver::Event::FrameRateOverride, frameRateHz, 8);
}
} // namespace android::test
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 2392ae5..ce3afa2 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -687,7 +687,7 @@
sp<ISurfaceComposerClient> createConnection() override { return nullptr; }
sp<IDisplayEventConnection> createDisplayEventConnection(
- ISurfaceComposer::VsyncSource, ISurfaceComposer::ConfigChanged) override {
+ ISurfaceComposer::VsyncSource, ISurfaceComposer::EventRegistrationFlags) override {
return nullptr;
}
sp<IBinder> createDisplay(const String8& /*displayName*/,
diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp
index 9e515cd..6d91916 100644
--- a/libs/nativedisplay/AChoreographer.cpp
+++ b/libs/nativedisplay/AChoreographer.cpp
@@ -141,6 +141,8 @@
void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t configId,
nsecs_t vsyncPeriod) override;
void dispatchNullEvent(nsecs_t, PhysicalDisplayId) override;
+ void dispatchFrameRateOverrides(nsecs_t timestamp, PhysicalDisplayId displayId,
+ std::vector<FrameRateOverride> overrides) override;
void scheduleCallbacks();
@@ -175,8 +177,7 @@
}
Choreographer::Choreographer(const sp<Looper>& looper)
- : DisplayEventDispatcher(looper, ISurfaceComposer::VsyncSource::eVsyncSourceApp,
- ISurfaceComposer::ConfigChanged::eConfigChangedSuppress),
+ : DisplayEventDispatcher(looper, ISurfaceComposer::VsyncSource::eVsyncSourceApp),
mLooper(looper),
mThreadId(std::this_thread::get_id()) {
std::lock_guard<std::mutex> _l(gChoreographers.lock);
@@ -381,15 +382,13 @@
this, to_string(displayId).c_str(), toString(connected));
}
-// TODO(b/74619554): The PhysicalDisplayId is ignored because currently
-// Choreographer only supports dispatching VSYNC events for the internal
-// display, so as such Choreographer does not support the notion of multiple
-// displays. When multi-display choreographer is properly supported, then
-// PhysicalDisplayId should no longer be ignored.
-void Choreographer::dispatchConfigChanged(nsecs_t, PhysicalDisplayId displayId, int32_t configId,
- nsecs_t) {
- ALOGV("choreographer %p ~ received config change event (displayId=%s, configId=%d).",
- this, to_string(displayId).c_str(), configId);
+void Choreographer::dispatchConfigChanged(nsecs_t, PhysicalDisplayId, int32_t, nsecs_t) {
+ LOG_ALWAYS_FATAL("dispatchConfigChanged was called but was never registered");
+}
+
+void Choreographer::dispatchFrameRateOverrides(nsecs_t, PhysicalDisplayId,
+ std::vector<FrameRateOverride>) {
+ LOG_ALWAYS_FATAL("dispatchFrameRateOverrides was called but was never registered");
}
void Choreographer::dispatchNullEvent(nsecs_t, PhysicalDisplayId) {
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index bf5be47..b63e8c8 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -45,6 +45,9 @@
#include "FrameTimeline.h"
#include "HwcStrongTypes.h"
+#undef LOG_TAG
+#define LOG_TAG "EventThread"
+
using namespace std::chrono_literals;
namespace android {
@@ -123,14 +126,36 @@
return event;
}
+DisplayEventReceiver::Event makeFrameRateOverrideEvent(PhysicalDisplayId displayId,
+ FrameRateOverride frameRateOverride) {
+ return DisplayEventReceiver::Event{
+ .header =
+ DisplayEventReceiver::Event::Header{
+ .type = DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE,
+ .displayId = displayId,
+ .timestamp = systemTime(),
+ },
+ .frameRateOverride = frameRateOverride,
+ };
+}
+
+DisplayEventReceiver::Event makeFrameRateOverrideFlushEvent(PhysicalDisplayId displayId) {
+ return DisplayEventReceiver::Event{
+ .header = DisplayEventReceiver::Event::Header{
+ .type = DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH,
+ .displayId = displayId,
+ .timestamp = systemTime(),
+ }};
+}
+
} // namespace
-EventThreadConnection::EventThreadConnection(EventThread* eventThread, uid_t callingUid,
- ResyncCallback resyncCallback,
- ISurfaceComposer::ConfigChanged configChanged)
+EventThreadConnection::EventThreadConnection(
+ EventThread* eventThread, uid_t callingUid, ResyncCallback resyncCallback,
+ ISurfaceComposer::EventRegistrationFlags eventRegistration)
: resyncCallback(std::move(resyncCallback)),
- mConfigChanged(configChanged),
mOwnerUid(callingUid),
+ mEventRegistration(eventRegistration),
mEventThread(eventThread),
mChannel(gui::BitTube::DefaultSize) {}
@@ -161,8 +186,25 @@
}
status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {
- ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
- return size < 0 ? status_t(size) : status_t(NO_ERROR);
+ constexpr auto toStatus = [](ssize_t size) {
+ return size < 0 ? status_t(size) : status_t(NO_ERROR);
+ };
+
+ if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE ||
+ event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH) {
+ mPendingEvents.emplace_back(event);
+ if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE) {
+ return status_t(NO_ERROR);
+ }
+
+ auto size = DisplayEventReceiver::sendEvents(&mChannel, mPendingEvents.data(),
+ mPendingEvents.size());
+ mPendingEvents.clear();
+ return toStatus(size);
+ }
+
+ auto size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
+ return toStatus(size);
}
// ---------------------------------------------------------------------------
@@ -220,10 +262,11 @@
}
sp<EventThreadConnection> EventThread::createEventConnection(
- ResyncCallback resyncCallback, ISurfaceComposer::ConfigChanged configChanged) const {
+ ResyncCallback resyncCallback,
+ ISurfaceComposer::EventRegistrationFlags eventRegistration) const {
return new EventThreadConnection(const_cast<EventThread*>(this),
IPCThreadState::self()->getCallingUid(),
- std::move(resyncCallback), configChanged);
+ std::move(resyncCallback), eventRegistration);
}
status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) {
@@ -333,6 +376,18 @@
mCondition.notify_all();
}
+void EventThread::onFrameRateOverridesChanged(PhysicalDisplayId displayId,
+ std::vector<FrameRateOverride> overrides) {
+ std::lock_guard<std::mutex> lock(mMutex);
+
+ for (auto frameRateOverride : overrides) {
+ mPendingEvents.push_back(makeFrameRateOverrideEvent(displayId, frameRateOverride));
+ }
+ mPendingEvents.push_back(makeFrameRateOverrideFlushEvent(displayId));
+
+ mCondition.notify_all();
+}
+
size_t EventThread::getEventThreadConnectionCount() {
std::lock_guard<std::mutex> lock(mMutex);
return mDisplayEventConnections.size();
@@ -459,7 +514,8 @@
return true;
case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED: {
- return connection->mConfigChanged == ISurfaceComposer::eConfigChangedDispatch;
+ return connection->mEventRegistration.test(
+ ISurfaceComposer::EventRegistration::configChanged);
}
case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
@@ -488,6 +544,12 @@
return event.vsync.count % vsyncPeriod(connection->vsyncRequest) == 0;
}
+ case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE:
+ [[fallthrough]];
+ case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH:
+ return connection->mEventRegistration.test(
+ ISurfaceComposer::EventRegistration::frameRateOverride);
+
default:
return false;
}
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index 2e2d989..e75b718 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -48,6 +48,7 @@
// ---------------------------------------------------------------------------
using ResyncCallback = std::function<void()>;
+using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride;
enum class VSyncRequest {
None = -2,
@@ -82,7 +83,7 @@
class EventThreadConnection : public BnDisplayEventConnection {
public:
EventThreadConnection(EventThread*, uid_t callingUid, ResyncCallback,
- ISurfaceComposer::ConfigChanged configChanged);
+ ISurfaceComposer::EventRegistrationFlags eventRegistration = {});
virtual ~EventThreadConnection();
virtual status_t postEvent(const DisplayEventReceiver::Event& event);
@@ -95,15 +96,15 @@
const ResyncCallback resyncCallback;
VSyncRequest vsyncRequest = VSyncRequest::None;
- const ISurfaceComposer::ConfigChanged mConfigChanged =
- ISurfaceComposer::ConfigChanged::eConfigChangedSuppress;
-
const uid_t mOwnerUid;
+ const ISurfaceComposer::EventRegistrationFlags mEventRegistration;
private:
virtual void onFirstRef();
EventThread* const mEventThread;
gui::BitTube mChannel;
+
+ std::vector<DisplayEventReceiver::Event> mPendingEvents;
};
class EventThread {
@@ -111,7 +112,8 @@
virtual ~EventThread();
virtual sp<EventThreadConnection> createEventConnection(
- ResyncCallback, ISurfaceComposer::ConfigChanged configChanged) const = 0;
+ ResyncCallback,
+ ISurfaceComposer::EventRegistrationFlags eventRegistration = {}) const = 0;
// called before the screen is turned off from main thread
virtual void onScreenReleased() = 0;
@@ -125,6 +127,10 @@
virtual void onConfigChanged(PhysicalDisplayId displayId, HwcConfigIndexType configId,
nsecs_t vsyncPeriod) = 0;
+ // called when SF updates the Frame Rate Override list
+ virtual void onFrameRateOverridesChanged(PhysicalDisplayId displayId,
+ std::vector<FrameRateOverride> overrides) = 0;
+
virtual void dump(std::string& result) const = 0;
virtual void setDuration(std::chrono::nanoseconds workDuration,
@@ -152,7 +158,8 @@
~EventThread();
sp<EventThreadConnection> createEventConnection(
- ResyncCallback, ISurfaceComposer::ConfigChanged configChanged) const override;
+ ResyncCallback,
+ ISurfaceComposer::EventRegistrationFlags eventRegistration = {}) const override;
status_t registerDisplayEventConnection(const sp<EventThreadConnection>& connection) override;
void setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& connection) override;
@@ -169,6 +176,9 @@
void onConfigChanged(PhysicalDisplayId displayId, HwcConfigIndexType configId,
nsecs_t vsyncPeriod) override;
+ void onFrameRateOverridesChanged(PhysicalDisplayId displayId,
+ std::vector<FrameRateOverride> overrides) override;
+
void dump(std::string& result) const override;
void setDuration(std::chrono::nanoseconds workDuration,
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index b872d7a..8b4283c 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -687,21 +687,20 @@
return RefreshRateConfigs::KernelIdleTimerAction::TurnOn;
}
-void RefreshRateConfigs::setPreferredRefreshRateForUid(uid_t uid, float refreshRateHz) {
- if (refreshRateHz > 0 && refreshRateHz < 1) {
+void RefreshRateConfigs::setPreferredRefreshRateForUid(FrameRateOverride frameRateOverride) {
+ if (frameRateOverride.frameRateHz > 0 && frameRateOverride.frameRateHz < 1) {
return;
}
std::lock_guard lock(mLock);
- if (refreshRateHz != 0) {
- mPreferredRefreshRateForUid[uid] = refreshRateHz;
+ if (frameRateOverride.frameRateHz != 0) {
+ mPreferredRefreshRateForUid[frameRateOverride.uid] = frameRateOverride.frameRateHz;
} else {
- mPreferredRefreshRateForUid.erase(uid);
+ mPreferredRefreshRateForUid.erase(frameRateOverride.uid);
}
}
int RefreshRateConfigs::getRefreshRateDividerForUid(uid_t uid) const {
- constexpr float kThreshold = 0.1f;
std::lock_guard lock(mLock);
const auto iter = mPreferredRefreshRateForUid.find(uid);
@@ -709,6 +708,9 @@
return 1;
}
+ // This calculation needs to be in sync with the java code
+ // in DisplayManagerService.getDisplayInfoForFrameRateOverride
+ constexpr float kThreshold = 0.1f;
const auto refreshRateHz = iter->second;
const auto numPeriods = mCurrentRefreshRate->getFps() / refreshRateHz;
const auto numPeriodsRounded = std::round(numPeriods);
@@ -716,7 +718,19 @@
return 1;
}
- return static_cast<int>(numPeriods);
+ return static_cast<int>(numPeriodsRounded);
+}
+
+std::vector<FrameRateOverride> RefreshRateConfigs::getFrameRateOverrides() {
+ std::lock_guard lock(mLock);
+ std::vector<FrameRateOverride> overrides;
+ overrides.reserve(mPreferredRefreshRateForUid.size());
+
+ for (const auto [uid, frameRate] : mPreferredRefreshRateForUid) {
+ overrides.emplace_back(FrameRateOverride{uid, frameRate});
+ }
+
+ return overrides;
}
void RefreshRateConfigs::dump(std::string& result) const {
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index 3159352..a873777 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -17,6 +17,7 @@
#pragma once
#include <android-base/stringprintf.h>
+#include <gui/DisplayEventReceiver.h>
#include <algorithm>
#include <numeric>
@@ -39,6 +40,8 @@
return static_cast<RefreshRateConfigEvent>(static_cast<T>(lhs) | static_cast<T>(rhs));
}
+using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride;
+
/**
* This class is used to encapsulate configuration for refresh rates. It holds information
* about available refresh rates on the device, and the mapping between the numbers and human
@@ -316,14 +319,17 @@
KernelIdleTimerAction getIdleTimerAction() const;
// Stores the preferred refresh rate that an app should run at.
- // refreshRate == 0 means no preference.
- void setPreferredRefreshRateForUid(uid_t, float refreshRateHz) EXCLUDES(mLock);
+ // FrameRateOverride.refreshRateHz == 0 means no preference.
+ void setPreferredRefreshRateForUid(FrameRateOverride) EXCLUDES(mLock);
// Returns a divider for the current refresh rate
int getRefreshRateDividerForUid(uid_t) const EXCLUDES(mLock);
void dump(std::string& result) const EXCLUDES(mLock);
+ // Returns the current frame rate overrides
+ std::vector<FrameRateOverride> getFrameRateOverrides() EXCLUDES(mLock);
+
private:
friend class RefreshRateConfigsTest;
@@ -381,6 +387,8 @@
Policy mDisplayManagerPolicy GUARDED_BY(mLock);
std::optional<Policy> mOverridePolicy GUARDED_BY(mLock);
+ // A mapping between a UID and a preferred refresh rate that this app would
+ // run at.
std::unordered_map<uid_t, float> mPreferredRefreshRateForUid GUARDED_BY(mLock);
// The min and max refresh rates supported by the device.
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index a14019e..a93bf11 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -239,8 +239,7 @@
const ConnectionHandle handle = ConnectionHandle{mNextConnectionHandleId++};
ALOGV("Creating a connection handle with ID %" PRIuPTR, handle.id);
- auto connection =
- createConnectionInternal(eventThread.get(), ISurfaceComposer::eConfigChangedSuppress);
+ auto connection = createConnectionInternal(eventThread.get());
std::lock_guard<std::mutex> lock(mConnectionsLock);
mConnections.emplace(handle, Connection{connection, std::move(eventThread)});
@@ -248,15 +247,15 @@
}
sp<EventThreadConnection> Scheduler::createConnectionInternal(
- EventThread* eventThread, ISurfaceComposer::ConfigChanged configChanged) {
- return eventThread->createEventConnection([&] { resync(); }, configChanged);
+ EventThread* eventThread, ISurfaceComposer::EventRegistrationFlags eventRegistration) {
+ return eventThread->createEventConnection([&] { resync(); }, eventRegistration);
}
sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
- ConnectionHandle handle, ISurfaceComposer::ConfigChanged configChanged) {
+ ConnectionHandle handle, ISurfaceComposer::EventRegistrationFlags eventRegistration) {
std::lock_guard<std::mutex> lock(mConnectionsLock);
RETURN_IF_INVALID_HANDLE(handle, nullptr);
- return createConnectionInternal(mConnections[handle].thread.get(), configChanged);
+ return createConnectionInternal(mConnections[handle].thread.get(), eventRegistration);
}
sp<EventThreadConnection> Scheduler::getEventConnection(ConnectionHandle handle) {
@@ -297,6 +296,17 @@
thread->onScreenReleased();
}
+void Scheduler::onFrameRateOverridesChanged(ConnectionHandle handle, PhysicalDisplayId displayId,
+ std::vector<FrameRateOverride> overrides) {
+ android::EventThread* thread;
+ {
+ std::lock_guard<std::mutex> lock(mConnectionsLock);
+ RETURN_IF_INVALID_HANDLE(handle);
+ thread = mConnections[handle].thread.get();
+ }
+ thread->onFrameRateOverridesChanged(displayId, std::move(overrides));
+}
+
void Scheduler::onPrimaryDisplayConfigChanged(ConnectionHandle handle, PhysicalDisplayId displayId,
HwcConfigIndexType configId, nsecs_t vsyncPeriod) {
std::lock_guard<std::mutex> lock(mFeatureStateLock);
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 4c86d26..76e8f57 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -79,8 +79,8 @@
std::chrono::nanoseconds readyDuration,
impl::EventThread::InterceptVSyncsCallback);
- sp<IDisplayEventConnection> createDisplayEventConnection(ConnectionHandle,
- ISurfaceComposer::ConfigChanged);
+ sp<IDisplayEventConnection> createDisplayEventConnection(
+ ConnectionHandle, ISurfaceComposer::EventRegistrationFlags eventRegistration = {});
sp<EventThreadConnection> getEventConnection(ConnectionHandle);
@@ -93,6 +93,9 @@
void onScreenAcquired(ConnectionHandle);
void onScreenReleased(ConnectionHandle);
+ void onFrameRateOverridesChanged(ConnectionHandle, PhysicalDisplayId,
+ std::vector<FrameRateOverride>);
+
// Modifies work duration in the event thread.
void setDuration(ConnectionHandle, std::chrono::nanoseconds workDuration,
std::chrono::nanoseconds readyDuration);
@@ -203,8 +206,8 @@
// Create a connection on the given EventThread.
ConnectionHandle createConnection(std::unique_ptr<EventThread>);
- sp<EventThreadConnection> createConnectionInternal(EventThread*,
- ISurfaceComposer::ConfigChanged);
+ sp<EventThreadConnection> createConnectionInternal(
+ EventThread*, ISurfaceComposer::EventRegistrationFlags eventRegistration = {});
// Update feature state machine to given state when corresponding timer resets or expires.
void kernelIdleTimerCallback(TimerState);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 91f050c..eed6aa4 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1527,11 +1527,12 @@
// ----------------------------------------------------------------------------
sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
- ISurfaceComposer::VsyncSource vsyncSource, ISurfaceComposer::ConfigChanged configChanged) {
+ ISurfaceComposer::VsyncSource vsyncSource,
+ ISurfaceComposer::EventRegistrationFlags eventRegistration) {
const auto& handle =
vsyncSource == eVsyncSourceSurfaceFlinger ? mSfConnectionHandle : mAppConnectionHandle;
- return mScheduler->createDisplayEventConnection(handle, configChanged);
+ return mScheduler->createDisplayEventConnection(handle, eventRegistration);
}
void SurfaceFlinger::signalTransaction() {
@@ -5274,10 +5275,18 @@
return NO_ERROR;
}
case 1039: {
- // The first parameter is the uid
- n = data.readInt32();
- const float refreshRateHz = data.readFloat();
- mRefreshRateConfigs->setPreferredRefreshRateForUid(n, refreshRateHz);
+ PhysicalDisplayId displayId = [&]() {
+ Mutex::Autolock lock(mStateLock);
+ return getDefaultDisplayDeviceLocked()->getPhysicalId();
+ }();
+
+ auto inUid = static_cast<uid_t>(data.readInt32());
+ const auto refreshRate = data.readFloat();
+ mRefreshRateConfigs->setPreferredRefreshRateForUid(
+ FrameRateOverride{inUid, refreshRate});
+ const auto mappings = mRefreshRateConfigs->getFrameRateOverrides();
+ mScheduler->onFrameRateOverridesChanged(mAppConnectionHandle, displayId,
+ std::move(mappings));
}
return NO_ERROR;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 9666f14..a909ad8 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -530,8 +530,7 @@
status_t getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported) const override;
sp<IDisplayEventConnection> createDisplayEventConnection(
ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp,
- ISurfaceComposer::ConfigChanged configChanged =
- ISurfaceComposer::eConfigChangedSuppress) override;
+ ISurfaceComposer::EventRegistrationFlags eventRegistration = {}) override;
status_t captureDisplay(const DisplayCaptureArgs& args,
const sp<IScreenCaptureListener>& captureListener) override;
status_t captureDisplay(uint64_t displayOrLayerStack,
diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
index 0a70f5c..31a5126 100644
--- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
+++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
@@ -240,8 +240,9 @@
mComposerClient = new SurfaceComposerClient;
ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
- mReceiver.reset(new DisplayEventReceiver(ISurfaceComposer::eVsyncSourceApp,
- ISurfaceComposer::eConfigChangedDispatch));
+ mReceiver.reset(
+ new DisplayEventReceiver(ISurfaceComposer::eVsyncSourceApp,
+ ISurfaceComposer::EventRegistration::configChanged));
mLooper = new Looper(false);
mLooper->addFd(mReceiver->getFd(), 0, ALOOPER_EVENT_INPUT, processDisplayEvents, this);
}
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 0911712..be9d336 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -133,17 +133,13 @@
EXPECT_CALL(*eventThread, registerDisplayEventConnection(_));
EXPECT_CALL(*eventThread, createEventConnection(_, _))
- .WillOnce(Return(
- new EventThreadConnection(eventThread.get(), /*callingUid=*/0,
- ResyncCallback(),
- ISurfaceComposer::eConfigChangedSuppress)));
+ .WillOnce(Return(new EventThreadConnection(eventThread.get(), /*callingUid=*/0,
+ ResyncCallback())));
EXPECT_CALL(*sfEventThread, registerDisplayEventConnection(_));
EXPECT_CALL(*sfEventThread, createEventConnection(_, _))
- .WillOnce(Return(
- new EventThreadConnection(sfEventThread.get(), /*callingUid=*/0,
- ResyncCallback(),
- ISurfaceComposer::eConfigChangedSuppress)));
+ .WillOnce(Return(new EventThreadConnection(sfEventThread.get(), /*callingUid=*/0,
+ ResyncCallback())));
auto vsyncController = std::make_unique<mock::VsyncController>();
auto vsyncTracker = std::make_unique<mock::VSyncTracker>();
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index f0311bd..9069200 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -70,15 +70,13 @@
void DisplayTransactionTest::injectMockScheduler() {
EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_));
EXPECT_CALL(*mEventThread, createEventConnection(_, _))
- .WillOnce(Return(new EventThreadConnection(mEventThread, /*callingUid=*/0,
- ResyncCallback(),
- ISurfaceComposer::eConfigChangedSuppress)));
+ .WillOnce(Return(
+ new EventThreadConnection(mEventThread, /*callingUid=*/0, ResyncCallback())));
EXPECT_CALL(*mSFEventThread, registerDisplayEventConnection(_));
EXPECT_CALL(*mSFEventThread, createEventConnection(_, _))
- .WillOnce(Return(new EventThreadConnection(mSFEventThread, /*callingUid=*/0,
- ResyncCallback(),
- ISurfaceComposer::eConfigChangedSuppress)));
+ .WillOnce(Return(
+ new EventThreadConnection(mSFEventThread, /*callingUid=*/0, ResyncCallback())));
mFlinger.setupScheduler(std::unique_ptr<scheduler::VsyncController>(mVsyncController),
std::unique_ptr<scheduler::VSyncTracker>(mVSyncTracker),
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index 3aafd45..ee56178 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -29,6 +29,7 @@
using namespace std::chrono_literals;
using namespace std::placeholders;
+using namespace android::flag_operators;
using testing::_;
using testing::Invoke;
@@ -61,9 +62,9 @@
public:
MockEventThreadConnection(impl::EventThread* eventThread, uid_t callingUid,
ResyncCallback&& resyncCallback,
- ISurfaceComposer::ConfigChanged configChanged)
+ ISurfaceComposer::EventRegistrationFlags eventRegistration)
: EventThreadConnection(eventThread, callingUid, std::move(resyncCallback),
- configChanged) {}
+ eventRegistration) {}
MOCK_METHOD1(postEvent, status_t(const DisplayEventReceiver::Event& event));
};
@@ -74,9 +75,10 @@
~EventThreadTest() override;
void createThread(std::unique_ptr<VSyncSource>);
- sp<MockEventThreadConnection> createConnection(ConnectionEventRecorder& recorder,
- ISurfaceComposer::ConfigChanged configChanged,
- uid_t ownerUid = mConnectionUid);
+ sp<MockEventThreadConnection> createConnection(
+ ConnectionEventRecorder& recorder,
+ ISurfaceComposer::EventRegistrationFlags eventRegistration = {},
+ uid_t ownerUid = mConnectionUid);
void expectVSyncSetEnabledCallReceived(bool expectedState);
void expectVSyncSetDurationCallReceived(std::chrono::nanoseconds expectedDuration,
@@ -93,6 +95,8 @@
int32_t expectedConfigId,
nsecs_t expectedVsyncPeriod);
void expectThrottleVsyncReceived(nsecs_t expectedTimestamp, uid_t);
+ void expectUidFrameRateMappingEventReceivedByConnection(PhysicalDisplayId expectedDisplayId,
+ std::vector<FrameRateOverride>);
AsyncCallRecorder<void (*)(bool)> mVSyncSetEnabledCallRecorder;
AsyncCallRecorder<void (*)(VSyncSource::Callback*)> mVSyncSetCallbackCallRecorder;
@@ -133,10 +137,11 @@
createThread(std::move(vsyncSource));
mConnection = createConnection(mConnectionEventCallRecorder,
- ISurfaceComposer::eConfigChangedDispatch);
- mThrottledConnection =
- createConnection(mThrottledConnectionEventCallRecorder,
- ISurfaceComposer::eConfigChangedDispatch, mThrottledConnectionUid);
+ ISurfaceComposer::EventRegistration::configChanged |
+ ISurfaceComposer::EventRegistration::frameRateOverride);
+ mThrottledConnection = createConnection(mThrottledConnectionEventCallRecorder,
+ ISurfaceComposer::EventRegistration::configChanged,
+ mThrottledConnectionUid);
// A display must be connected for VSYNC events to be delivered.
mThread->onHotplugReceived(INTERNAL_DISPLAY_ID, true);
@@ -169,11 +174,11 @@
}
sp<EventThreadTest::MockEventThreadConnection> EventThreadTest::createConnection(
- ConnectionEventRecorder& recorder, ISurfaceComposer::ConfigChanged configChanged,
- uid_t ownerUid) {
+ ConnectionEventRecorder& recorder,
+ ISurfaceComposer::EventRegistrationFlags eventRegistration, uid_t ownerUid) {
sp<MockEventThreadConnection> connection =
new MockEventThreadConnection(mThread.get(), ownerUid,
- mResyncCallRecorder.getInvocable(), configChanged);
+ mResyncCallRecorder.getInvocable(), eventRegistration);
EXPECT_CALL(*connection, postEvent(_)).WillRepeatedly(Invoke(recorder.getInvocable()));
return connection;
}
@@ -254,6 +259,25 @@
EXPECT_EQ(expectedVsyncPeriod, event.config.vsyncPeriod);
}
+void EventThreadTest::expectUidFrameRateMappingEventReceivedByConnection(
+ PhysicalDisplayId expectedDisplayId, std::vector<FrameRateOverride> expectedOverrides) {
+ for (const auto [uid, frameRateHz] : expectedOverrides) {
+ auto args = mConnectionEventCallRecorder.waitForCall();
+ ASSERT_TRUE(args.has_value());
+ const auto& event = std::get<0>(args.value());
+ EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE, event.header.type);
+ EXPECT_EQ(expectedDisplayId, event.header.displayId);
+ EXPECT_EQ(uid, event.frameRateOverride.uid);
+ EXPECT_EQ(frameRateHz, event.frameRateOverride.frameRateHz);
+ }
+
+ auto args = mConnectionEventCallRecorder.waitForCall();
+ ASSERT_TRUE(args.has_value());
+ const auto& event = std::get<0>(args.value());
+ EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH, event.header.type);
+ EXPECT_EQ(expectedDisplayId, event.header.displayId);
+}
+
namespace {
/* ------------------------------------------------------------------------
@@ -313,9 +337,7 @@
TEST_F(EventThreadTest, setVsyncRateZeroPostsNoVSyncEventsToThatConnection) {
// Create a first connection, register it, and request a vsync rate of zero.
ConnectionEventRecorder firstConnectionEventRecorder{0};
- sp<MockEventThreadConnection> firstConnection =
- createConnection(firstConnectionEventRecorder,
- ISurfaceComposer::eConfigChangedSuppress);
+ sp<MockEventThreadConnection> firstConnection = createConnection(firstConnectionEventRecorder);
mThread->setVsyncRate(0, firstConnection);
// By itself, this should not enable vsync events
@@ -325,8 +347,7 @@
// However if there is another connection which wants events at a nonzero rate.....
ConnectionEventRecorder secondConnectionEventRecorder{0};
sp<MockEventThreadConnection> secondConnection =
- createConnection(secondConnectionEventRecorder,
- ISurfaceComposer::eConfigChangedSuppress);
+ createConnection(secondConnectionEventRecorder);
mThread->setVsyncRate(1, secondConnection);
// EventThread should enable vsync callbacks.
@@ -418,9 +439,7 @@
TEST_F(EventThreadTest, connectionsRemovedIfEventDeliveryError) {
ConnectionEventRecorder errorConnectionEventRecorder{NO_MEMORY};
- sp<MockEventThreadConnection> errorConnection =
- createConnection(errorConnectionEventRecorder,
- ISurfaceComposer::eConfigChangedSuppress);
+ sp<MockEventThreadConnection> errorConnection = createConnection(errorConnectionEventRecorder);
mThread->setVsyncRate(1, errorConnection);
// EventThread should enable vsync callbacks.
@@ -445,15 +464,12 @@
TEST_F(EventThreadTest, tracksEventConnections) {
EXPECT_EQ(2, mThread->getEventThreadConnectionCount());
ConnectionEventRecorder errorConnectionEventRecorder{NO_MEMORY};
- sp<MockEventThreadConnection> errorConnection =
- createConnection(errorConnectionEventRecorder,
- ISurfaceComposer::eConfigChangedSuppress);
+ sp<MockEventThreadConnection> errorConnection = createConnection(errorConnectionEventRecorder);
mThread->setVsyncRate(1, errorConnection);
EXPECT_EQ(3, mThread->getEventThreadConnectionCount());
ConnectionEventRecorder secondConnectionEventRecorder{0};
sp<MockEventThreadConnection> secondConnection =
- createConnection(secondConnectionEventRecorder,
- ISurfaceComposer::eConfigChangedSuppress);
+ createConnection(secondConnectionEventRecorder);
mThread->setVsyncRate(1, secondConnection);
EXPECT_EQ(4, mThread->getEventThreadConnectionCount());
@@ -472,9 +488,7 @@
TEST_F(EventThreadTest, eventsDroppedIfNonfatalEventDeliveryError) {
ConnectionEventRecorder errorConnectionEventRecorder{WOULD_BLOCK};
- sp<MockEventThreadConnection> errorConnection =
- createConnection(errorConnectionEventRecorder,
- ISurfaceComposer::eConfigChangedSuppress);
+ sp<MockEventThreadConnection> errorConnection = createConnection(errorConnectionEventRecorder);
mThread->setVsyncRate(1, errorConnection);
// EventThread should enable vsync callbacks.
@@ -539,8 +553,7 @@
TEST_F(EventThreadTest, suppressConfigChanged) {
ConnectionEventRecorder suppressConnectionEventRecorder{0};
sp<MockEventThreadConnection> suppressConnection =
- createConnection(suppressConnectionEventRecorder,
- ISurfaceComposer::eConfigChangedSuppress);
+ createConnection(suppressConnectionEventRecorder);
mThread->onConfigChanged(INTERNAL_DISPLAY_ID, HwcConfigIndexType(9), 16666666);
expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 9, 16666666);
@@ -549,6 +562,35 @@
ASSERT_FALSE(args.has_value());
}
+TEST_F(EventThreadTest, postUidFrameRateMapping) {
+ const std::vector<FrameRateOverride> overrides = {
+ {.uid = 1, .frameRateHz = 20},
+ {.uid = 3, .frameRateHz = 40},
+ {.uid = 5, .frameRateHz = 60},
+ };
+
+ mThread->onFrameRateOverridesChanged(INTERNAL_DISPLAY_ID, overrides);
+ expectUidFrameRateMappingEventReceivedByConnection(INTERNAL_DISPLAY_ID, overrides);
+}
+
+TEST_F(EventThreadTest, suppressUidFrameRateMapping) {
+ const std::vector<FrameRateOverride> overrides = {
+ {.uid = 1, .frameRateHz = 20},
+ {.uid = 3, .frameRateHz = 40},
+ {.uid = 5, .frameRateHz = 60},
+ };
+
+ ConnectionEventRecorder suppressConnectionEventRecorder{0};
+ sp<MockEventThreadConnection> suppressConnection =
+ createConnection(suppressConnectionEventRecorder);
+
+ mThread->onFrameRateOverridesChanged(INTERNAL_DISPLAY_ID, overrides);
+ expectUidFrameRateMappingEventReceivedByConnection(INTERNAL_DISPLAY_ID, overrides);
+
+ auto args = suppressConnectionEventRecorder.waitForCall();
+ ASSERT_FALSE(args.has_value());
+}
+
TEST_F(EventThreadTest, requestNextVsyncWithThrottleVsyncDoesntPostVSync) {
// Signal that we want the next vsync event to be posted to the throttled connection
mThread->requestNextVsync(mThrottledConnection);
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index df76110..2fbc72a 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -1601,7 +1601,7 @@
std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device,
/*currentConfigId=*/HWC_CONFIG_ID_30);
const uid_t uid = 1234;
- refreshRateConfigs->setPreferredRefreshRateForUid(uid, 30);
+ refreshRateConfigs->setPreferredRefreshRateForUid({uid, 30});
EXPECT_EQ(1, refreshRateConfigs->getRefreshRateDividerForUid(uid));
refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_60);
@@ -1615,6 +1615,12 @@
refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_120);
EXPECT_EQ(4, refreshRateConfigs->getRefreshRateDividerForUid(uid));
+
+ refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90);
+ refreshRateConfigs->setPreferredRefreshRateForUid({uid, 22.5});
+ EXPECT_EQ(4, refreshRateConfigs->getRefreshRateDividerForUid(uid));
+ refreshRateConfigs->setPreferredRefreshRateForUid({uid, 22.6f});
+ EXPECT_EQ(4, refreshRateConfigs->getRefreshRateDividerForUid(uid));
}
} // namespace
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
index 8cd8372..c5deb7c 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
@@ -132,14 +132,12 @@
EXPECT_CALL(*eventThread, registerDisplayEventConnection(_));
EXPECT_CALL(*eventThread, createEventConnection(_, _))
.WillOnce(Return(new EventThreadConnection(eventThread.get(), /*callingUid=*/0,
- ResyncCallback(),
- ISurfaceComposer::eConfigChangedSuppress)));
+ ResyncCallback())));
EXPECT_CALL(*sfEventThread, registerDisplayEventConnection(_));
EXPECT_CALL(*sfEventThread, createEventConnection(_, _))
.WillOnce(Return(new EventThreadConnection(sfEventThread.get(), /*callingUid=*/0,
- ResyncCallback(),
- ISurfaceComposer::eConfigChangedSuppress)));
+ ResyncCallback())));
auto vsyncController = std::make_unique<mock::VsyncController>();
auto vsyncTracker = std::make_unique<mock::VSyncTracker>();
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 509858a..647689b 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -42,8 +42,7 @@
class MockEventThreadConnection : public android::EventThreadConnection {
public:
explicit MockEventThreadConnection(EventThread* eventThread)
- : EventThreadConnection(eventThread, /*callingUid=*/0, ResyncCallback(),
- ISurfaceComposer::eConfigChangedSuppress) {}
+ : EventThreadConnection(eventThread, /*callingUid=*/0, ResyncCallback()) {}
~MockEventThreadConnection() = default;
MOCK_METHOD1(stealReceiveChannel, status_t(gui::BitTube* outChannel));
@@ -98,9 +97,7 @@
TEST_F(SchedulerTest, invalidConnectionHandle) {
Scheduler::ConnectionHandle handle;
- const sp<IDisplayEventConnection> connection =
- mScheduler.createDisplayEventConnection(handle,
- ISurfaceComposer::eConfigChangedSuppress);
+ const sp<IDisplayEventConnection> connection = mScheduler.createDisplayEventConnection(handle);
EXPECT_FALSE(connection);
EXPECT_FALSE(mScheduler.getEventConnection(handle));
@@ -126,8 +123,7 @@
TEST_F(SchedulerTest, validConnectionHandle) {
const sp<IDisplayEventConnection> connection =
- mScheduler.createDisplayEventConnection(mConnectionHandle,
- ISurfaceComposer::eConfigChangedSuppress);
+ mScheduler.createDisplayEventConnection(mConnectionHandle);
ASSERT_EQ(mEventThreadConnection, connection);
EXPECT_TRUE(mScheduler.getEventConnection(mConnectionHandle));
diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
index e25d501..5278641 100644
--- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
@@ -172,14 +172,12 @@
EXPECT_CALL(*eventThread, registerDisplayEventConnection(_));
EXPECT_CALL(*eventThread, createEventConnection(_, _))
.WillOnce(Return(new EventThreadConnection(eventThread.get(), /*callingUid=*/0,
- ResyncCallback(),
- ISurfaceComposer::eConfigChangedSuppress)));
+ ResyncCallback())));
EXPECT_CALL(*sfEventThread, registerDisplayEventConnection(_));
EXPECT_CALL(*sfEventThread, createEventConnection(_, _))
.WillOnce(Return(new EventThreadConnection(sfEventThread.get(), /*callingUid=*/0,
- ResyncCallback(),
- ISurfaceComposer::eConfigChangedSuppress)));
+ ResyncCallback())));
auto vsyncController = std::make_unique<mock::VsyncController>();
auto vsyncTracker = std::make_unique<mock::VSyncTracker>();
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index 68cf330..c36d994 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -65,17 +65,13 @@
EXPECT_CALL(*eventThread, registerDisplayEventConnection(_));
EXPECT_CALL(*eventThread, createEventConnection(_, _))
- .WillOnce(Return(
- new EventThreadConnection(eventThread.get(), /*callingUid=*/0,
- ResyncCallback(),
- ISurfaceComposer::eConfigChangedSuppress)));
+ .WillOnce(Return(new EventThreadConnection(eventThread.get(), /*callingUid=*/0,
+ ResyncCallback())));
EXPECT_CALL(*sfEventThread, registerDisplayEventConnection(_));
EXPECT_CALL(*sfEventThread, createEventConnection(_, _))
- .WillOnce(Return(
- new EventThreadConnection(sfEventThread.get(), /*callingUid=*/0,
- ResyncCallback(),
- ISurfaceComposer::eConfigChangedSuppress)));
+ .WillOnce(Return(new EventThreadConnection(sfEventThread.get(), /*callingUid=*/0,
+ ResyncCallback())));
EXPECT_CALL(*mVSyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
EXPECT_CALL(*mVSyncTracker, currentPeriod())
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
index b4594c1..650d52d 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
@@ -28,11 +28,14 @@
~EventThread() override;
MOCK_CONST_METHOD2(createEventConnection,
- sp<EventThreadConnection>(ResyncCallback, ISurfaceComposer::ConfigChanged));
+ sp<EventThreadConnection>(ResyncCallback,
+ ISurfaceComposer::EventRegistrationFlags));
MOCK_METHOD0(onScreenReleased, void());
MOCK_METHOD0(onScreenAcquired, void());
MOCK_METHOD2(onHotplugReceived, void(PhysicalDisplayId, bool));
MOCK_METHOD3(onConfigChanged, void(PhysicalDisplayId, HwcConfigIndexType, nsecs_t));
+ MOCK_METHOD2(onFrameRateOverridesChanged,
+ void(PhysicalDisplayId, std::vector<FrameRateOverride>));
MOCK_CONST_METHOD1(dump, void(std::string&));
MOCK_METHOD2(setDuration,
void(std::chrono::nanoseconds workDuration,