diff options
author | 2020-10-13 19:07:23 -0700 | |
---|---|---|
committer | 2020-11-18 13:30:27 -0800 | |
commit | 62f216c62edbe4c997e959cfb28c8609664978df (patch) | |
tree | a5f22b610a460033ef656e58df3f3575ffa69d85 | |
parent | 939739b86288069814cf73b37133119983779278 (diff) |
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
29 files changed, 330 insertions, 145 deletions
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg index 560459be13..a8c0500683 100644 --- a/PREUPLOAD.cfg +++ b/PREUPLOAD.cfg @@ -14,6 +14,7 @@ clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp 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 a0e9cbf2eb..af9ef06b86 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -237,6 +237,10 @@ cc_defaults { "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 abfee61685..c6c9a8f7a7 100644 --- a/libs/gui/DisplayEventDispatcher.cpp +++ b/libs/gui/DisplayEventDispatcher.cpp @@ -33,10 +33,10 @@ namespace android { // 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 @@ bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, 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 @@ bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, 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 f2b0962eb7..03b33c7330 100644 --- a/libs/gui/DisplayEventReceiver.cpp +++ b/libs/gui/DisplayEventReceiver.cpp @@ -32,11 +32,12 @@ namespace android { // --------------------------------------------------------------------------- -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 a9fe5bf319..e46a415f8c 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -223,8 +223,8 @@ public: 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 @@ public: 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 @@ status_t BnSurfaceComposer::onTransact( 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 c65618b31f..5587acf08f 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 @@ public: 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 @@ private: 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 @@ private: // 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 df3118ff6d..3191fc9ab5 100644 --- a/libs/gui/include/gui/DisplayEventReceiver.h +++ b/libs/gui/include/gui/DisplayEventReceiver.h @@ -54,6 +54,8 @@ public: 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 @@ public: 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 @@ public: * 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 9e96b79b8c..86e3a25f5a 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 @@ public: 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 @@ public: /* 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 72109109c4..c5093e2d88 100644 --- a/libs/gui/tests/DisplayEventStructLayout_test.cpp +++ b/libs/gui/tests/DisplayEventStructLayout_test.cpp @@ -40,6 +40,9 @@ TEST(DisplayEventStructLayoutTest, TestEventAlignment) { 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 2392ae5ccd..ce3afa2710 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -687,7 +687,7 @@ public: 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 9e515cdc80..6d91916978 100644 --- a/libs/nativedisplay/AChoreographer.cpp +++ b/libs/nativedisplay/AChoreographer.cpp @@ -141,6 +141,8 @@ private: 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::getForThread() { } 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 @@ void Choreographer::dispatchHotplug(nsecs_t, PhysicalDisplayId displayId, bool c 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 bf5be4790d..b63e8c835b 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 @@ DisplayEventReceiver::Event makeConfigChanged(PhysicalDisplayId displayId, 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 @@ void EventThreadConnection::requestNextVsync() { } 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 @@ void EventThread::setDuration(std::chrono::nanoseconds workDuration, } 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 @@ void EventThread::onConfigChanged(PhysicalDisplayId displayId, HwcConfigIndexTyp 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 @@ bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event, 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 @@ bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event, 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 2e2d98950e..e75b7189da 100644 --- a/services/surfaceflinger/Scheduler/EventThread.h +++ b/services/surfaceflinger/Scheduler/EventThread.h @@ -48,6 +48,7 @@ class TokenManager; // --------------------------------------------------------------------------- using ResyncCallback = std::function<void()>; +using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride; enum class VSyncRequest { None = -2, @@ -82,7 +83,7 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: ~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 @@ public: 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 b872d7a4dd..8b4283cd65 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -687,21 +687,20 @@ RefreshRateConfigs::KernelIdleTimerAction RefreshRateConfigs::getIdleTimerAction 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 @@ int RefreshRateConfigs::getRefreshRateDividerForUid(uid_t uid) const { 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 @@ int RefreshRateConfigs::getRefreshRateDividerForUid(uid_t uid) const { 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 3159352db9..a8737778d3 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 @@ inline RefreshRateConfigEvent operator|(RefreshRateConfigEvent lhs, RefreshRateC 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 @@ public: 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 @@ private: 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 a14019eeb5..a93bf11301 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -239,8 +239,7 @@ Scheduler::ConnectionHandle Scheduler::createConnection(std::unique_ptr<EventThr 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 @@ Scheduler::ConnectionHandle Scheduler::createConnection(std::unique_ptr<EventThr } 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 @@ void Scheduler::onScreenReleased(ConnectionHandle handle) { 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 4c86d26a01..76e8f57adc 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -79,8 +79,8 @@ public: 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 @@ public: 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 @@ private: // 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 91f050c017..eed6aa4a07 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1527,11 +1527,12 @@ status_t SurfaceFlinger::notifyPowerBoost(int32_t boostId) { // ---------------------------------------------------------------------------- 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 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r 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 9666f145b0..a909ad81c0 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -530,8 +530,7 @@ private: 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 0a70f5c504..31a51268e6 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -240,8 +240,9 @@ protected: 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 091171266f..be9d336137 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -133,17 +133,13 @@ public: 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 f0311bdaab..90692003ef 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -70,15 +70,13 @@ DisplayTransactionTest::~DisplayTransactionTest() { 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 3aafd456d9..ee56178169 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 @@ protected: 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 @@ protected: ~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 @@ protected: 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 @@ EventThreadTest::EventThreadTest() { 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 @@ void EventThreadTest::createThread(std::unique_ptr<VSyncSource> source) { } 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 @@ void EventThreadTest::expectConfigChangedEventReceivedByConnection( 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, requestNextVsyncPostsASingleVSyncEventToTheConnection) { 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 @@ TEST_F(EventThreadTest, setVsyncRateZeroPostsNoVSyncEventsToThatConnection) { // 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, connectionsRemovedIfInstanceDestroyed) { 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, connectionsRemovedIfEventDeliveryError) { 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, tracksEventConnections) { 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, postConfigChangedPrimary64bit) { 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 @@ TEST_F(EventThreadTest, suppressConfigChanged) { 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 df7611043a..2fbc72a01a 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -1601,7 +1601,7 @@ TEST_F(RefreshRateConfigsTest, RefreshRateDividerForUid) { 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 @@ TEST_F(RefreshRateConfigsTest, RefreshRateDividerForUid) { 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 8cd8372626..c5deb7ca07 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp @@ -132,14 +132,12 @@ void RefreshRateSelectionTest::setupScheduler() { 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 509858a4ab..647689b46c 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp @@ -42,8 +42,7 @@ protected: 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 @@ SchedulerTest::SchedulerTest() { 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, invalidConnectionHandle) { 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 e25d501fe3..5278641e5b 100644 --- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp +++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp @@ -172,14 +172,12 @@ void SetFrameRateTest::setupScheduler() { 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 68cf330b9c..c36d9947b7 100644 --- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp @@ -65,17 +65,13 @@ public: 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 b4594c183d..650d52d88a 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h +++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h @@ -28,11 +28,14 @@ public: ~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, |