From 214c89db99f280cd67ca14357c9ee11adce0acce Mon Sep 17 00:00:00 2001 From: chaviw Date: Wed, 4 Sep 2019 16:03:53 -0700 Subject: Remove setGeometryAppliesWithResize This function is no longer used so removing the API and any logic implemented for it. Test: go/wm-smoke Change-Id: I4ae2128cd38e818fcd16dafa4ce47c9411bd61c9 --- services/surfaceflinger/RefreshRateOverlay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 5b4bec96ea..976fedb58a 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -39,7 +39,7 @@ bool RefreshRateOverlay::createLayer() { Mutex::Autolock _l(mFlinger.mStateLock); mLayer = mClient->getLayerUser(mIBinder); - mLayer->setCrop_legacy(Rect(50, 70, 200, 100), true); + mLayer->setCrop_legacy(Rect(50, 70, 200, 100)); // setting Layer's Z requires resorting layersSortedByZ ssize_t idx = mFlinger.mCurrentState.layersSortedByZ.indexOf(mLayer); -- cgit v1.2.3-59-g8ed1b From 2139f73d98f3f0d31f0f90bcca7f4537c66e5e70 Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Wed, 13 Nov 2019 18:56:40 -0800 Subject: SurfaceFlinger: use config groups Composer 2.4 adds a new attribute for configs groups. This change groups configs according to their group and store them in RefreshRateConfigs. Test: rev up composer to 2.4 and test refresh rate switching Test: adb shell /data/nativetest64/libsurfaceflinger_unittest/libsurfaceflinger_unittest Test: adb shell /data/nativetest64/SurfaceFlinger_test/SurfaceFlinger_test Bug: 141329414 Fixes: 139751853 Change-Id: Ic0bcd3da4bf6b73efa11a60c2594948ce030362f --- services/surfaceflinger/BufferQueueLayer.cpp | 3 +- services/surfaceflinger/BufferStateLayer.cpp | 3 +- services/surfaceflinger/DisplayDevice.cpp | 6 +- services/surfaceflinger/DisplayDevice.h | 7 +- services/surfaceflinger/RefreshRateOverlay.cpp | 6 +- services/surfaceflinger/RefreshRateOverlay.h | 4 +- services/surfaceflinger/Scheduler/EventThread.cpp | 8 +- services/surfaceflinger/Scheduler/EventThread.h | 5 +- services/surfaceflinger/Scheduler/HwcStrongTypes.h | 27 +++ services/surfaceflinger/Scheduler/LayerHistory.cpp | 11 +- services/surfaceflinger/Scheduler/LayerHistory.h | 3 +- services/surfaceflinger/Scheduler/LayerInfo.h | 4 - services/surfaceflinger/Scheduler/PhaseOffsets.cpp | 30 +-- services/surfaceflinger/Scheduler/PhaseOffsets.h | 20 +- .../Scheduler/RefreshRateConfigs.cpp | 208 ++++++++++++--------- .../surfaceflinger/Scheduler/RefreshRateConfigs.h | 134 +++++++++---- .../surfaceflinger/Scheduler/RefreshRateStats.h | 29 ++- services/surfaceflinger/Scheduler/Scheduler.cpp | 121 +++++------- services/surfaceflinger/Scheduler/Scheduler.h | 34 ++-- services/surfaceflinger/Scheduler/StrongTyping.h | 20 +- services/surfaceflinger/Scheduler/VSyncDispatch.h | 2 +- .../Scheduler/VSyncDispatchTimerQueue.h | 3 +- .../surfaceflinger/Scheduler/VSyncModulator.cpp | 11 +- services/surfaceflinger/Scheduler/VSyncModulator.h | 3 - services/surfaceflinger/SurfaceFlinger.cpp | 160 +++++++++------- services/surfaceflinger/SurfaceFlinger.h | 21 ++- .../tests/unittests/DisplayTransactionTest.cpp | 2 +- .../tests/unittests/EventThreadTest.cpp | 10 +- .../tests/unittests/FakePhaseOffsets.h | 10 +- .../tests/unittests/LayerHistoryTest.cpp | 44 ++--- .../tests/unittests/RefreshRateConfigsTest.cpp | 195 +++++++++++++++---- .../tests/unittests/RefreshRateStatsTest.cpp | 29 +-- .../tests/unittests/SchedulerTest.cpp | 9 +- .../tests/unittests/StrongTypingTest.cpp | 14 +- .../tests/unittests/TestableSurfaceFlinger.h | 25 +-- .../tests/unittests/mock/MockEventThread.h | 2 +- 36 files changed, 735 insertions(+), 488 deletions(-) create mode 100644 services/surfaceflinger/Scheduler/HwcStrongTypes.h (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index d51d34b3c5..8957e90034 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -399,8 +399,7 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { // Add this buffer from our internal queue tracker { // Autolock scope const nsecs_t presentTime = item.mIsAutoTimestamp ? 0 : item.mTimestamp; - const bool isHDR = item.mHdrMetadata.validTypes != 0; - mFlinger->mScheduler->recordLayerHistory(this, presentTime, isHDR); + mFlinger->mScheduler->recordLayerHistory(this, presentTime); Mutex::Autolock lock(mQueueItemLock); // Reset the frame number tracker when we receive the first buffer after diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index d68fe8e3a5..1e471e53ff 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -247,8 +247,7 @@ bool BufferStateLayer::setBuffer(const sp& buffer, nsecs_t postTi FrameTracer::FrameEvent::POST); mCurrentState.desiredPresentTime = desiredPresentTime; - const bool isHDR = mCurrentState.hdrMetadata.validTypes != 0; - mFlinger->mScheduler->recordLayerHistory(this, desiredPresentTime, isHDR); + mFlinger->mScheduler->recordLayerHistory(this, desiredPresentTime); return true; } diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 89123df46c..84ec597d2f 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -132,11 +132,11 @@ bool DisplayDevice::isPoweredOn() const { } // ---------------------------------------------------------------------------- -void DisplayDevice::setActiveConfig(int mode) { +void DisplayDevice::setActiveConfig(HwcConfigIndexType mode) { mActiveConfig = mode; } -int DisplayDevice::getActiveConfig() const { +HwcConfigIndexType DisplayDevice::getActiveConfig() const { return mActiveConfig; } @@ -285,7 +285,7 @@ void DisplayDevice::dump(std::string& result) const { result.append(" "); StringAppendF(&result, "powerMode=%d, ", mPowerMode); - StringAppendF(&result, "activeConfig=%d, ", mActiveConfig); + StringAppendF(&result, "activeConfig=%d, ", mActiveConfig.value()); getCompositionDisplay()->dump(result); } diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index ce4e1e6b09..2d0875b0c5 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -43,6 +43,7 @@ #include "DisplayHardware/DisplayIdentification.h" #include "DisplayHardware/PowerAdvisor.h" #include "RenderArea.h" +#include "Scheduler/HwcStrongTypes.h" namespace android { @@ -141,8 +142,8 @@ public: /* ------------------------------------------------------------------------ * Display active config management. */ - int getActiveConfig() const; - void setActiveConfig(int mode); + HwcConfigIndexType getActiveConfig() const; + void setActiveConfig(HwcConfigIndexType mode); // release HWC resources (if any) for removable displays void disconnect(); @@ -186,7 +187,7 @@ private: // Current power mode int mPowerMode; // Current active config - int mActiveConfig; + HwcConfigIndexType mActiveConfig; // TODO(b/74619554): Remove special cases for primary display. const bool mIsPrimary; diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 976fedb58a..38a80a798a 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -20,8 +20,6 @@ namespace android { -using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType; - RefreshRateOverlay::RefreshRateOverlay(SurfaceFlinger& flinger) : mFlinger(flinger), mClient(new Client(&mFlinger)) { createLayer(); @@ -51,8 +49,8 @@ bool RefreshRateOverlay::createLayer() { return true; } -void RefreshRateOverlay::changeRefreshRate(RefreshRateType type) { - const half3& color = (type == RefreshRateType::PERFORMANCE) ? GREEN : RED; +void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { + const half3& color = (refreshRate.fps > 65.0f) ? GREEN : RED; mLayer->setColor(color); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } diff --git a/services/surfaceflinger/RefreshRateOverlay.h b/services/surfaceflinger/RefreshRateOverlay.h index ce29bc3243..414bc47ac9 100644 --- a/services/surfaceflinger/RefreshRateOverlay.h +++ b/services/surfaceflinger/RefreshRateOverlay.h @@ -19,13 +19,13 @@ namespace android { -using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType; +using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate; class RefreshRateOverlay { public: RefreshRateOverlay(SurfaceFlinger& flinger); - void changeRefreshRate(RefreshRateType type); + void changeRefreshRate(const RefreshRate& refreshRate); private: bool createLayer(); diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp index 8d9adc8525..ff800c3dbf 100644 --- a/services/surfaceflinger/Scheduler/EventThread.cpp +++ b/services/surfaceflinger/Scheduler/EventThread.cpp @@ -36,6 +36,7 @@ #include #include "EventThread.h" +#include "HwcStrongTypes.h" using namespace std::chrono_literals; @@ -101,10 +102,11 @@ DisplayEventReceiver::Event makeVSync(PhysicalDisplayId displayId, nsecs_t times return event; } -DisplayEventReceiver::Event makeConfigChanged(PhysicalDisplayId displayId, int32_t configId) { +DisplayEventReceiver::Event makeConfigChanged(PhysicalDisplayId displayId, + HwcConfigIndexType configId) { DisplayEventReceiver::Event event; event.header = {DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED, displayId, systemTime()}; - event.config.configId = configId; + event.config.configId = configId.value(); return event; } @@ -290,7 +292,7 @@ void EventThread::onHotplugReceived(PhysicalDisplayId displayId, bool connected) mCondition.notify_all(); } -void EventThread::onConfigChanged(PhysicalDisplayId displayId, int32_t configId) { +void EventThread::onConfigChanged(PhysicalDisplayId displayId, HwcConfigIndexType configId) { std::lock_guard lock(mMutex); mPendingEvents.push_back(makeConfigChanged(displayId, configId)); diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h index a029586088..a42546c7df 100644 --- a/services/surfaceflinger/Scheduler/EventThread.h +++ b/services/surfaceflinger/Scheduler/EventThread.h @@ -33,6 +33,7 @@ #include #include +#include "HwcStrongTypes.h" // --------------------------------------------------------------------------- namespace android { @@ -109,7 +110,7 @@ public: virtual void onHotplugReceived(PhysicalDisplayId displayId, bool connected) = 0; // called when SF changes the active config and apps needs to be notified about the change - virtual void onConfigChanged(PhysicalDisplayId displayId, int32_t configId) = 0; + virtual void onConfigChanged(PhysicalDisplayId displayId, HwcConfigIndexType configId) = 0; virtual void dump(std::string& result) const = 0; @@ -146,7 +147,7 @@ public: void onHotplugReceived(PhysicalDisplayId displayId, bool connected) override; - void onConfigChanged(PhysicalDisplayId displayId, int32_t configId) override; + void onConfigChanged(PhysicalDisplayId displayId, HwcConfigIndexType configId) override; void dump(std::string& result) const override; diff --git a/services/surfaceflinger/Scheduler/HwcStrongTypes.h b/services/surfaceflinger/Scheduler/HwcStrongTypes.h new file mode 100644 index 0000000000..cfbbdfe4fd --- /dev/null +++ b/services/surfaceflinger/Scheduler/HwcStrongTypes.h @@ -0,0 +1,27 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "StrongTyping.h" + +namespace android { + +// Strong types for the different indexes as they are referring to a different base. +using HwcConfigIndexType = StrongTyping; +using HwcConfigGroupType = StrongTyping; + +} // namespace android \ No newline at end of file diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index 8b717289c6..146ec1bce0 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -39,7 +39,7 @@ namespace android::scheduler { namespace { bool isLayerActive(const Layer& layer, const LayerInfo& info, nsecs_t threshold) { - return layer.isVisible() && (info.isHDR() || info.getLastUpdatedTime() >= threshold); + return layer.isVisible() && info.getLastUpdatedTime() >= threshold; } bool traceEnabled() { @@ -69,7 +69,7 @@ void LayerHistory::registerLayer(Layer* layer, float lowRefreshRate, float highR mLayerInfos.emplace_back(layer, std::move(info)); } -void LayerHistory::record(Layer* layer, nsecs_t presentTime, bool isHDR, nsecs_t now) { +void LayerHistory::record(Layer* layer, nsecs_t presentTime, nsecs_t now) { std::lock_guard lock(mLock); const auto it = std::find_if(mLayerInfos.begin(), mLayerInfos.end(), @@ -78,7 +78,6 @@ void LayerHistory::record(Layer* layer, nsecs_t presentTime, bool isHDR, nsecs_t const auto& info = it->second; info->setLastPresentTime(presentTime, now); - info->setIsHDR(isHDR); // Activate layer if inactive. if (const auto end = activeLayers().end(); it >= end) { @@ -89,7 +88,6 @@ void LayerHistory::record(Layer* layer, nsecs_t presentTime, bool isHDR, nsecs_t LayerHistory::Summary LayerHistory::summarize(nsecs_t now) { float maxRefreshRate = 0; - bool isHDR = false; std::lock_guard lock(mLock); @@ -108,13 +106,12 @@ LayerHistory::Summary LayerHistory::summarize(nsecs_t now) { trace(layer, std::round(refreshRate)); } } - isHDR |= info->isHDR(); } if (CC_UNLIKELY(mTraceEnabled)) { - ALOGD("%s: maxRefreshRate=%.2f, isHDR=%d", __FUNCTION__, maxRefreshRate, isHDR); + ALOGD("%s: maxRefreshRate=%.2f", __FUNCTION__, maxRefreshRate); } - return {maxRefreshRate, isHDR}; + return {maxRefreshRate}; } void LayerHistory::partitionLayers(nsecs_t now) { diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h index bd9aca1aed..745c4c16ee 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.h +++ b/services/surfaceflinger/Scheduler/LayerHistory.h @@ -46,11 +46,10 @@ public: void registerLayer(Layer*, float lowRefreshRate, float highRefreshRate); // Marks the layer as active, and records the given state to its history. - void record(Layer*, nsecs_t presentTime, bool isHDR, nsecs_t now); + void record(Layer*, nsecs_t presentTime, nsecs_t now); struct Summary { float maxRefreshRate; // Maximum refresh rate among recently active layers. - bool isHDR; // True if any recently active layer has HDR content. }; // Rebuilds sets of active/inactive layers, and accumulates stats for active layers. diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h index b86709fc9c..cb81ca2840 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.h +++ b/services/surfaceflinger/Scheduler/LayerInfo.h @@ -140,9 +140,6 @@ public: // updated time, the updated time is the present time. void setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now); - bool isHDR() const { return mIsHDR; } - void setIsHDR(bool isHDR) { mIsHDR = isHDR; } - bool isRecentlyActive(nsecs_t now) const { return mPresentTimeHistory.isRecentlyActive(now); } bool isFrequent(nsecs_t now) const { return mPresentTimeHistory.isFrequent(now); } @@ -167,7 +164,6 @@ private: nsecs_t mLastPresentTime = 0; RefreshRateHistory mRefreshRateHistory{mHighRefreshRate}; PresentTimeHistory mPresentTimeHistory; - bool mIsHDR = false; }; } // namespace scheduler diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp index 6be88f89f9..12832a690a 100644 --- a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp +++ b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp @@ -48,16 +48,18 @@ PhaseOffsets::PhaseOffsets() { getProperty("debug.sf.phase_offset_threshold_for_next_vsync_ns") .value_or(std::numeric_limits::max()); - const Offsets defaultOffsets = getDefaultOffsets(thresholdForNextVsync); - const Offsets highFpsOffsets = getHighFpsOffsets(thresholdForNextVsync); - - mOffsets.insert({RefreshRateType::DEFAULT, defaultOffsets}); - mOffsets.insert({RefreshRateType::PERFORMANCE, highFpsOffsets}); + mDefaultOffsets = getDefaultOffsets(thresholdForNextVsync); + mHighFpsOffsets = getHighFpsOffsets(thresholdForNextVsync); } -PhaseOffsets::Offsets PhaseOffsets::getOffsetsForRefreshRate( - RefreshRateType refreshRateType) const { - return mOffsets.at(refreshRateType); +PhaseOffsets::Offsets PhaseOffsets::getOffsetsForRefreshRate(float fps) const { + // TODO(145561086): Once offsets are common for all refresh rates we can remove the magic + // number for refresh rate + if (fps > 65.0f) { + return mHighFpsOffsets; + } else { + return mDefaultOffsets; + } } void PhaseOffsets::dump(std::string& result) const { @@ -80,13 +82,13 @@ PhaseOffsets::Offsets PhaseOffsets::getDefaultOffsets(nsecs_t thresholdForNextVs const auto earlyAppOffsetNs = getProperty("debug.sf.early_app_phase_offset_ns"); const auto earlyGlAppOffsetNs = getProperty("debug.sf.early_gl_app_phase_offset_ns"); - return {{RefreshRateType::DEFAULT, earlySfOffsetNs.value_or(sfVsyncPhaseOffsetNs), + return {{earlySfOffsetNs.value_or(sfVsyncPhaseOffsetNs), earlyAppOffsetNs.value_or(vsyncPhaseOffsetNs)}, - {RefreshRateType::DEFAULT, earlyGlSfOffsetNs.value_or(sfVsyncPhaseOffsetNs), + {earlyGlSfOffsetNs.value_or(sfVsyncPhaseOffsetNs), earlyGlAppOffsetNs.value_or(vsyncPhaseOffsetNs)}, - {RefreshRateType::DEFAULT, sfVsyncPhaseOffsetNs, vsyncPhaseOffsetNs}, + {sfVsyncPhaseOffsetNs, vsyncPhaseOffsetNs}, thresholdForNextVsync}; } @@ -104,13 +106,13 @@ PhaseOffsets::Offsets PhaseOffsets::getHighFpsOffsets(nsecs_t thresholdForNextVs const auto highFpsEarlyGlAppOffsetNs = getProperty("debug.sf.high_fps_early_gl_app_phase_offset_ns"); - return {{RefreshRateType::PERFORMANCE, highFpsEarlySfOffsetNs.value_or(highFpsLateSfOffsetNs), + return {{highFpsEarlySfOffsetNs.value_or(highFpsLateSfOffsetNs), highFpsEarlyAppOffsetNs.value_or(highFpsLateAppOffsetNs)}, - {RefreshRateType::PERFORMANCE, highFpsEarlyGlSfOffsetNs.value_or(highFpsLateSfOffsetNs), + {highFpsEarlyGlSfOffsetNs.value_or(highFpsLateSfOffsetNs), highFpsEarlyGlAppOffsetNs.value_or(highFpsLateAppOffsetNs)}, - {RefreshRateType::PERFORMANCE, highFpsLateSfOffsetNs, highFpsLateAppOffsetNs}, + {highFpsLateSfOffsetNs, highFpsLateAppOffsetNs}, thresholdForNextVsync}; } diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.h b/services/surfaceflinger/Scheduler/PhaseOffsets.h index 2c52432448..7747f0cfcc 100644 --- a/services/surfaceflinger/Scheduler/PhaseOffsets.h +++ b/services/surfaceflinger/Scheduler/PhaseOffsets.h @@ -32,7 +32,6 @@ namespace android::scheduler { class PhaseOffsets { public: using Offsets = VSyncModulator::OffsetsConfig; - using RefreshRateType = RefreshRateConfigs::RefreshRateType; virtual ~PhaseOffsets(); @@ -43,9 +42,9 @@ public: } virtual Offsets getCurrentOffsets() const = 0; - virtual Offsets getOffsetsForRefreshRate(RefreshRateType) const = 0; + virtual Offsets getOffsetsForRefreshRate(float fps) const = 0; - virtual void setRefreshRateType(RefreshRateType) = 0; + virtual void setRefreshRateFps(float fps) = 0; virtual void dump(std::string& result) const = 0; }; @@ -57,18 +56,14 @@ public: PhaseOffsets(); // Returns early, early GL, and late offsets for Apps and SF for a given refresh rate. - Offsets getOffsetsForRefreshRate(RefreshRateType) const override; + Offsets getOffsetsForRefreshRate(float fps) const override; // Returns early, early GL, and late offsets for Apps and SF. - Offsets getCurrentOffsets() const override { - return getOffsetsForRefreshRate(mRefreshRateType); - } + Offsets getCurrentOffsets() const override { return getOffsetsForRefreshRate(mRefreshRateFps); } // This function should be called when the device is switching between different // refresh rates, to properly update the offsets. - void setRefreshRateType(RefreshRateType refreshRateType) override { - mRefreshRateType = refreshRateType; - } + void setRefreshRateFps(float fps) override { mRefreshRateFps = fps; } // Returns current offsets in human friendly format. void dump(std::string& result) const override; @@ -77,9 +72,10 @@ private: static Offsets getDefaultOffsets(nsecs_t thresholdForNextVsync); static Offsets getHighFpsOffsets(nsecs_t thresholdForNextVsync); - std::atomic mRefreshRateType = RefreshRateType::DEFAULT; + std::atomic mRefreshRateFps = 0; - std::unordered_map mOffsets; + Offsets mDefaultOffsets; + Offsets mHighFpsOffsets; }; } // namespace impl diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index 7dc98cce94..23fb96a38b 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -13,135 +13,169 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +// #define LOG_NDEBUG 0 #include "RefreshRateConfigs.h" namespace android::scheduler { + +using AllRefreshRatesMapType = RefreshRateConfigs::AllRefreshRatesMapType; using RefreshRate = RefreshRateConfigs::RefreshRate; -using RefreshRateType = RefreshRateConfigs::RefreshRateType; // Returns the refresh rate map. This map won't be modified at runtime, so it's safe to access // from multiple threads. This can only be called if refreshRateSwitching() returns true. // TODO(b/122916473): Get this information from configs prepared by vendors, instead of // baking them in. -const std::map& RefreshRateConfigs::getRefreshRateMap() const { - LOG_ALWAYS_FATAL_IF(!mRefreshRateSwitchingSupported); - return mRefreshRateMap; -} - -const RefreshRate& RefreshRateConfigs::getRefreshRateFromType(RefreshRateType type) const { - if (!mRefreshRateSwitchingSupported) { - return getCurrentRefreshRate().second; - } else { - auto refreshRate = mRefreshRateMap.find(type); - LOG_ALWAYS_FATAL_IF(refreshRate == mRefreshRateMap.end()); - return refreshRate->second; - } -} - -std::pair RefreshRateConfigs::getCurrentRefreshRate() const { - int currentConfig = mCurrentConfig; - if (mRefreshRateSwitchingSupported) { - for (const auto& [type, refresh] : mRefreshRateMap) { - if (refresh.configId == currentConfig) { - return {type, refresh}; +const RefreshRate& RefreshRateConfigs::getRefreshRateForContent(float contentFramerate) const { + std::lock_guard lock(mLock); + // Find the appropriate refresh rate with minimal error + auto iter = min_element(mAvailableRefreshRates.cbegin(), mAvailableRefreshRates.cend(), + [contentFramerate](const auto& lhs, const auto& rhs) -> bool { + return std::abs(lhs->fps - contentFramerate) < + std::abs(rhs->fps - contentFramerate); + }); + + // Some content aligns better on higher refresh rate. For example for 45fps we should choose + // 90Hz config. However we should still prefer a lower refresh rate if the content doesn't + // align well with both + const RefreshRate* bestSoFar = *iter; + constexpr float MARGIN = 0.05f; + float ratio = (*iter)->fps / contentFramerate; + if (std::abs(std::round(ratio) - ratio) > MARGIN) { + while (iter != mAvailableRefreshRates.cend()) { + ratio = (*iter)->fps / contentFramerate; + + if (std::abs(std::round(ratio) - ratio) <= MARGIN) { + bestSoFar = *iter; + break; } + ++iter; } - LOG_ALWAYS_FATAL(); } - return {RefreshRateType::DEFAULT, mRefreshRates[currentConfig]}; + + return *bestSoFar; } -const RefreshRate& RefreshRateConfigs::getRefreshRateFromConfigId(int configId) const { - LOG_ALWAYS_FATAL_IF(configId >= mRefreshRates.size()); - return mRefreshRates[configId]; +const AllRefreshRatesMapType& RefreshRateConfigs::getAllRefreshRates() const { + return mRefreshRates; } -RefreshRateType RefreshRateConfigs::getRefreshRateTypeFromHwcConfigId(hwc2_config_t hwcId) const { - if (!mRefreshRateSwitchingSupported) return RefreshRateType::DEFAULT; +const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicy() const { + std::lock_guard lock(mLock); + if (!mRefreshRateSwitching) { + return *mCurrentRefreshRate; + } else { + return *mAvailableRefreshRates.front(); + } +} - for (const auto& [type, refreshRate] : mRefreshRateMap) { - if (refreshRate.hwcId == hwcId) { - return type; - } +const RefreshRate& RefreshRateConfigs::getMaxRefreshRateByPolicy() const { + std::lock_guard lock(mLock); + if (!mRefreshRateSwitching) { + return *mCurrentRefreshRate; + } else { + return *mAvailableRefreshRates.back(); } +} - return RefreshRateType::DEFAULT; +const RefreshRate& RefreshRateConfigs::getCurrentRefreshRate() const { + std::lock_guard lock(mLock); + return *mCurrentRefreshRate; } -void RefreshRateConfigs::setCurrentConfig(int config) { - LOG_ALWAYS_FATAL_IF(config >= mRefreshRates.size()); - mCurrentConfig = config; +void RefreshRateConfigs::setCurrentConfigId(HwcConfigIndexType configId) { + std::lock_guard lock(mLock); + mCurrentRefreshRate = &mRefreshRates.at(configId); } RefreshRateConfigs::RefreshRateConfigs(bool refreshRateSwitching, - const std::vector& configs, int currentConfig) { - init(refreshRateSwitching, configs, currentConfig); + const std::vector& configs, + HwcConfigIndexType currentHwcConfig) + : mRefreshRateSwitching(refreshRateSwitching) { + init(configs, currentHwcConfig); } RefreshRateConfigs::RefreshRateConfigs( bool refreshRateSwitching, const std::vector>& configs, - int currentConfig) { + HwcConfigIndexType currentConfigId) + : mRefreshRateSwitching(refreshRateSwitching) { std::vector inputConfigs; - for (const auto& config : configs) { - inputConfigs.push_back({config->getId(), config->getVsyncPeriod()}); + for (auto configId = HwcConfigIndexType(0); configId < HwcConfigIndexType(configs.size()); + ++configId) { + auto configGroup = HwcConfigGroupType(configs[configId.value()]->getConfigGroup()); + inputConfigs.push_back( + {configId, configGroup, configs[configId.value()]->getVsyncPeriod()}); } - init(refreshRateSwitching, inputConfigs, currentConfig); + init(inputConfigs, currentConfigId); } -void RefreshRateConfigs::init(bool refreshRateSwitching, const std::vector& configs, - int currentConfig) { - mRefreshRateSwitchingSupported = refreshRateSwitching; - LOG_ALWAYS_FATAL_IF(configs.empty()); - LOG_ALWAYS_FATAL_IF(currentConfig >= configs.size()); - mCurrentConfig = currentConfig; - - auto buildRefreshRate = [&](int configId) -> RefreshRate { - const nsecs_t vsyncPeriod = configs[configId].vsyncPeriod; - const float fps = 1e9 / vsyncPeriod; - return {configId, base::StringPrintf("%2.ffps", fps), static_cast(fps), - vsyncPeriod, configs[configId].hwcId}; - }; +void RefreshRateConfigs::setPolicy(HwcConfigIndexType defaultConfigId, float minRefreshRate, + float maxRefreshRate) { + std::lock_guard lock(mLock); + mCurrentGroupId = mRefreshRates.at(defaultConfigId).configGroup; + mMinRefreshRateFps = minRefreshRate; + mMaxRefreshRateFps = maxRefreshRate; + constructAvailableRefreshRates(); +} - for (int i = 0; i < configs.size(); ++i) { - mRefreshRates.push_back(buildRefreshRate(i)); +void RefreshRateConfigs::getSortedRefreshRateList( + const std::function& shouldAddRefreshRate, + std::vector* outRefreshRates) { + outRefreshRates->clear(); + outRefreshRates->reserve(mRefreshRates.size()); + for (const auto& [type, refreshRate] : mRefreshRates) { + if (shouldAddRefreshRate(refreshRate)) { + ALOGV("getSortedRefreshRateList: config %d added to list policy", + refreshRate.configId.value()); + outRefreshRates->push_back(&refreshRate); + } } - if (!mRefreshRateSwitchingSupported) return; + std::sort(outRefreshRates->begin(), outRefreshRates->end(), + [](const auto refreshRate1, const auto refreshRate2) { + return refreshRate1->vsyncPeriod > refreshRate2->vsyncPeriod; + }); +} - auto findDefaultAndPerfConfigs = [&]() -> std::optional> { - if (configs.size() < 2) { - return {}; - } +void RefreshRateConfigs::constructAvailableRefreshRates() { + // Filter configs based on current policy and sort based on vsync period + ALOGV("constructRefreshRateMap: group %d min %.2f max %.2f", mCurrentGroupId.value(), + mMinRefreshRateFps, mMaxRefreshRateFps); + getSortedRefreshRateList( + [this](const RefreshRate& refreshRate) REQUIRES(mLock) { + return refreshRate.configGroup == mCurrentGroupId && + refreshRate.fps >= mMinRefreshRateFps && + refreshRate.fps <= mMaxRefreshRateFps; + }, + &mAvailableRefreshRates); +} - std::vector sortedRefreshRates; - for (const auto& refreshRate : mRefreshRates) { - sortedRefreshRates.push_back(&refreshRate); - } - std::sort(sortedRefreshRates.begin(), sortedRefreshRates.end(), - [](const RefreshRate* refreshRate1, const RefreshRate* refreshRate2) { - return refreshRate1->vsyncPeriod > refreshRate2->vsyncPeriod; - }); - - // When the configs are ordered by the resync rate, we assume that - // the first one is DEFAULT and the second one is PERFORMANCE, - // i.e. the higher rate. - if (sortedRefreshRates[0]->vsyncPeriod == 0 || sortedRefreshRates[1]->vsyncPeriod == 0) { - return {}; - } +// NO_THREAD_SAFETY_ANALYSIS since this is called from the constructor +void RefreshRateConfigs::init(const std::vector& configs, + HwcConfigIndexType currentHwcConfig) NO_THREAD_SAFETY_ANALYSIS { + LOG_ALWAYS_FATAL_IF(configs.empty()); + LOG_ALWAYS_FATAL_IF(currentHwcConfig.value() >= configs.size()); - return std::pair(sortedRefreshRates[0]->configId, - sortedRefreshRates[1]->configId); + auto buildRefreshRate = [&](InputConfig config) -> RefreshRate { + const float fps = 1e9f / config.vsyncPeriod; + return RefreshRate(config.configId, config.vsyncPeriod, config.configGroup, + base::StringPrintf("%2.ffps", fps), fps); }; - auto defaultAndPerfConfigs = findDefaultAndPerfConfigs(); - if (!defaultAndPerfConfigs) { - mRefreshRateSwitchingSupported = false; - return; + for (const auto& config : configs) { + mRefreshRates.emplace(config.configId, buildRefreshRate(config)); + if (config.configId == currentHwcConfig) { + mCurrentRefreshRate = &mRefreshRates.at(config.configId); + mCurrentGroupId = config.configGroup; + } } - mRefreshRateMap[RefreshRateType::DEFAULT] = mRefreshRates[defaultAndPerfConfigs->first]; - mRefreshRateMap[RefreshRateType::PERFORMANCE] = mRefreshRates[defaultAndPerfConfigs->second]; + std::vector sortedConfigs; + getSortedRefreshRateList([](const RefreshRate&) { return true; }, &sortedConfigs); + mMinSupportedRefreshRate = sortedConfigs.front(); + mMaxSupportedRefreshRate = sortedConfigs.back(); + constructAvailableRefreshRates(); } -} // namespace android::scheduler \ No newline at end of file +} // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index 90bba24332..fb14dc7a9a 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -23,7 +23,9 @@ #include #include "DisplayHardware/HWComposer.h" +#include "HwcStrongTypes.h" #include "Scheduler/SchedulerUtils.h" +#include "Scheduler/StrongTyping.h" namespace android::scheduler { @@ -41,71 +43,123 @@ inline RefreshRateConfigEvent operator|(RefreshRateConfigEvent lhs, RefreshRateC */ class RefreshRateConfigs { public: - // Enum to indicate which vsync rate to run at. Default is the old 60Hz, and performance - // is the new 90Hz. Eventually we want to have a way for vendors to map these in the configs. - enum class RefreshRateType { DEFAULT, PERFORMANCE }; - struct RefreshRate { + RefreshRate(HwcConfigIndexType configId, nsecs_t vsyncPeriod, + HwcConfigGroupType configGroup, std::string name, float fps) + : configId(configId), + vsyncPeriod(vsyncPeriod), + configGroup(configGroup), + name(std::move(name)), + fps(fps) {} // This config ID corresponds to the position of the config in the vector that is stored // on the device. - int configId; - // Human readable name of the refresh rate. - std::string name; - // Refresh rate in frames per second, rounded to the nearest integer. - uint32_t fps = 0; + const HwcConfigIndexType configId; // Vsync period in nanoseconds. - nsecs_t vsyncPeriod; - // Hwc config Id (returned from HWC2::Display::Config::getId()) - hwc2_config_t hwcId; + const nsecs_t vsyncPeriod; + // This configGroup for the config. + const HwcConfigGroupType configGroup; + // Human readable name of the refresh rate. + const std::string name; + // Refresh rate in frames per second + const float fps = 0; + + bool operator!=(const RefreshRate& other) const { + return configId != other.configId || vsyncPeriod != other.vsyncPeriod || + configGroup != other.configGroup; + } + + bool operator==(const RefreshRate& other) const { return !(*this != other); } }; + using AllRefreshRatesMapType = std::unordered_map; + + // Sets the current policy to choose refresh rates. + void setPolicy(HwcConfigIndexType defaultConfigId, float minRefreshRate, float maxRefreshRate) + EXCLUDES(mLock); + // Returns true if this device is doing refresh rate switching. This won't change at runtime. - bool refreshRateSwitchingSupported() const { return mRefreshRateSwitchingSupported; } + bool refreshRateSwitchingSupported() const { return mRefreshRateSwitching; } + + // Returns all available refresh rates according to the current policy. + const RefreshRate& getRefreshRateForContent(float contentFramerate) const EXCLUDES(mLock); + + // Returns all the refresh rates supported by the device. This won't change at runtime. + const AllRefreshRatesMapType& getAllRefreshRates() const EXCLUDES(mLock); - // Returns the refresh rate map. This map won't be modified at runtime, so it's safe to access - // from multiple threads. This can only be called if refreshRateSwitching() returns true. - // TODO(b/122916473): Get this information from configs prepared by vendors, instead of - // baking them in. - const std::map& getRefreshRateMap() const; + // Returns the lowest refresh rate supported by the device. This won't change at runtime. + const RefreshRate& getMinRefreshRate() const { return *mMinSupportedRefreshRate; } - const RefreshRate& getRefreshRateFromType(RefreshRateType type) const; + // Returns the lowest refresh rate according to the current policy. May change in runtime. + const RefreshRate& getMinRefreshRateByPolicy() const EXCLUDES(mLock); - std::pair getCurrentRefreshRate() const; + // Returns the highest refresh rate supported by the device. This won't change at runtime. + const RefreshRate& getMaxRefreshRate() const { return *mMaxSupportedRefreshRate; } - const RefreshRate& getRefreshRateFromConfigId(int configId) const; + // Returns the highest refresh rate according to the current policy. May change in runtime. + const RefreshRate& getMaxRefreshRateByPolicy() const EXCLUDES(mLock); - RefreshRateType getRefreshRateTypeFromHwcConfigId(hwc2_config_t hwcId) const; + // Returns the current refresh rate + const RefreshRate& getCurrentRefreshRate() const EXCLUDES(mLock); - void setCurrentConfig(int config); + // Returns the refresh rate that corresponds to a HwcConfigIndexType. This won't change at + // runtime. + const RefreshRate& getRefreshRateFromConfigId(HwcConfigIndexType configId) const { + return mRefreshRates.at(configId); + }; + + // Stores the current configId the device operates at + void setCurrentConfigId(HwcConfigIndexType configId) EXCLUDES(mLock); struct InputConfig { - hwc2_config_t hwcId = 0; + HwcConfigIndexType configId = HwcConfigIndexType(0); + HwcConfigGroupType configGroup = HwcConfigGroupType(0); nsecs_t vsyncPeriod = 0; }; RefreshRateConfigs(bool refreshRateSwitching, const std::vector& configs, - int currentConfig); - + HwcConfigIndexType currentHwcConfig); RefreshRateConfigs(bool refreshRateSwitching, const std::vector>& configs, - int currentConfig); + HwcConfigIndexType currentConfigId); private: - void init(bool refreshRateSwitching, const std::vector& configs, - int currentConfig); - // Whether this device is doing refresh rate switching or not. This must not change after this - // object is initialized. - bool mRefreshRateSwitchingSupported; + void init(const std::vector& configs, HwcConfigIndexType currentHwcConfig); + + void constructAvailableRefreshRates() REQUIRES(mLock); + + void getSortedRefreshRateList( + const std::function& shouldAddRefreshRate, + std::vector* outRefreshRates); + // The list of refresh rates, indexed by display config ID. This must not change after this // object is initialized. - std::vector mRefreshRates; - // The mapping of refresh rate type to RefreshRate. This must not change after this object is - // initialized. - std::map mRefreshRateMap; - // The ID of the current config. This will change at runtime. This is set by SurfaceFlinger on - // the main thread, and read by the Scheduler (and other objects) on other threads, so it's - // atomic. - std::atomic mCurrentConfig; + AllRefreshRatesMapType mRefreshRates; + + // The list of refresh rates which are available in the current policy, ordered by vsyncPeriod + // (the first element is the lowest refresh rate) + std::vector mAvailableRefreshRates GUARDED_BY(mLock); + + // The current config. This will change at runtime. This is set by SurfaceFlinger on + // the main thread, and read by the Scheduler (and other objects) on other threads. + const RefreshRate* mCurrentRefreshRate GUARDED_BY(mLock); + + // The current config group. This will change at runtime. This is set by SurfaceFlinger on + // the main thread, and read by the Scheduler (and other objects) on other threads. + HwcConfigGroupType mCurrentGroupId GUARDED_BY(mLock); + + // The min and max FPS allowed by the policy. This will change at runtime and set by + // SurfaceFlinger on the main thread. + float mMinRefreshRateFps GUARDED_BY(mLock) = 0; + float mMaxRefreshRateFps GUARDED_BY(mLock) = std::numeric_limits::max(); + + // The min and max refresh rates supported by the device. + // This will not change at runtime. + const RefreshRate* mMinSupportedRefreshRate; + const RefreshRate* mMaxSupportedRefreshRate; + + const bool mRefreshRateSwitching; + + mutable std::mutex mLock; }; } // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/RefreshRateStats.h b/services/surfaceflinger/Scheduler/RefreshRateStats.h index 8afc93e8db..a384dbe29b 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateStats.h +++ b/services/surfaceflinger/Scheduler/RefreshRateStats.h @@ -25,8 +25,7 @@ #include "android-base/stringprintf.h" #include "utils/Timers.h" -namespace android { -namespace scheduler { +namespace android::scheduler { /** * Class to encapsulate statistics about refresh rates that the display is using. When the power @@ -42,10 +41,10 @@ class RefreshRateStats { public: RefreshRateStats(const RefreshRateConfigs& refreshRateConfigs, TimeStats& timeStats, - int currentConfigMode, int currentPowerMode) + HwcConfigIndexType currentConfigId, int currentPowerMode) : mRefreshRateConfigs(refreshRateConfigs), mTimeStats(timeStats), - mCurrentConfigMode(currentConfigMode), + mCurrentConfigMode(currentConfigId), mCurrentPowerMode(currentPowerMode) {} // Sets power mode. @@ -59,12 +58,12 @@ public: // Sets config mode. If the mode has changed, it records how much time was spent in the previous // mode. - void setConfigMode(int mode) { - if (mCurrentConfigMode == mode) { + void setConfigMode(HwcConfigIndexType configId) { + if (mCurrentConfigMode == configId) { return; } flushTime(); - mCurrentConfigMode = mode; + mCurrentConfigMode = configId; } // Returns a map between human readable refresh rate and number of seconds the device spent in @@ -78,11 +77,11 @@ public: std::unordered_map totalTime; // Multiple configs may map to the same name, e.g. "60fps". Add the // times for such configs together. - for (const auto& [config, time] : mConfigModesTotalTime) { - totalTime[mRefreshRateConfigs.getRefreshRateFromConfigId(config).name] = 0; + for (const auto& [configId, time] : mConfigModesTotalTime) { + totalTime[mRefreshRateConfigs.getRefreshRateFromConfigId(configId).name] = 0; } - for (const auto& [config, time] : mConfigModesTotalTime) { - totalTime[mRefreshRateConfigs.getRefreshRateFromConfigId(config).name] += time; + for (const auto& [configId, time] : mConfigModesTotalTime) { + totalTime[mRefreshRateConfigs.getRefreshRateFromConfigId(configId).name] += time; } totalTime["ScreenOff"] = mScreenOffTime; return totalTime; @@ -139,14 +138,14 @@ private: // Aggregate refresh rate statistics for telemetry. TimeStats& mTimeStats; - int mCurrentConfigMode; + HwcConfigIndexType mCurrentConfigMode; int32_t mCurrentPowerMode; - std::unordered_map mConfigModesTotalTime; + std::unordered_map + mConfigModesTotalTime; int64_t mScreenOffTime = 0; nsecs_t mPreviousRecordedTime = systemTime(); }; -} // namespace scheduler -} // namespace android +} // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 55fd6032f2..1d50fe1dd4 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -182,7 +182,7 @@ void Scheduler::onScreenReleased(ConnectionHandle handle) { } void Scheduler::onConfigChanged(ConnectionHandle handle, PhysicalDisplayId displayId, - int32_t configId) { + HwcConfigIndexType configId) { RETURN_IF_INVALID_HANDLE(handle); mConnections[handle].thread->onConfigChanged(displayId, configId); } @@ -280,8 +280,7 @@ void Scheduler::resync() { const nsecs_t last = mLastResyncTime.exchange(now); if (now - last > kIgnoreDelay) { - resyncToHardwareVsync(false, - mRefreshRateConfigs.getCurrentRefreshRate().second.vsyncPeriod); + resyncToHardwareVsync(false, mRefreshRateConfigs.getCurrentRefreshRate().vsyncPeriod); } } @@ -332,53 +331,49 @@ nsecs_t Scheduler::getDispSyncExpectedPresentTime() { void Scheduler::registerLayer(Layer* layer) { if (!mLayerHistory) return; - const auto type = layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER - ? RefreshRateType::DEFAULT - : RefreshRateType::PERFORMANCE; - - const auto lowFps = mRefreshRateConfigs.getRefreshRateFromType(RefreshRateType::DEFAULT).fps; - const auto highFps = mRefreshRateConfigs.getRefreshRateFromType(type).fps; + const auto lowFps = mRefreshRateConfigs.getMinRefreshRate().fps; + const auto highFps = layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER + ? lowFps + : mRefreshRateConfigs.getMaxRefreshRate().fps; mLayerHistory->registerLayer(layer, lowFps, highFps); } -void Scheduler::recordLayerHistory(Layer* layer, nsecs_t presentTime, bool isHDR) { +void Scheduler::recordLayerHistory(Layer* layer, nsecs_t presentTime) { if (mLayerHistory) { - mLayerHistory->record(layer, presentTime, isHDR, systemTime()); + mLayerHistory->record(layer, presentTime, systemTime()); } } void Scheduler::chooseRefreshRateForContent() { if (!mLayerHistory) return; - auto [refreshRate, isHDR] = mLayerHistory->summarize(systemTime()); + auto [refreshRate] = mLayerHistory->summarize(systemTime()); const uint32_t refreshRateRound = std::round(refreshRate); - RefreshRateType newRefreshRateType; + HwcConfigIndexType newConfigId; { std::lock_guard lock(mFeatureStateLock); - if (mFeatures.contentRefreshRate == refreshRateRound && mFeatures.isHDRContent == isHDR) { + if (mFeatures.contentRefreshRate == refreshRateRound) { return; } mFeatures.contentRefreshRate = refreshRateRound; ATRACE_INT("ContentFPS", refreshRateRound); - mFeatures.isHDRContent = isHDR; - ATRACE_INT("ContentHDR", isHDR); - mFeatures.contentDetection = refreshRateRound > 0 ? ContentDetectionState::On : ContentDetectionState::Off; - newRefreshRateType = calculateRefreshRateType(); - if (mFeatures.refreshRateType == newRefreshRateType) { + newConfigId = calculateRefreshRateType(); + if (mFeatures.configId == newConfigId) { return; } - mFeatures.refreshRateType = newRefreshRateType; - } - changeRefreshRate(newRefreshRateType, ConfigEvent::Changed); + mFeatures.configId = newConfigId; + }; + auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); + changeRefreshRate(newRefreshRate, ConfigEvent::Changed); } -void Scheduler::setChangeRefreshRateCallback(ChangeRefreshRateCallback&& callback) { +void Scheduler::setSchedulerCallback(android::Scheduler::ISchedulerCallback* callback) { std::lock_guard lock(mCallbackLock); - mChangeRefreshRateCallback = std::move(callback); + mSchedulerCallback = callback; } void Scheduler::resetIdleTimer() { @@ -423,13 +418,16 @@ void Scheduler::setDisplayPowerState(bool normal) { void Scheduler::kernelIdleTimerCallback(TimerState state) { ATRACE_INT("ExpiredKernelIdleTimer", static_cast(state)); + // TODO(145561154): cleanup the kernel idle timer implementation and the refresh rate + // magic number const auto refreshRate = mRefreshRateConfigs.getCurrentRefreshRate(); - if (state == TimerState::Reset && refreshRate.first == RefreshRateType::PERFORMANCE) { + constexpr float FPS_THRESHOLD_FOR_KERNEL_TIMER = 65.0f; + if (state == TimerState::Reset && refreshRate.fps > FPS_THRESHOLD_FOR_KERNEL_TIMER) { // If we're not in performance mode then the kernel timer shouldn't do // anything, as the refresh rate during DPU power collapse will be the // same. - resyncToHardwareVsync(true /* makeAvailable */, refreshRate.second.vsyncPeriod); - } else if (state == TimerState::Expired && refreshRate.first != RefreshRateType::PERFORMANCE) { + resyncToHardwareVsync(true /* makeAvailable */, refreshRate.vsyncPeriod); + } else if (state == TimerState::Expired && refreshRate.fps <= FPS_THRESHOLD_FOR_KERNEL_TIMER) { // Disable HW VSYNC if the timer expired, as we don't need it enabled if // we're not pushing frames, and if we're in PERFORMANCE mode then we'll // need to update the DispSync model anyway. @@ -471,96 +469,67 @@ void Scheduler::dump(std::string& result) const { template void Scheduler::handleTimerStateChanged(T* currentState, T newState, bool eventOnContentDetection) { ConfigEvent event = ConfigEvent::None; - RefreshRateType newRefreshRateType; + HwcConfigIndexType newConfigId; { std::lock_guard lock(mFeatureStateLock); if (*currentState == newState) { return; } *currentState = newState; - newRefreshRateType = calculateRefreshRateType(); - if (mFeatures.refreshRateType == newRefreshRateType) { + newConfigId = calculateRefreshRateType(); + if (mFeatures.configId == newConfigId) { return; } - mFeatures.refreshRateType = newRefreshRateType; + mFeatures.configId = newConfigId; if (eventOnContentDetection && mFeatures.contentDetection == ContentDetectionState::On) { event = ConfigEvent::Changed; } } - changeRefreshRate(newRefreshRateType, event); + const RefreshRate& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); + changeRefreshRate(newRefreshRate, event); } -Scheduler::RefreshRateType Scheduler::calculateRefreshRateType() { +HwcConfigIndexType Scheduler::calculateRefreshRateType() { if (!mRefreshRateConfigs.refreshRateSwitchingSupported()) { - return RefreshRateType::DEFAULT; - } - - // HDR content is not supported on PERFORMANCE mode - if (mForceHDRContentToDefaultRefreshRate && mFeatures.isHDRContent) { - return RefreshRateType::DEFAULT; + return mRefreshRateConfigs.getCurrentRefreshRate().configId; } // If Display Power is not in normal operation we want to be in performance mode. // When coming back to normal mode, a grace period is given with DisplayPowerTimer if (!mFeatures.isDisplayPowerStateNormal || mFeatures.displayPowerTimer == TimerState::Reset) { - return RefreshRateType::PERFORMANCE; + return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId; } // As long as touch is active we want to be in performance mode if (mFeatures.touch == TouchState::Active) { - return RefreshRateType::PERFORMANCE; + return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId; } // If timer has expired as it means there is no new content on the screen if (mFeatures.idleTimer == TimerState::Expired) { - return RefreshRateType::DEFAULT; + return mRefreshRateConfigs.getMinRefreshRateByPolicy().configId; } // If content detection is off we choose performance as we don't know the content fps if (mFeatures.contentDetection == ContentDetectionState::Off) { - return RefreshRateType::PERFORMANCE; + return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId; } // Content detection is on, find the appropriate refresh rate with minimal error - // TODO(b/139751853): Scan allowed refresh rates only (SurfaceFlinger::mAllowedDisplayConfigs) - const float rate = static_cast(mFeatures.contentRefreshRate); - auto iter = min_element(mRefreshRateConfigs.getRefreshRateMap().cbegin(), - mRefreshRateConfigs.getRefreshRateMap().cend(), - [rate](const auto& lhs, const auto& rhs) -> bool { - return std::abs(lhs.second.fps - rate) < - std::abs(rhs.second.fps - rate); - }); - RefreshRateType currRefreshRateType = iter->first; - - // Some content aligns better on higher refresh rate. For example for 45fps we should choose - // 90Hz config. However we should still prefer a lower refresh rate if the content doesn't - // align well with both - constexpr float MARGIN = 0.05f; - float ratio = mRefreshRateConfigs.getRefreshRateFromType(currRefreshRateType).fps / rate; - if (std::abs(std::round(ratio) - ratio) > MARGIN) { - while (iter != mRefreshRateConfigs.getRefreshRateMap().cend()) { - ratio = iter->second.fps / rate; - - if (std::abs(std::round(ratio) - ratio) <= MARGIN) { - currRefreshRateType = iter->first; - break; - } - ++iter; - } - } - - return currRefreshRateType; + return mRefreshRateConfigs + .getRefreshRateForContent(static_cast(mFeatures.contentRefreshRate)) + .configId; } -Scheduler::RefreshRateType Scheduler::getPreferredRefreshRateType() { +std::optional Scheduler::getPreferredConfigId() { std::lock_guard lock(mFeatureStateLock); - return mFeatures.refreshRateType; + return mFeatures.configId; } -void Scheduler::changeRefreshRate(RefreshRateType refreshRateType, ConfigEvent configEvent) { +void Scheduler::changeRefreshRate(const RefreshRate& refreshRate, ConfigEvent configEvent) { std::lock_guard lock(mCallbackLock); - if (mChangeRefreshRateCallback) { - mChangeRefreshRateCallback(refreshRateType, configEvent); + if (mSchedulerCallback) { + mSchedulerCallback->changeRefreshRate(refreshRate, configEvent); } } diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index 346896c44f..04a83906b1 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -34,6 +34,8 @@ namespace android { +using namespace std::chrono_literals; + class DispSync; class FenceTime; class InjectVSyncSource; @@ -41,10 +43,14 @@ struct DisplayStateInfo; class Scheduler { public: - using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType; + using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate; using ConfigEvent = scheduler::RefreshRateConfigEvent; - using ChangeRefreshRateCallback = std::function; + class ISchedulerCallback { + public: + virtual ~ISchedulerCallback() = default; + virtual void changeRefreshRate(const RefreshRate&, ConfigEvent) = 0; + }; // Indicates whether to start the transaction early, or at vsync time. enum class TransactionStart { EARLY, NORMAL }; @@ -67,7 +73,7 @@ public: sp getEventConnection(ConnectionHandle); void onHotplugReceived(ConnectionHandle, PhysicalDisplayId, bool connected); - void onConfigChanged(ConnectionHandle, PhysicalDisplayId, int32_t configId); + void onConfigChanged(ConnectionHandle, PhysicalDisplayId, HwcConfigIndexType configId); void onScreenAcquired(ConnectionHandle); void onScreenReleased(ConnectionHandle); @@ -103,13 +109,13 @@ public: // Layers are registered on creation, and unregistered when the weak reference expires. void registerLayer(Layer*); - void recordLayerHistory(Layer*, nsecs_t presentTime, bool isHDR); + void recordLayerHistory(Layer*, nsecs_t presentTime); // Detects content using layer history, and selects a matching refresh rate. void chooseRefreshRateForContent(); - // Called by Scheduler to change refresh rate. - void setChangeRefreshRateCallback(ChangeRefreshRateCallback&&); + // Called by Scheduler to control SurfaceFlinger operations. + void setSchedulerCallback(ISchedulerCallback*); bool isIdleTimerEnabled() const { return mIdleTimer.has_value(); } void resetIdleTimer(); @@ -122,8 +128,8 @@ public: void dump(std::string&) const; void dump(ConnectionHandle, std::string&) const; - // Get the appropriate refresh type for current conditions. - RefreshRateType getPreferredRefreshRateType(); + // Get the appropriate refresh for current conditions. + std::optional getPreferredConfigId(); private: friend class TestableScheduler; @@ -158,9 +164,9 @@ private: void setVsyncPeriod(nsecs_t period); - RefreshRateType calculateRefreshRateType() REQUIRES(mFeatureStateLock); + HwcConfigIndexType calculateRefreshRateType() REQUIRES(mFeatureStateLock); // Acquires a lock and calls the ChangeRefreshRateCallback with given parameters. - void changeRefreshRate(RefreshRateType, ConfigEvent); + void changeRefreshRate(const RefreshRate&, ConfigEvent); // Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection. struct Connection { @@ -198,7 +204,7 @@ private: std::optional mDisplayPowerTimer; std::mutex mCallbackLock; - ChangeRefreshRateCallback mChangeRefreshRateCallback GUARDED_BY(mCallbackLock); + ISchedulerCallback* mSchedulerCallback GUARDED_BY(mCallbackLock) = nullptr; // In order to make sure that the features don't override themselves, we need a state machine // to keep track which feature requested the config change. @@ -210,17 +216,13 @@ private: TouchState touch = TouchState::Inactive; TimerState displayPowerTimer = TimerState::Expired; - RefreshRateType refreshRateType = RefreshRateType::DEFAULT; + std::optional configId; uint32_t contentRefreshRate = 0; - bool isHDRContent = false; bool isDisplayPowerStateNormal = true; } mFeatures GUARDED_BY(mFeatureStateLock); const scheduler::RefreshRateConfigs& mRefreshRateConfigs; - - // Global config to force HDR content to work on DEFAULT refreshRate - static constexpr bool mForceHDRContentToDefaultRefreshRate = false; }; } // namespace android diff --git a/services/surfaceflinger/Scheduler/StrongTyping.h b/services/surfaceflinger/Scheduler/StrongTyping.h index 02db022e08..e8ca0ba836 100644 --- a/services/surfaceflinger/Scheduler/StrongTyping.h +++ b/services/surfaceflinger/Scheduler/StrongTyping.h @@ -51,13 +51,22 @@ struct Compare : Ability { inline bool operator>(T const& other) const { return !(*this < other || *this == other); } }; +template +struct Hash : Ability { + [[nodiscard]] std::size_t hash() const { + return std::hashbase().value())>::type>::type>{}( + this->base().value()); + } +}; + template class... Ability> struct StrongTyping : Ability>... { StrongTyping() : mValue(0) {} explicit StrongTyping(T const& value) : mValue(value) {} StrongTyping(StrongTyping const&) = default; StrongTyping& operator=(StrongTyping const&) = default; - inline operator T() const { return mValue; } + explicit inline operator T() const { return mValue; } T const& value() const { return mValue; } T& value() { return mValue; } @@ -65,3 +74,12 @@ private: T mValue; }; } // namespace android + +namespace std { +template class... Ability> +struct hash> { + std::size_t operator()(android::StrongTyping const& k) const { + return k.hash(); + } +}; +} // namespace std diff --git a/services/surfaceflinger/Scheduler/VSyncDispatch.h b/services/surfaceflinger/Scheduler/VSyncDispatch.h index 4a4bef8b2e..e001080015 100644 --- a/services/surfaceflinger/Scheduler/VSyncDispatch.h +++ b/services/surfaceflinger/Scheduler/VSyncDispatch.h @@ -34,7 +34,7 @@ enum class CancelResult { Cancelled, TooLate, Error }; */ class VSyncDispatch { public: - using CallbackToken = StrongTyping; + using CallbackToken = StrongTyping; virtual ~VSyncDispatch(); diff --git a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h index f0580999c6..0e12e7f321 100644 --- a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h +++ b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h @@ -106,7 +106,8 @@ private: VSyncDispatchTimerQueue(VSyncDispatchTimerQueue const&) = delete; VSyncDispatchTimerQueue& operator=(VSyncDispatchTimerQueue const&) = delete; - using CallbackMap = std::unordered_map>; + using CallbackMap = + std::unordered_map>; void timerCallback(); void setTimer(nsecs_t, nsecs_t) REQUIRES(mMutex); diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.cpp b/services/surfaceflinger/Scheduler/VSyncModulator.cpp index 27fd76cba3..8de35b1c2f 100644 --- a/services/surfaceflinger/Scheduler/VSyncModulator.cpp +++ b/services/surfaceflinger/Scheduler/VSyncModulator.cpp @@ -134,18 +134,13 @@ void VSyncModulator::updateOffsetsLocked() { return; } - const bool isDefault = mOffsets.fpsMode == RefreshRateType::DEFAULT; - const bool isPerformance = mOffsets.fpsMode == RefreshRateType::PERFORMANCE; const bool isEarly = &offsets == &mOffsetsConfig.early; const bool isEarlyGl = &offsets == &mOffsetsConfig.earlyGl; const bool isLate = &offsets == &mOffsetsConfig.late; - ATRACE_INT("Vsync-EarlyOffsetsOn", isDefault && isEarly); - ATRACE_INT("Vsync-EarlyGLOffsetsOn", isDefault && isEarlyGl); - ATRACE_INT("Vsync-LateOffsetsOn", isDefault && isLate); - ATRACE_INT("Vsync-HighFpsEarlyOffsetsOn", isPerformance && isEarly); - ATRACE_INT("Vsync-HighFpsEarlyGLOffsetsOn", isPerformance && isEarlyGl); - ATRACE_INT("Vsync-HighFpsLateOffsetsOn", isPerformance && isLate); + ATRACE_INT("Vsync-EarlyOffsetsOn", isEarly); + ATRACE_INT("Vsync-EarlyGLOffsetsOn", isEarlyGl); + ATRACE_INT("Vsync-LateOffsetsOn", isLate); } } // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.h b/services/surfaceflinger/Scheduler/VSyncModulator.h index 727cef26fe..63c0feb9cc 100644 --- a/services/surfaceflinger/Scheduler/VSyncModulator.h +++ b/services/surfaceflinger/Scheduler/VSyncModulator.h @@ -37,13 +37,10 @@ private: // switch in and out of gl composition. static constexpr int MIN_EARLY_GL_FRAME_COUNT_TRANSACTION = 2; - using RefreshRateType = RefreshRateConfigs::RefreshRateType; - public: // Wrapper for a collection of surfaceflinger/app offsets for a particular // configuration. struct Offsets { - RefreshRateType fpsMode; nsecs_t sf; nsecs_t app; }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index bf3b4c9f01..5aa2447419 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -542,14 +542,8 @@ void SurfaceFlinger::bootFinished() if (mRefreshRateConfigs->refreshRateSwitchingSupported()) { // set the refresh rate according to the policy - const auto& performanceRefreshRate = - mRefreshRateConfigs->getRefreshRateFromType(RefreshRateType::PERFORMANCE); - - if (isDisplayConfigAllowed(performanceRefreshRate.configId)) { - setRefreshRateTo(RefreshRateType::PERFORMANCE, Scheduler::ConfigEvent::None); - } else { - setRefreshRateTo(RefreshRateType::DEFAULT, Scheduler::ConfigEvent::None); - } + const auto& performanceRefreshRate = mRefreshRateConfigs->getMaxRefreshRateByPolicy(); + changeRefreshRateLocked(performanceRefreshRate, Scheduler::ConfigEvent::None); } })); } @@ -821,9 +815,8 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& displayToken, info.xdpi = xdpi; info.ydpi = ydpi; info.fps = 1e9 / hwConfig->getVsyncPeriod(); - const auto refreshRateType = - mRefreshRateConfigs->getRefreshRateTypeFromHwcConfigId(hwConfig->getId()); - const auto offset = mPhaseOffsets->getOffsetsForRefreshRate(refreshRateType); + + const auto offset = mPhaseOffsets->getOffsetsForRefreshRate(info.fps); info.appVsyncOffset = offset.late.app; // This is how far in advance a buffer must be queued for @@ -873,17 +866,17 @@ int SurfaceFlinger::getActiveConfig(const sp& displayToken) { if (display->isPrimary()) { std::lock_guard lock(mActiveConfigLock); if (mDesiredActiveConfigChanged) { - return mDesiredActiveConfig.configId; - } else { - return display->getActiveConfig(); + return mDesiredActiveConfig.configId.value(); } - } else { - return display->getActiveConfig(); } + + return display->getActiveConfig().value(); } void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) { ATRACE_CALL(); + auto refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(info.configId); + ALOGV("setDesiredActiveConfig(%s)", refreshRate.name.c_str()); // Don't check against the current mode yet. Worst case we set the desired // config twice. However event generation config might have changed so we need to update it @@ -902,13 +895,14 @@ void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) { // As we called to set period, we will call to onRefreshRateChangeCompleted once // DispSync model is locked. mVSyncModulator->onRefreshRateChangeInitiated(); - mPhaseOffsets->setRefreshRateType(info.type); + + mPhaseOffsets->setRefreshRateFps(refreshRate.fps); mVSyncModulator->setPhaseOffsets(mPhaseOffsets->getCurrentOffsets()); } mDesiredActiveConfigChanged = true; if (mRefreshRateOverlay) { - mRefreshRateOverlay->changeRefreshRate(mDesiredActiveConfig.type); + mRefreshRateOverlay->changeRefreshRate(refreshRate); } } @@ -930,14 +924,15 @@ void SurfaceFlinger::setActiveConfigInternal() { } std::lock_guard lock(mActiveConfigLock); - mRefreshRateConfigs->setCurrentConfig(mUpcomingActiveConfig.configId); + mRefreshRateConfigs->setCurrentConfigId(mUpcomingActiveConfig.configId); mRefreshRateStats->setConfigMode(mUpcomingActiveConfig.configId); - display->setActiveConfig(mUpcomingActiveConfig.configId); - mPhaseOffsets->setRefreshRateType(mUpcomingActiveConfig.type); + auto refreshRate = + mRefreshRateConfigs->getRefreshRateFromConfigId(mUpcomingActiveConfig.configId); + mPhaseOffsets->setRefreshRateFps(refreshRate.fps); mVSyncModulator->setPhaseOffsets(mPhaseOffsets->getCurrentOffsets()); - ATRACE_INT("ActiveConfigMode", mUpcomingActiveConfig.configId); + ATRACE_INT("ActiveConfigFPS", refreshRate.fps); if (mUpcomingActiveConfig.event != Scheduler::ConfigEvent::None) { mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value, @@ -951,12 +946,15 @@ void SurfaceFlinger::desiredActiveConfigChangeDone() { mDesiredActiveConfigChanged = false; mScheduler->resyncToHardwareVsync(true, getVsyncPeriod()); - mPhaseOffsets->setRefreshRateType(mUpcomingActiveConfig.type); + auto refreshRate = + mRefreshRateConfigs->getRefreshRateFromConfigId(mDesiredActiveConfig.configId); + mPhaseOffsets->setRefreshRateFps(refreshRate.fps); mVSyncModulator->setPhaseOffsets(mPhaseOffsets->getCurrentOffsets()); } bool SurfaceFlinger::performSetActiveConfig() { ATRACE_CALL(); + ALOGV("performSetActiveConfig"); if (mCheckPendingFence) { if (previousFrameMissed()) { // fence has not signaled yet. wait for the next invalidate @@ -980,6 +978,10 @@ bool SurfaceFlinger::performSetActiveConfig() { desiredActiveConfig = mDesiredActiveConfig; } + auto refreshRate = + mRefreshRateConfigs->getRefreshRateFromConfigId(desiredActiveConfig.configId); + ALOGV("performSetActiveConfig changing active config to %d(%s)", refreshRate.configId.value(), + refreshRate.name.c_str()); const auto display = getDefaultDisplayDeviceLocked(); if (!display || display->getActiveConfig() == desiredActiveConfig.configId) { // display is not valid or we are already in the requested mode @@ -1000,8 +1002,8 @@ bool SurfaceFlinger::performSetActiveConfig() { const auto displayId = display->getId(); LOG_ALWAYS_FATAL_IF(!displayId); - ATRACE_INT("ActiveConfigModeHWC", mUpcomingActiveConfig.configId); - getHwComposer().setActiveConfig(*displayId, mUpcomingActiveConfig.configId); + ATRACE_INT("ActiveConfigFPS_HWC", refreshRate.fps); + getHwComposer().setActiveConfig(*displayId, mUpcomingActiveConfig.configId.value()); // we need to submit an empty frame to HWC to start the process mCheckPendingFence = true; @@ -1396,11 +1398,12 @@ void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) { *compositorTiming = getBE().mCompositorTiming; } -bool SurfaceFlinger::isDisplayConfigAllowed(int32_t configId) const { +bool SurfaceFlinger::isDisplayConfigAllowed(HwcConfigIndexType configId) const { return mAllowedDisplayConfigs.empty() || mAllowedDisplayConfigs.count(configId); } -void SurfaceFlinger::setRefreshRateTo(RefreshRateType refreshRate, Scheduler::ConfigEvent event) { +void SurfaceFlinger::changeRefreshRateLocked(const RefreshRate& refreshRate, + Scheduler::ConfigEvent event) { const auto display = getDefaultDisplayDeviceLocked(); if (!display || mBootStage != BootStage::FINISHED) { return; @@ -1408,15 +1411,13 @@ void SurfaceFlinger::setRefreshRateTo(RefreshRateType refreshRate, Scheduler::Co ATRACE_CALL(); // Don't do any updating if the current fps is the same as the new one. - const auto& refreshRateConfig = mRefreshRateConfigs->getRefreshRateFromType(refreshRate); - const int desiredConfigId = refreshRateConfig.configId; - - if (!isDisplayConfigAllowed(desiredConfigId)) { - ALOGV("Skipping config %d as it is not part of allowed configs", desiredConfigId); + if (!isDisplayConfigAllowed(refreshRate.configId)) { + ALOGV("Skipping config %d as it is not part of allowed configs", + refreshRate.configId.value()); return; } - setDesiredActiveConfig({refreshRate, desiredConfigId, event}); + setDesiredActiveConfig({refreshRate.configId, event}); } void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId, @@ -2180,7 +2181,8 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( Dataspace::UNKNOWN}); if (!state.isVirtual()) { LOG_ALWAYS_FATAL_IF(!displayId); - display->setActiveConfig(getHwComposer().getActiveConfigIndex(*displayId)); + auto activeConfigId = HwcConfigIndexType(getHwComposer().getActiveConfigIndex(*displayId)); + display->setActiveConfig(activeConfigId); } display->setLayerStack(state.layerStack); @@ -2520,6 +2522,12 @@ void SurfaceFlinger::updateCursorAsync() mCompositionEngine->updateCursorAsync(refreshArgs); } +void SurfaceFlinger::changeRefreshRate(const RefreshRate& refreshRate, + Scheduler::ConfigEvent event) { + Mutex::Autolock lock(mStateLock); + changeRefreshRateLocked(refreshRate, event); +} + void SurfaceFlinger::initScheduler(DisplayId primaryDisplayId) { if (mScheduler) { // In practice it's not allowed to hotplug in/out the primary display once it's been @@ -2528,7 +2536,7 @@ void SurfaceFlinger::initScheduler(DisplayId primaryDisplayId) { return; } - int currentConfig = getHwComposer().getActiveConfigIndex(primaryDisplayId); + auto currentConfig = HwcConfigIndexType(getHwComposer().getActiveConfigIndex(primaryDisplayId)); mRefreshRateConfigs = std::make_unique(refresh_rate_switching(false), getHwComposer().getConfigs( @@ -2562,11 +2570,7 @@ void SurfaceFlinger::initScheduler(DisplayId primaryDisplayId) { new RegionSamplingThread(*this, *mScheduler, RegionSamplingThread::EnvironmentTimingTunables()); - mScheduler->setChangeRefreshRateCallback( - [this](RefreshRateType type, Scheduler::ConfigEvent event) { - Mutex::Autolock lock(mStateLock); - setRefreshRateTo(type, event); - }); + mScheduler->setSchedulerCallback(this); } void SurfaceFlinger::commitTransaction() @@ -3966,9 +3970,10 @@ void SurfaceFlinger::dumpVSync(std::string& result) const { dispSyncPresentTimeOffset, getVsyncPeriod()); StringAppendF(&result, "Allowed Display Configs: "); - for (int32_t configId : mAllowedDisplayConfigs) { + for (auto configId : mAllowedDisplayConfigs) { StringAppendF(&result, "%" PRIu32 " Hz, ", - mRefreshRateConfigs->getRefreshRateFromConfigId(configId).fps); + static_cast( + mRefreshRateConfigs->getRefreshRateFromConfigId(configId).fps)); } StringAppendF(&result, "(config override by backdoor: %s)\n\n", mDebugDisplayConfigSetByBackdoor ? "yes" : "no"); @@ -4809,13 +4814,9 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r n = data.readInt32(); if (n && !mRefreshRateOverlay && mRefreshRateConfigs->refreshRateSwitchingSupported()) { - RefreshRateType type; - { - std::lock_guard lock(mActiveConfigLock); - type = mDesiredActiveConfig.type; - } mRefreshRateOverlay = std::make_unique(*this); - mRefreshRateOverlay->changeRefreshRate(type); + auto current = mRefreshRateConfigs->getCurrentRefreshRate(); + mRefreshRateOverlay->changeRefreshRate(current); } else if (!n) { mRefreshRateOverlay.reset(); } @@ -5417,28 +5418,48 @@ void SurfaceFlinger::setAllowedDisplayConfigsInternal(const sp& d mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value, display->getActiveConfig()); + // Prepare the parameters needed for RefreshRateConfigs::setPolicy. This will change to just + // passthrough once DisplayManager provide these parameters directly. + const auto refreshRate = + mRefreshRateConfigs->getRefreshRateFromConfigId(HwcConfigIndexType(allowedConfigs[0])); + const auto defaultModeId = refreshRate.configId; + auto minRefreshRateFps = refreshRate.fps; + auto maxRefreshRateFps = minRefreshRateFps; + + for (auto config : allowedConfigs) { + const auto configRefreshRate = + mRefreshRateConfigs->getRefreshRateFromConfigId(HwcConfigIndexType(config)); + if (configRefreshRate.fps < minRefreshRateFps) { + minRefreshRateFps = configRefreshRate.fps; + } else if (configRefreshRate.fps > maxRefreshRateFps) { + maxRefreshRateFps = configRefreshRate.fps; + } + } + mRefreshRateConfigs->setPolicy(defaultModeId, minRefreshRateFps, maxRefreshRateFps); + if (mRefreshRateConfigs->refreshRateSwitchingSupported()) { - const auto& type = mScheduler->getPreferredRefreshRateType(); - const auto& config = mRefreshRateConfigs->getRefreshRateFromType(type); - if (isDisplayConfigAllowed(config.configId)) { - ALOGV("switching to Scheduler preferred config %d", config.configId); - setDesiredActiveConfig({type, config.configId, Scheduler::ConfigEvent::Changed}); + auto configId = mScheduler->getPreferredConfigId(); + auto preferredRefreshRate = configId + ? mRefreshRateConfigs->getRefreshRateFromConfigId(*configId) + : mRefreshRateConfigs->getMinRefreshRateByPolicy(); + ALOGV("trying to switch to Scheduler preferred config %d (%s)", + preferredRefreshRate.configId.value(), preferredRefreshRate.name.c_str()); + if (isDisplayConfigAllowed(preferredRefreshRate.configId)) { + ALOGV("switching to Scheduler preferred config %d", + preferredRefreshRate.configId.value()); + setDesiredActiveConfig( + {preferredRefreshRate.configId, Scheduler::ConfigEvent::Changed}); } else { - // Set the highest allowed config by iterating backwards on available refresh rates - const auto& refreshRates = mRefreshRateConfigs->getRefreshRateMap(); - for (auto iter = refreshRates.crbegin(); iter != refreshRates.crend(); ++iter) { - if (isDisplayConfigAllowed(iter->second.configId)) { - ALOGV("switching to allowed config %d", iter->second.configId); - setDesiredActiveConfig( - {iter->first, iter->second.configId, Scheduler::ConfigEvent::Changed}); - break; - } - } + // Set the highest allowed config + setDesiredActiveConfig({mRefreshRateConfigs->getMaxRefreshRateByPolicy().configId, + Scheduler::ConfigEvent::Changed}); + } + } else { + if (!allowedConfigs.empty()) { + ALOGV("switching to config %d", allowedConfigs[0]); + auto configId = HwcConfigIndexType(allowedConfigs[0]); + setDesiredActiveConfig({configId, Scheduler::ConfigEvent::Changed}); } - } else if (!allowedConfigs.empty()) { - ALOGV("switching to config %d", allowedConfigs[0]); - setDesiredActiveConfig( - {RefreshRateType::DEFAULT, allowedConfigs[0], Scheduler::ConfigEvent::Changed}); } } @@ -5487,7 +5508,10 @@ status_t SurfaceFlinger::getAllowedDisplayConfigs(const sp& displayToke } if (display->isPrimary()) { - outAllowedConfigs->assign(mAllowedDisplayConfigs.begin(), mAllowedDisplayConfigs.end()); + outAllowedConfigs->reserve(mAllowedDisplayConfigs.size()); + for (auto configId : mAllowedDisplayConfigs) { + outAllowedConfigs->push_back(configId.value()); + } } return NO_ERROR; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 8e1199ca59..900c5f7f71 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -174,7 +174,8 @@ class SurfaceFlinger : public BnSurfaceComposer, public PriorityDumper, public ClientCache::ErasedRecipient, private IBinder::DeathRecipient, - private HWC2::ComposerCallback { + private HWC2::ComposerCallback, + private Scheduler::ISchedulerCallback { public: SurfaceFlingerBE& getBE() { return mBE; } const SurfaceFlingerBE& getBE() const { return mBE; } @@ -494,6 +495,10 @@ private: int32_t sequenceId, hwc2_display_t display, const hwc_vsync_period_change_timeline_t& updatedTimeline) override; + /* ------------------------------------------------------------------------ + * Scheduler::ISchedulerCallback + */ + void changeRefreshRate(const Scheduler::RefreshRate&, Scheduler::ConfigEvent) override; /* ------------------------------------------------------------------------ * Message handling */ @@ -504,15 +509,14 @@ private: void signalLayerUpdate(); void signalRefresh(); - using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType; + using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate; struct ActiveConfigInfo { - RefreshRateType type = RefreshRateType::DEFAULT; - int configId = 0; + HwcConfigIndexType configId; Scheduler::ConfigEvent event = Scheduler::ConfigEvent::None; bool operator!=(const ActiveConfigInfo& other) const { - return type != other.type || configId != other.configId || event != other.event; + return configId != other.configId || event != other.event; } }; @@ -787,9 +791,10 @@ private: // Sets the refresh rate by switching active configs, if they are available for // the desired refresh rate. - void setRefreshRateTo(RefreshRateType, Scheduler::ConfigEvent event) REQUIRES(mStateLock); + void changeRefreshRateLocked(const RefreshRate&, Scheduler::ConfigEvent event) + REQUIRES(mStateLock); - bool isDisplayConfigAllowed(int32_t configId) const REQUIRES(mStateLock); + bool isDisplayConfigAllowed(HwcConfigIndexType configId) const REQUIRES(mStateLock); bool previousFrameMissed(int graceTimeMs = 0); @@ -1113,7 +1118,7 @@ private: std::atomic mExpectedPresentTime = 0; // All configs are allowed if the set is empty. - using DisplayConfigs = std::set; + using DisplayConfigs = std::set; DisplayConfigs mAllowedDisplayConfigs GUARDED_BY(mStateLock); std::mutex mActiveConfigLock; diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index db7d04c8e3..76e8171255 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -1427,7 +1427,7 @@ void SetupNewDisplayDeviceInternalTest::setupNewDisplayDeviceInternalTest() { // Note: This is not Case::Display::HWC_ACTIVE_CONFIG_ID as the ids are // remapped, and the test only ever sets up one config. If there were an error // looking up the remapped index, device->getActiveConfig() would be -1 instead. - EXPECT_EQ(0, device->getActiveConfig()); + EXPECT_EQ(0, device->getActiveConfig().value()); EXPECT_EQ(Case::PerFrameMetadataSupport::PER_FRAME_METADATA_KEYS, device->getSupportedPerFrameMetadata()); } diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp index 2662f52581..80bca021ab 100644 --- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp +++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp @@ -26,6 +26,7 @@ #include "AsyncCallRecorder.h" #include "Scheduler/EventThread.h" +#include "Scheduler/HwcStrongTypes.h" using namespace std::chrono_literals; using namespace std::placeholders; @@ -34,6 +35,7 @@ using testing::_; using testing::Invoke; namespace android { + namespace { constexpr PhysicalDisplayId INTERNAL_DISPLAY_ID = 111; @@ -448,17 +450,17 @@ TEST_F(EventThreadTest, postHotplugExternalConnect) { } TEST_F(EventThreadTest, postConfigChangedPrimary) { - mThread->onConfigChanged(INTERNAL_DISPLAY_ID, 7); + mThread->onConfigChanged(INTERNAL_DISPLAY_ID, HwcConfigIndexType(7)); expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 7); } TEST_F(EventThreadTest, postConfigChangedExternal) { - mThread->onConfigChanged(EXTERNAL_DISPLAY_ID, 5); + mThread->onConfigChanged(EXTERNAL_DISPLAY_ID, HwcConfigIndexType(5)); expectConfigChangedEventReceivedByConnection(EXTERNAL_DISPLAY_ID, 5); } TEST_F(EventThreadTest, postConfigChangedPrimary64bit) { - mThread->onConfigChanged(DISPLAY_ID_64BIT, 7); + mThread->onConfigChanged(DISPLAY_ID_64BIT, HwcConfigIndexType(7)); expectConfigChangedEventReceivedByConnection(DISPLAY_ID_64BIT, 7); } @@ -468,7 +470,7 @@ TEST_F(EventThreadTest, suppressConfigChanged) { createConnection(suppressConnectionEventRecorder, ISurfaceComposer::eConfigChangedSuppress); - mThread->onConfigChanged(INTERNAL_DISPLAY_ID, 9); + mThread->onConfigChanged(INTERNAL_DISPLAY_ID, HwcConfigIndexType(9)); expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 9); auto args = suppressConnectionEventRecorder.waitForCall(); diff --git a/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h b/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h index 66c7f6b81f..da4eea0221 100644 --- a/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h +++ b/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h @@ -25,16 +25,16 @@ namespace android::scheduler { struct FakePhaseOffsets : PhaseOffsets { static constexpr nsecs_t FAKE_PHASE_OFFSET_NS = 0; - Offsets getOffsetsForRefreshRate(RefreshRateType) const override { return getCurrentOffsets(); } + Offsets getOffsetsForRefreshRate(float) const override { return getCurrentOffsets(); } Offsets getCurrentOffsets() const override { - return {{RefreshRateType::DEFAULT, FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS}, - {RefreshRateType::DEFAULT, FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS}, - {RefreshRateType::DEFAULT, FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS}, + return {{FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS}, + {FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS}, + {FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS}, FAKE_PHASE_OFFSET_NS}; } - void setRefreshRateType(RefreshRateType) override {} + void setRefreshRateFps(float) override {} void dump(std::string&) const override {} }; diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index e93d31e7f2..d95252b67f 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -44,9 +44,15 @@ protected: auto createLayer() { return sp(new mock::MockLayer(mFlinger.flinger())); } RefreshRateConfigs mConfigs{true, - {RefreshRateConfigs::InputConfig{0, LO_FPS_PERIOD}, - RefreshRateConfigs::InputConfig{1, HI_FPS_PERIOD}}, - 0}; + { + RefreshRateConfigs::InputConfig{HwcConfigIndexType(0), + HwcConfigGroupType(0), + LO_FPS_PERIOD}, + RefreshRateConfigs::InputConfig{HwcConfigIndexType(1), + HwcConfigGroupType(0), + HI_FPS_PERIOD}, + }, + HwcConfigIndexType(0)}; TestableScheduler* const mScheduler{new TestableScheduler(mConfigs)}; TestableSurfaceFlinger mFlinger; @@ -57,7 +63,6 @@ namespace { TEST_F(LayerHistoryTest, oneLayer) { const auto layer = createLayer(); - constexpr bool isHDR = false; EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); EXPECT_EQ(1, layerCount()); @@ -69,14 +74,14 @@ TEST_F(LayerHistoryTest, oneLayer) { // 0 FPS is returned if active layers have insufficient history. for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - 1; i++) { - history().record(layer.get(), 0, isHDR, mTime); + history().record(layer.get(), 0, mTime); EXPECT_FLOAT_EQ(0, history().summarize(mTime).maxRefreshRate); EXPECT_EQ(1, activeLayerCount()); } // High FPS is returned once enough history has been recorded. for (int i = 0; i < 10; i++) { - history().record(layer.get(), 0, isHDR, mTime); + history().record(layer.get(), 0, mTime); EXPECT_FLOAT_EQ(HI_FPS, history().summarize(mTime).maxRefreshRate); EXPECT_EQ(1, activeLayerCount()); } @@ -84,29 +89,25 @@ TEST_F(LayerHistoryTest, oneLayer) { TEST_F(LayerHistoryTest, oneHDRLayer) { const auto layer = createLayer(); - constexpr bool isHDR = true; EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); EXPECT_EQ(1, layerCount()); EXPECT_EQ(0, activeLayerCount()); - history().record(layer.get(), 0, isHDR, mTime); + history().record(layer.get(), 0, mTime); auto summary = history().summarize(mTime); EXPECT_FLOAT_EQ(0, summary.maxRefreshRate); - EXPECT_TRUE(summary.isHDR); EXPECT_EQ(1, activeLayerCount()); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(false)); summary = history().summarize(mTime); EXPECT_FLOAT_EQ(0, summary.maxRefreshRate); - EXPECT_FALSE(summary.isHDR); EXPECT_EQ(0, activeLayerCount()); } TEST_F(LayerHistoryTest, explicitTimestamp) { const auto layer = createLayer(); - constexpr bool isHDR = false; EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); EXPECT_EQ(1, layerCount()); @@ -114,7 +115,7 @@ TEST_F(LayerHistoryTest, explicitTimestamp) { nsecs_t time = mTime; for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { - history().record(layer.get(), time, isHDR, time); + history().record(layer.get(), time, time); time += LO_FPS_PERIOD; } @@ -127,7 +128,6 @@ TEST_F(LayerHistoryTest, multipleLayers) { auto layer1 = createLayer(); auto layer2 = createLayer(); auto layer3 = createLayer(); - constexpr bool isHDR = false; EXPECT_CALL(*layer1, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*layer2, isVisible()).WillRepeatedly(Return(true)); @@ -141,7 +141,7 @@ TEST_F(LayerHistoryTest, multipleLayers) { // layer1 is active but infrequent. for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { - history().record(layer1.get(), time, isHDR, time); + history().record(layer1.get(), time, time); time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); } @@ -151,12 +151,12 @@ TEST_F(LayerHistoryTest, multipleLayers) { // layer2 is frequent and has high refresh rate. for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { - history().record(layer2.get(), time, isHDR, time); + history().record(layer2.get(), time, time); time += HI_FPS_PERIOD; } // layer1 is still active but infrequent. - history().record(layer1.get(), time, isHDR, time); + history().record(layer1.get(), time, time); EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time).maxRefreshRate); EXPECT_EQ(2, activeLayerCount()); @@ -165,7 +165,7 @@ TEST_F(LayerHistoryTest, multipleLayers) { // layer1 is no longer active. // layer2 is frequent and has low refresh rate. for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { - history().record(layer2.get(), time, isHDR, time); + history().record(layer2.get(), time, time); time += LO_FPS_PERIOD; } @@ -178,10 +178,10 @@ TEST_F(LayerHistoryTest, multipleLayers) { constexpr int RATIO = LO_FPS_PERIOD / HI_FPS_PERIOD; for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - 1; i++) { if (i % RATIO == 0) { - history().record(layer2.get(), time, isHDR, time); + history().record(layer2.get(), time, time); } - history().record(layer3.get(), time, isHDR, time); + history().record(layer3.get(), time, time); time += HI_FPS_PERIOD; } @@ -190,7 +190,7 @@ TEST_F(LayerHistoryTest, multipleLayers) { EXPECT_EQ(2, frequentLayerCount(time)); // layer3 becomes recently active. - history().record(layer3.get(), time, isHDR, time); + history().record(layer3.get(), time, time); EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time).maxRefreshRate); EXPECT_EQ(2, activeLayerCount()); EXPECT_EQ(2, frequentLayerCount(time)); @@ -205,7 +205,7 @@ TEST_F(LayerHistoryTest, multipleLayers) { // layer2 still has low refresh rate. // layer3 becomes inactive. for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { - history().record(layer2.get(), time, isHDR, time); + history().record(layer2.get(), time, time); time += LO_FPS_PERIOD; } @@ -222,7 +222,7 @@ TEST_F(LayerHistoryTest, multipleLayers) { // layer3 becomes active and has high refresh rate. for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { - history().record(layer3.get(), time, isHDR, time); + history().record(layer3.get(), time, time); time += HI_FPS_PERIOD; } diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp index f315a8a86c..546e65c1ea 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -30,27 +30,19 @@ using testing::_; namespace android { namespace scheduler { -using RefreshRateType = RefreshRateConfigs::RefreshRateType; using RefreshRate = RefreshRateConfigs::RefreshRate; class RefreshRateConfigsTest : public testing::Test { protected: - static constexpr int CONFIG_ID_60 = 0; - static constexpr hwc2_config_t HWC2_CONFIG_ID_60 = 0; - static constexpr int CONFIG_ID_90 = 1; - static constexpr hwc2_config_t HWC2_CONFIG_ID_90 = 1; + static inline const HwcConfigIndexType HWC_CONFIG_ID_60 = HwcConfigIndexType(0); + static inline const HwcConfigIndexType HWC_CONFIG_ID_90 = HwcConfigIndexType(1); + static inline const HwcConfigGroupType HWC_GROUP_ID_0 = HwcConfigGroupType(0); + static inline const HwcConfigGroupType HWC_GROUP_ID_1 = HwcConfigGroupType(1); static constexpr int64_t VSYNC_60 = 16666667; static constexpr int64_t VSYNC_90 = 11111111; RefreshRateConfigsTest(); ~RefreshRateConfigsTest(); - - void assertRatesEqual(const RefreshRate& left, const RefreshRate& right) { - ASSERT_EQ(left.configId, right.configId); - ASSERT_EQ(left.name, right.name); - ASSERT_EQ(left.fps, right.fps); - ASSERT_EQ(left.vsyncPeriod, right.vsyncPeriod); - } }; RefreshRateConfigsTest::RefreshRateConfigsTest() { @@ -69,40 +61,173 @@ namespace { /* ------------------------------------------------------------------------ * Test cases */ -TEST_F(RefreshRateConfigsTest, oneDeviceConfig_isRejected) { - std::vector configs{{HWC2_CONFIG_ID_60, VSYNC_60}}; +TEST_F(RefreshRateConfigsTest, oneDeviceConfig_SwitchingSupported) { + std::vector configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}}}; auto refreshRateConfigs = std::make_unique(/*refreshRateSwitching=*/true, configs, - /*currentConfig=*/0); + /*currentConfigId=*/HWC_CONFIG_ID_60); + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); +} + +TEST_F(RefreshRateConfigsTest, oneDeviceConfig_SwitchingNotSupported) { + std::vector configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/false, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); ASSERT_FALSE(refreshRateConfigs->refreshRateSwitchingSupported()); } TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap) { - std::vector configs{{HWC2_CONFIG_ID_60, VSYNC_60}, - {HWC2_CONFIG_ID_90, VSYNC_90}}; + std::vector configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; auto refreshRateConfigs = std::make_unique(/*refreshRateSwitching=*/true, configs, - /*currentConfig=*/0); + /*currentConfigId=*/HWC_CONFIG_ID_60); ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); - const auto& rates = refreshRateConfigs->getRefreshRateMap(); - ASSERT_EQ(2, rates.size()); - const auto& defaultRate = rates.find(RefreshRateType::DEFAULT); - const auto& performanceRate = rates.find(RefreshRateType::PERFORMANCE); - ASSERT_NE(rates.end(), defaultRate); - ASSERT_NE(rates.end(), performanceRate); - - RefreshRate expectedDefaultConfig = {CONFIG_ID_60, "60fps", 60, VSYNC_60, HWC2_CONFIG_ID_60}; - assertRatesEqual(expectedDefaultConfig, defaultRate->second); - RefreshRate expectedPerformanceConfig = {CONFIG_ID_90, "90fps", 90, VSYNC_90, - HWC2_CONFIG_ID_90}; - assertRatesEqual(expectedPerformanceConfig, performanceRate->second); - - assertRatesEqual(expectedDefaultConfig, - refreshRateConfigs->getRefreshRateFromType(RefreshRateType::DEFAULT)); - assertRatesEqual(expectedPerformanceConfig, - refreshRateConfigs->getRefreshRateFromType(RefreshRateType::PERFORMANCE)); + + const auto minRate = refreshRateConfigs->getMinRefreshRate(); + const auto performanceRate = refreshRateConfigs->getMaxRefreshRate(); + + RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + ASSERT_EQ(expectedDefaultConfig, minRate); + RefreshRate expectedPerformanceConfig = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", + 90}; + ASSERT_EQ(expectedPerformanceConfig, performanceRate); + + const auto minRateByPolicy = refreshRateConfigs->getMinRefreshRateByPolicy(); + const auto performanceRateByPolicy = refreshRateConfigs->getMaxRefreshRateByPolicy(); + ASSERT_EQ(minRateByPolicy, minRate); + ASSERT_EQ(performanceRateByPolicy, performanceRate); } + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap_differentGroups) { + std::vector configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_1, VSYNC_90}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/true, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + const auto minRate = refreshRateConfigs->getMinRefreshRateByPolicy(); + const auto performanceRate = refreshRateConfigs->getMaxRefreshRate(); + const auto minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy(); + const auto performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy(); + + RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + ASSERT_EQ(expectedDefaultConfig, minRate); + ASSERT_EQ(expectedDefaultConfig, minRate60); + ASSERT_EQ(expectedDefaultConfig, performanceRate60); + + refreshRateConfigs->setPolicy(HWC_CONFIG_ID_90, 60, 90); + refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); + + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + const auto minRate90 = refreshRateConfigs->getMinRefreshRateByPolicy(); + const auto performanceRate90 = refreshRateConfigs->getMaxRefreshRateByPolicy(); + + RefreshRate expectedPerformanceConfig = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_1, "90fps", + 90}; + ASSERT_EQ(expectedPerformanceConfig, performanceRate); + ASSERT_EQ(expectedPerformanceConfig, minRate90); + ASSERT_EQ(expectedPerformanceConfig, performanceRate90); +} + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_policyChange) { + std::vector configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/true, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + auto minRate = refreshRateConfigs->getMinRefreshRateByPolicy(); + auto performanceRate = refreshRateConfigs->getMaxRefreshRateByPolicy(); + + RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + ASSERT_EQ(expectedDefaultConfig, minRate); + RefreshRate expectedPerformanceConfig = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", + 90}; + ASSERT_EQ(expectedPerformanceConfig, performanceRate); + + refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 60, 60); + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + + auto minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy(); + auto performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy(); + ASSERT_EQ(expectedDefaultConfig, minRate60); + ASSERT_EQ(expectedDefaultConfig, performanceRate60); +} + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getCurrentRefreshRate) { + std::vector configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/true, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); + { + auto current = refreshRateConfigs->getCurrentRefreshRate(); + EXPECT_EQ(current.configId, HWC_CONFIG_ID_60); + } + + refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); + { + auto current = refreshRateConfigs->getCurrentRefreshRate(); + EXPECT_EQ(current.configId, HWC_CONFIG_ID_90); + } + + refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 90, 90); + { + auto current = refreshRateConfigs->getCurrentRefreshRate(); + EXPECT_EQ(current.configId, HWC_CONFIG_ID_90); + } +} + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContent) { + std::vector configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/true, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + + RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + + ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(90.0f)); + ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(60.0f)); + ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(45.0f)); + ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(30.0f)); + ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(24.0f)); + + refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 60, 60); + ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(90.0f)); + ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(60.0f)); + ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(45.0f)); + ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(30.0f)); + ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(24.0f)); + + refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 90, 90); + ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(90.0f)); + ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(60.0f)); + ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(45.0f)); + ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(30.0f)); + ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(24.0f)); + refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 0, 120); + ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(90.0f)); + ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(60.0f)); + ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(45.0f)); + ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(30.0f)); + ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(24.0f)); +} + } // namespace } // namespace scheduler } // namespace android diff --git a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp index cec0b32a6b..ef4699f628 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp @@ -33,8 +33,9 @@ namespace scheduler { class RefreshRateStatsTest : public testing::Test { protected: - static constexpr int CONFIG_ID_90 = 0; - static constexpr int CONFIG_ID_60 = 1; + static inline const auto CONFIG_ID_0 = HwcConfigIndexType(0); + static inline const auto CONFIG_ID_1 = HwcConfigIndexType(1); + static inline const auto CONFIG_GROUP_0 = HwcConfigGroupType(0); static constexpr int64_t VSYNC_90 = 11111111; static constexpr int64_t VSYNC_60 = 16666667; @@ -43,10 +44,10 @@ protected: void init(const std::vector& configs) { mRefreshRateConfigs = std::make_unique( - /*refreshRateSwitching=*/true, configs, /*currentConfig=*/0); + /*refreshRateSwitching=*/true, configs, /*currentConfig=*/CONFIG_ID_0); mRefreshRateStats = std::make_unique(*mRefreshRateConfigs, mTimeStats, - /*currentConfig=*/0, + /*currentConfigId=*/CONFIG_ID_0, /*currentPowerMode=*/HWC_POWER_MODE_OFF); } @@ -72,7 +73,7 @@ namespace { * Test cases */ TEST_F(RefreshRateStatsTest, oneConfigTest) { - init({{CONFIG_ID_90, VSYNC_90}}); + init({{{CONFIG_ID_0, CONFIG_GROUP_0, VSYNC_90}}}); EXPECT_CALL(mTimeStats, recordRefreshRate(0, _)).Times(AtLeast(1)); EXPECT_CALL(mTimeStats, recordRefreshRate(90, _)).Times(AtLeast(1)); @@ -91,7 +92,7 @@ TEST_F(RefreshRateStatsTest, oneConfigTest) { EXPECT_LT(screenOff, times["ScreenOff"]); EXPECT_EQ(0u, times.count("90fps")); - mRefreshRateStats->setConfigMode(CONFIG_ID_90); + mRefreshRateStats->setConfigMode(CONFIG_ID_0); mRefreshRateStats->setPowerMode(HWC_POWER_MODE_NORMAL); screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); @@ -107,7 +108,7 @@ TEST_F(RefreshRateStatsTest, oneConfigTest) { EXPECT_LT(screenOff, times["ScreenOff"]); EXPECT_EQ(ninety, times["90fps"]); - mRefreshRateStats->setConfigMode(CONFIG_ID_90); + mRefreshRateStats->setConfigMode(CONFIG_ID_0); screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); @@ -118,7 +119,7 @@ TEST_F(RefreshRateStatsTest, oneConfigTest) { } TEST_F(RefreshRateStatsTest, twoConfigsTest) { - init({{CONFIG_ID_90, VSYNC_90}, {CONFIG_ID_60, VSYNC_60}}); + init({{{CONFIG_ID_0, CONFIG_GROUP_0, VSYNC_90}, {CONFIG_ID_1, CONFIG_GROUP_0, VSYNC_60}}}); EXPECT_CALL(mTimeStats, recordRefreshRate(0, _)).Times(AtLeast(1)); EXPECT_CALL(mTimeStats, recordRefreshRate(60, _)).Times(AtLeast(1)); @@ -137,7 +138,7 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { times = mRefreshRateStats->getTotalTimes(); EXPECT_LT(screenOff, times["ScreenOff"]); - mRefreshRateStats->setConfigMode(CONFIG_ID_90); + mRefreshRateStats->setConfigMode(CONFIG_ID_0); mRefreshRateStats->setPowerMode(HWC_POWER_MODE_NORMAL); screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); @@ -147,7 +148,7 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { EXPECT_LT(0, times["90fps"]); // When power mode is normal, time for configs updates. - mRefreshRateStats->setConfigMode(CONFIG_ID_60); + mRefreshRateStats->setConfigMode(CONFIG_ID_1); int ninety = mRefreshRateStats->getTotalTimes()["90fps"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); @@ -156,7 +157,7 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { ASSERT_EQ(1u, times.count("60fps")); EXPECT_LT(0, times["60fps"]); - mRefreshRateStats->setConfigMode(CONFIG_ID_90); + mRefreshRateStats->setConfigMode(CONFIG_ID_0); int sixty = mRefreshRateStats->getTotalTimes()["60fps"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); @@ -164,7 +165,7 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { EXPECT_LT(ninety, times["90fps"]); EXPECT_EQ(sixty, times["60fps"]); - mRefreshRateStats->setConfigMode(CONFIG_ID_60); + mRefreshRateStats->setConfigMode(CONFIG_ID_1); ninety = mRefreshRateStats->getTotalTimes()["90fps"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); @@ -175,7 +176,7 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { // Because the power mode is not HWC_POWER_MODE_NORMAL, switching the config // does not update refresh rates that come from the config. mRefreshRateStats->setPowerMode(HWC_POWER_MODE_DOZE); - mRefreshRateStats->setConfigMode(CONFIG_ID_90); + mRefreshRateStats->setConfigMode(CONFIG_ID_0); sixty = mRefreshRateStats->getTotalTimes()["60fps"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); @@ -183,7 +184,7 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { EXPECT_EQ(ninety, times["90fps"]); EXPECT_EQ(sixty, times["60fps"]); - mRefreshRateStats->setConfigMode(CONFIG_ID_60); + mRefreshRateStats->setConfigMode(CONFIG_ID_1); screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp index b4cc1e15e8..40536abc5d 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp @@ -50,10 +50,11 @@ SchedulerTest::SchedulerTest() { ::testing::UnitTest::GetInstance()->current_test_info(); ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); - std::vector configs{{/*hwcId=*/0, 16666667}}; - mRefreshRateConfigs = - std::make_unique(/*refreshRateSwitching=*/false, configs, - /*currentConfig=*/0); + std::vector configs{ + {{HwcConfigIndexType(0), HwcConfigGroupType(0), 16666667}}}; + mRefreshRateConfigs = std::make_unique< + scheduler::RefreshRateConfigs>(/*refreshRateSwitching=*/false, configs, + /*currentConfig=*/HwcConfigIndexType(0)); mScheduler = std::make_unique(*mRefreshRateConfigs); diff --git a/services/surfaceflinger/tests/unittests/StrongTypingTest.cpp b/services/surfaceflinger/tests/unittests/StrongTypingTest.cpp index b9ddcd77d0..54068797a1 100644 --- a/services/surfaceflinger/tests/unittests/StrongTypingTest.cpp +++ b/services/surfaceflinger/tests/unittests/StrongTypingTest.cpp @@ -56,18 +56,18 @@ TEST(StrongTypeTest, addition) { EXPECT_THAT(f1 + f2, Eq(FunkyType(32))); EXPECT_THAT(f2 + f1, Eq(FunkyType(32))); - EXPECT_THAT(++f1, Eq(11)); - EXPECT_THAT(f1, Eq(11)); - EXPECT_THAT(f1++, Eq(11)); - EXPECT_THAT(f1++, Eq(12)); - EXPECT_THAT(f1, Eq(13)); + EXPECT_THAT(++f1.value(), Eq(11)); + EXPECT_THAT(f1.value(), Eq(11)); + EXPECT_THAT(f1++.value(), Eq(11)); + EXPECT_THAT(f1++.value(), Eq(12)); + EXPECT_THAT(f1.value(), Eq(13)); auto f3 = f1; EXPECT_THAT(f1, Eq(f3)); EXPECT_THAT(f1, Lt(f2)); f3 += f1; - EXPECT_THAT(f1, Eq(13)); - EXPECT_THAT(f3, Eq(26)); + EXPECT_THAT(f1.value(), Eq(13)); + EXPECT_THAT(f3.value(), Eq(26)); } } // namespace android diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 94fc5f7273..c4b8408202 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -193,15 +193,15 @@ public: std::unique_ptr eventControlThread, std::unique_ptr appEventThread, std::unique_ptr sfEventThread) { - std::vector configs{{/*hwcId=*/0, 16666667}}; - mFlinger->mRefreshRateConfigs = - std::make_unique(/*refreshRateSwitching=*/false, - configs, /*currentConfig=*/0); - mFlinger->mRefreshRateStats = - std::make_unique(*mFlinger->mRefreshRateConfigs, - *mFlinger->mTimeStats, - /*currentConfig=*/0, - /*powerMode=*/HWC_POWER_MODE_OFF); + std::vector configs{ + {{HwcConfigIndexType(0), HwcConfigGroupType(0), 16666667}}}; + mFlinger->mRefreshRateConfigs = std::make_unique< + scheduler::RefreshRateConfigs>(/*refreshRateSwitching=*/false, configs, + /*currentConfig=*/HwcConfigIndexType(0)); + mFlinger->mRefreshRateStats = std::make_unique< + scheduler::RefreshRateStats>(*mFlinger->mRefreshRateConfigs, *mFlinger->mTimeStats, + /*currentConfig=*/HwcConfigIndexType(0), + /*powerMode=*/HWC_POWER_MODE_OFF); mScheduler = new TestableScheduler(std::move(primaryDispSync), std::move(eventControlThread), @@ -429,6 +429,7 @@ public: static constexpr int32_t DEFAULT_WIDTH = 1920; static constexpr int32_t DEFAULT_HEIGHT = 1280; static constexpr int32_t DEFAULT_REFRESH_RATE = 16'666'666; + static constexpr int32_t DEFAULT_CONFIG_GROUP = 7; static constexpr int32_t DEFAULT_DPI = 320; static constexpr int32_t DEFAULT_ACTIVE_CONFIG = 0; static constexpr int32_t DEFAULT_POWER_MODE = 2; @@ -452,7 +453,7 @@ public: return *this; } - auto& setRefreshRate(int32_t refreshRate) { + auto& setRefreshRate(uint32_t refreshRate) { mRefreshRate = refreshRate; return *this; } @@ -499,6 +500,7 @@ public: config.setVsyncPeriod(mRefreshRate); config.setDpiX(mDpiX); config.setDpiY(mDpiY); + config.setConfigGroup(mConfigGroup); display->mutableConfigs().emplace(mActiveConfig, config.build()); display->mutableIsConnected() = true; display->setPowerMode(static_cast(mPowerMode)); @@ -522,8 +524,9 @@ public: hwc2_display_t mHwcDisplayId = DEFAULT_HWC_DISPLAY_ID; int32_t mWidth = DEFAULT_WIDTH; int32_t mHeight = DEFAULT_HEIGHT; - int32_t mRefreshRate = DEFAULT_REFRESH_RATE; + uint32_t mRefreshRate = DEFAULT_REFRESH_RATE; int32_t mDpiX = DEFAULT_DPI; + int32_t mConfigGroup = DEFAULT_CONFIG_GROUP; int32_t mDpiY = DEFAULT_DPI; int32_t mActiveConfig = DEFAULT_ACTIVE_CONFIG; int32_t mPowerMode = DEFAULT_POWER_MODE; diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h index ed35ebf2b6..f7c380490b 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h +++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h @@ -33,7 +33,7 @@ public: MOCK_METHOD0(onScreenReleased, void()); MOCK_METHOD0(onScreenAcquired, void()); MOCK_METHOD2(onHotplugReceived, void(PhysicalDisplayId, bool)); - MOCK_METHOD2(onConfigChanged, void(PhysicalDisplayId, int32_t)); + MOCK_METHOD2(onConfigChanged, void(PhysicalDisplayId, HwcConfigIndexType)); MOCK_CONST_METHOD1(dump, void(std::string&)); MOCK_METHOD1(setPhaseOffset, void(nsecs_t phaseOffset)); MOCK_METHOD1(registerDisplayEventConnection, -- cgit v1.2.3-59-g8ed1b From 2cb8b62ef3264c0b8b0429ba1a86d04307d31ab8 Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Mon, 2 Dec 2019 18:55:33 -0800 Subject: SurfaceFlinger: show refresh rate instead of color in overlay Change the RefreshRateOverlay to show the actual refresh rate fps instead of just a color. Change-Id: Ifd6e419b1534736de466d67e9e95042e62c730c6 Test: adb shell service call SurfaceFlinger 1034 i32 1 Bug: 129297325 --- services/surfaceflinger/RefreshRateOverlay.cpp | 159 +++++++++++++++++++++++-- services/surfaceflinger/RefreshRateOverlay.h | 32 ++++- services/surfaceflinger/SurfaceFlinger.cpp | 8 +- 3 files changed, 186 insertions(+), 13 deletions(-) (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 38a80a798a..6598bd861b 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -18,26 +18,139 @@ #include "Client.h" #include "Layer.h" +#include + +#undef LOG_TAG +#define LOG_TAG "RefreshRateOverlay" + namespace android { +void RefreshRateOverlay::SevenSegmentDrawer::drawRect(const Rect& r, const half4& color, + const sp& buffer, + uint8_t* pixels) { + for (int32_t j = r.top; j < r.bottom; j++) { + if (j >= buffer->getHeight()) { + break; + } + + for (int32_t i = r.left; i < r.right; i++) { + if (i >= buffer->getWidth()) { + break; + } + + uint8_t* iter = pixels + 4 * (i + (buffer->getStride() * j)); + iter[0] = uint8_t(color.r * 255); + iter[1] = uint8_t(color.g * 255); + iter[2] = uint8_t(color.b * 255); + iter[3] = uint8_t(color.a * 255); + } + } +} + +void RefreshRateOverlay::SevenSegmentDrawer::drawSegment(Segment segment, int left, + const half4& color, + const sp& buffer, + uint8_t* pixels) { + const Rect rect = [&]() { + switch (segment) { + case Segment::Upper: + return Rect(left, 0, left + DIGIT_WIDTH, DIGIT_SPACE); + case Segment::UpperLeft: + return Rect(left, 0, left + DIGIT_SPACE, DIGIT_HEIGHT / 2); + case Segment::UpperRight: + return Rect(left + DIGIT_WIDTH - DIGIT_SPACE, 0, left + DIGIT_WIDTH, + DIGIT_HEIGHT / 2); + case Segment::Middle: + return Rect(left, DIGIT_HEIGHT / 2 - DIGIT_SPACE / 2, left + DIGIT_WIDTH, + DIGIT_HEIGHT / 2 + DIGIT_SPACE / 2); + case Segment::LowerLeft: + return Rect(left, DIGIT_HEIGHT / 2, left + DIGIT_SPACE, DIGIT_HEIGHT); + case Segment::LowerRight: + return Rect(left + DIGIT_WIDTH - DIGIT_SPACE, DIGIT_HEIGHT / 2, left + DIGIT_WIDTH, + DIGIT_HEIGHT); + case Segment::Buttom: + return Rect(left, DIGIT_HEIGHT - DIGIT_SPACE, left + DIGIT_WIDTH, DIGIT_HEIGHT); + } + }(); + + drawRect(rect, color, buffer, pixels); +} + +void RefreshRateOverlay::SevenSegmentDrawer::drawDigit(int digit, int left, const half4& color, + const sp& buffer, + uint8_t* pixels) { + if (digit < 0 || digit > 9) return; + + if (digit == 0 || digit == 2 || digit == 3 || digit == 5 || digit == 6 || digit == 7 || + digit == 8 || digit == 9) + drawSegment(Segment::Upper, left, color, buffer, pixels); + if (digit == 0 || digit == 4 || digit == 5 || digit == 6 || digit == 8 || digit == 9) + drawSegment(Segment::UpperLeft, left, color, buffer, pixels); + if (digit == 0 || digit == 1 || digit == 2 || digit == 3 || digit == 4 || digit == 7 || + digit == 8 || digit == 9) + drawSegment(Segment::UpperRight, left, color, buffer, pixels); + if (digit == 2 || digit == 3 || digit == 4 || digit == 5 || digit == 6 || digit == 8 || + digit == 9) + drawSegment(Segment::Middle, left, color, buffer, pixels); + if (digit == 0 || digit == 2 || digit == 6 || digit == 8) + drawSegment(Segment::LowerLeft, left, color, buffer, pixels); + if (digit == 0 || digit == 1 || digit == 3 || digit == 4 || digit == 5 || digit == 6 || + digit == 7 || digit == 8 || digit == 9) + drawSegment(Segment::LowerRight, left, color, buffer, pixels); + if (digit == 0 || digit == 2 || digit == 3 || digit == 5 || digit == 6 || digit == 8 || + digit == 9) + drawSegment(Segment::Buttom, left, color, buffer, pixels); +} + +sp RefreshRateOverlay::SevenSegmentDrawer::drawNumber(int number, + const half4& color) { + if (number < 0 || number > 1000) return nullptr; + + const auto hundreds = number / 100; + const auto tens = (number / 10) % 10; + const auto ones = number % 10; + + sp buffer = + new GraphicBuffer(BUFFER_WIDTH, BUFFER_HEIGHT, HAL_PIXEL_FORMAT_RGBA_8888, 1, + GRALLOC_USAGE_SW_WRITE_RARELY, "RefreshRateOverlayBuffer"); + uint8_t* pixels; + buffer->lock(GRALLOC_USAGE_SW_WRITE_RARELY, reinterpret_cast(&pixels)); + int left = 0; + if (hundreds != 0) { + drawDigit(hundreds, left, color, buffer, pixels); + left += DIGIT_WIDTH + DIGIT_SPACE; + } + + if (tens != 0) { + drawDigit(tens, left, color, buffer, pixels); + left += DIGIT_WIDTH + DIGIT_SPACE; + } + + drawDigit(ones, left, color, buffer, pixels); + buffer->unlock(); + return buffer; +} + RefreshRateOverlay::RefreshRateOverlay(SurfaceFlinger& flinger) : mFlinger(flinger), mClient(new Client(&mFlinger)) { createLayer(); + primeCache(); } bool RefreshRateOverlay::createLayer() { const status_t ret = - mFlinger.createLayer(String8("RefreshRateOverlay"), mClient, 0, 0, - PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceColor, - LayerMetadata(), &mIBinder, &mGbp, nullptr); + mFlinger.createLayer(String8("RefreshRateOverlay"), mClient, + SevenSegmentDrawer::getWidth(), SevenSegmentDrawer::getHeight(), + PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceBufferState, LayerMetadata(), + &mIBinder, &mGbp, nullptr); if (ret) { - ALOGE("failed to create color layer"); + ALOGE("failed to create buffer state layer"); return false; } Mutex::Autolock _l(mFlinger.mStateLock); mLayer = mClient->getLayerUser(mIBinder); - mLayer->setCrop_legacy(Rect(50, 70, 200, 100)); // setting Layer's Z requires resorting layersSortedByZ ssize_t idx = mFlinger.mCurrentState.layersSortedByZ.indexOf(mLayer); @@ -49,9 +162,41 @@ bool RefreshRateOverlay::createLayer() { return true; } +void RefreshRateOverlay::primeCache() { + auto allRefreshRates = mFlinger.mRefreshRateConfigs->getAllRefreshRates(); + if (allRefreshRates.size() == 1) { + auto fps = allRefreshRates.begin()->second.fps; + half4 color = {LOW_FPS_COLOR, ALPHA}; + mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color)); + return; + } + + std::vector supportedFps; + supportedFps.reserve(allRefreshRates.size()); + for (auto [ignored, refreshRate] : allRefreshRates) { + supportedFps.push_back(refreshRate.fps); + } + + std::sort(supportedFps.begin(), supportedFps.end()); + const auto mLowFps = supportedFps[0]; + const auto mHighFps = supportedFps[supportedFps.size() - 1]; + for (auto fps : supportedFps) { + const auto fpsScale = float(fps - mLowFps) / (mHighFps - mLowFps); + half4 color; + color.r = HIGH_FPS_COLOR.r * fpsScale + LOW_FPS_COLOR.r * (1 - fpsScale); + color.g = HIGH_FPS_COLOR.g * fpsScale + LOW_FPS_COLOR.g * (1 - fpsScale); + color.b = HIGH_FPS_COLOR.b * fpsScale + LOW_FPS_COLOR.b * (1 - fpsScale); + color.a = ALPHA; + mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color)); + } +} + void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { - const half3& color = (refreshRate.fps > 65.0f) ? GREEN : RED; - mLayer->setColor(color); + auto buffer = mBufferCache[refreshRate.fps]; + mLayer->setBuffer(buffer, 0, 0, {}); + mLayer->setFrame(Rect(20, 120, 20 + SevenSegmentDrawer::getWidth(), + 120 + SevenSegmentDrawer::getHeight())); + mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } diff --git a/services/surfaceflinger/RefreshRateOverlay.h b/services/surfaceflinger/RefreshRateOverlay.h index 414bc47ac9..6d34df220c 100644 --- a/services/surfaceflinger/RefreshRateOverlay.h +++ b/services/surfaceflinger/RefreshRateOverlay.h @@ -28,7 +28,32 @@ public: void changeRefreshRate(const RefreshRate& refreshRate); private: + class SevenSegmentDrawer { + public: + static sp drawNumber(int number, const half4& color); + static uint32_t getHeight() { return BUFFER_HEIGHT; } + static uint32_t getWidth() { return BUFFER_WIDTH; } + + private: + enum class Segment { Upper, UpperLeft, UpperRight, Middle, LowerLeft, LowerRight, Buttom }; + + static void drawRect(const Rect& r, const half4& color, const sp& buffer, + uint8_t* pixels); + static void drawSegment(Segment segment, int left, const half4& color, + const sp& buffer, uint8_t* pixels); + static void drawDigit(int digit, int left, const half4& color, + const sp& buffer, uint8_t* pixels); + + static constexpr uint32_t DIGIT_HEIGHT = 100; + static constexpr uint32_t DIGIT_WIDTH = 64; + static constexpr uint32_t DIGIT_SPACE = 16; + static constexpr uint32_t BUFFER_HEIGHT = DIGIT_HEIGHT; + static constexpr uint32_t BUFFER_WIDTH = + 3 * DIGIT_WIDTH + 2 * DIGIT_SPACE; // Digit|Space|Digit|Space|Digit + }; + bool createLayer(); + void primeCache(); SurfaceFlinger& mFlinger; sp mClient; @@ -36,8 +61,11 @@ private: sp mIBinder; sp mGbp; - const half3 RED = half3(1.0f, 0.0f, 0.0f); - const half3 GREEN = half3(0.0f, 1.0f, 0.0f); + std::unordered_map> mBufferCache; + + static constexpr float ALPHA = 0.8f; + const half3 LOW_FPS_COLOR = half3(1.0f, 0.0f, 0.0f); + const half3 HIGH_FPS_COLOR = half3(0.0f, 1.0f, 0.0f); }; }; // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 71ecf88213..3403b280f0 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4831,15 +4831,15 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r return NO_ERROR; } case 1034: { - // TODO(b/129297325): expose this via developer menu option n = data.readInt32(); - if (n && !mRefreshRateOverlay && - mRefreshRateConfigs->refreshRateSwitchingSupported()) { + if (n == 1 && !mRefreshRateOverlay) { mRefreshRateOverlay = std::make_unique(*this); auto current = mRefreshRateConfigs->getCurrentRefreshRate(); mRefreshRateOverlay->changeRefreshRate(current); - } else if (!n) { + } else if (n == 0) { mRefreshRateOverlay.reset(); + } else { + reply->writeBool(mRefreshRateOverlay != nullptr); } return NO_ERROR; } -- cgit v1.2.3-59-g8ed1b From 8be02e37686a3101f8a6d6137486a81e8cd5bfdc Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Mon, 6 Jan 2020 16:59:14 -0800 Subject: SurfaceFlinger: relative size RefreshRateOverlay Use display size to calculate the overlay size. Test: Enable refresh rate overlay Change-Id: I4b53c8f8137ec9b59867079d70e1016e2a57a2e6 --- services/surfaceflinger/RefreshRateOverlay.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 6598bd861b..c69859e32a 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -192,10 +192,20 @@ void RefreshRateOverlay::primeCache() { } void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { + const auto display = mFlinger.getDefaultDisplayDeviceLocked(); + if (!display) { + return; + } + + const int32_t left = display->getWidth() / 32; + const int32_t top = display->getHeight() / 32; + const int32_t right = left + display->getWidth() / 8; + const int32_t buttom = top + display->getHeight() / 32; + auto buffer = mBufferCache[refreshRate.fps]; mLayer->setBuffer(buffer, 0, 0, {}); - mLayer->setFrame(Rect(20, 120, 20 + SevenSegmentDrawer::getWidth(), - 120 + SevenSegmentDrawer::getHeight())); + + mLayer->setFrame(Rect(left, top, right, buttom)); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } -- cgit v1.2.3-59-g8ed1b From b0dbdaaf3b1a42ab072af9d111d56900b1197af4 Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Mon, 6 Jan 2020 16:19:42 -0800 Subject: SurfaceFlinger: Enable -WConversion in Android.bp Enable global -WConversion in Android.bp and turn it off in individual files. This is the first step to enable -WConversion in SurfaceFlinger. Test: boot Bug: 129481165 Change-Id: Ia752df39ef380bde71705a32582d618242c466f7 --- libs/renderengine/tests/RenderEngineTest.cpp | 7 +++++++ services/surfaceflinger/Android.bp | 1 + services/surfaceflinger/BufferLayer.cpp | 7 +++++++ services/surfaceflinger/BufferLayerConsumer.cpp | 7 +++++++ services/surfaceflinger/BufferQueueLayer.cpp | 7 +++++++ services/surfaceflinger/BufferStateLayer.cpp | 7 +++++++ services/surfaceflinger/Client.cpp | 7 +++++++ services/surfaceflinger/ColorLayer.cpp | 7 +++++++ .../CompositionEngine/mock/Display.cpp | 7 +++++++ .../CompositionEngine/mock/Layer.cpp | 7 +++++++ .../CompositionEngine/mock/LayerFE.cpp | 7 +++++++ .../CompositionEngine/mock/Output.cpp | 7 +++++++ .../CompositionEngine/mock/OutputLayer.cpp | 7 +++++++ .../CompositionEngine/src/CompositionEngine.cpp | 7 +++++++ .../CompositionEngine/src/Display.cpp | 7 +++++++ .../CompositionEngine/src/HwcBufferCache.cpp | 7 +++++++ .../surfaceflinger/CompositionEngine/src/Layer.cpp | 7 +++++++ .../src/LayerFECompositionState.cpp | 7 +++++++ .../CompositionEngine/src/Output.cpp | 7 +++++++ .../CompositionEngine/src/OutputLayer.cpp | 7 +++++++ .../src/OutputLayerCompositionState.cpp | 7 +++++++ .../CompositionEngine/src/RenderSurface.cpp | 7 +++++++ .../tests/CompositionEngineTest.cpp | 7 +++++++ .../CompositionEngine/tests/DisplayTest.cpp | 7 +++++++ .../CompositionEngine/tests/LayerTest.cpp | 7 +++++++ .../CompositionEngine/tests/OutputLayerTest.cpp | 7 +++++++ .../CompositionEngine/tests/OutputTest.cpp | 7 +++++++ .../CompositionEngine/tests/RenderSurfaceTest.cpp | 7 +++++++ services/surfaceflinger/ContainerLayer.cpp | 7 +++++++ services/surfaceflinger/DisplayDevice.cpp | 7 +++++++ .../surfaceflinger/DisplayHardware/ComposerHal.cpp | 7 +++++++ .../DisplayHardware/DisplayIdentification.cpp | 7 +++++++ .../DisplayHardware/FramebufferSurface.cpp | 7 +++++++ services/surfaceflinger/DisplayHardware/HWC2.cpp | 7 +++++++ .../surfaceflinger/DisplayHardware/HWComposer.cpp | 7 +++++++ .../DisplayHardware/VirtualDisplaySurface.cpp | 7 +++++++ services/surfaceflinger/Effects/Daltonizer.cpp | 7 +++++++ services/surfaceflinger/EventLog/EventLog.cpp | 7 +++++++ .../surfaceflinger/FrameTracer/FrameTracer.cpp | 7 +++++++ services/surfaceflinger/FrameTracker.cpp | 7 +++++++ services/surfaceflinger/Layer.cpp | 7 +++++++ services/surfaceflinger/LayerProtoHelper.cpp | 7 +++++++ services/surfaceflinger/LayerRejecter.cpp | 7 +++++++ services/surfaceflinger/LayerVector.cpp | 7 +++++++ services/surfaceflinger/MonitoredProducer.cpp | 7 +++++++ services/surfaceflinger/RefreshRateOverlay.cpp | 7 +++++++ services/surfaceflinger/RegionSamplingThread.cpp | 7 +++++++ services/surfaceflinger/RenderArea.cpp | 23 ++++++++++++++++++++++ services/surfaceflinger/Scheduler/DispSync.cpp | 7 +++++++ .../surfaceflinger/Scheduler/DispSyncSource.cpp | 7 +++++++ .../Scheduler/EventControlThread.cpp | 7 +++++++ services/surfaceflinger/Scheduler/EventThread.cpp | 7 +++++++ services/surfaceflinger/Scheduler/LayerHistory.cpp | 7 +++++++ services/surfaceflinger/Scheduler/MessageQueue.cpp | 7 +++++++ services/surfaceflinger/Scheduler/PhaseOffsets.cpp | 7 +++++++ .../Scheduler/RefreshRateConfigs.cpp | 6 ++++++ services/surfaceflinger/Scheduler/Scheduler.cpp | 7 +++++++ .../surfaceflinger/Scheduler/SchedulerUtils.cpp | 7 +++++++ .../surfaceflinger/Scheduler/VSyncModulator.cpp | 7 +++++++ .../surfaceflinger/Scheduler/VSyncPredictor.cpp | 7 +++++++ services/surfaceflinger/SurfaceFlinger.cpp | 7 +++++++ .../SurfaceFlingerDefaultFactory.cpp | 7 +++++++ services/surfaceflinger/SurfaceFlingerFactory.cpp | 7 +++++++ services/surfaceflinger/SurfaceInterceptor.cpp | 7 +++++++ services/surfaceflinger/SurfaceTracing.cpp | 7 +++++++ services/surfaceflinger/TimeStats/TimeStats.cpp | 7 +++++++ .../surfaceflinger/TransactionCompletedThread.cpp | 7 +++++++ services/surfaceflinger/main_surfaceflinger.cpp | 7 +++++++ services/surfaceflinger/tests/BufferGenerator.cpp | 7 +++++++ services/surfaceflinger/tests/Credentials_test.cpp | 7 +++++++ .../tests/DereferenceSurfaceControl_test.cpp | 7 +++++++ .../surfaceflinger/tests/DisplayConfigs_test.cpp | 7 +++++++ .../surfaceflinger/tests/LayerCallback_test.cpp | 7 +++++++ .../tests/LayerRenderTypeTransaction_test.cpp | 7 +++++++ .../surfaceflinger/tests/LayerTransaction_test.cpp | 7 +++++++ .../LayerTypeAndRenderTypeTransaction_test.cpp | 7 +++++++ .../tests/LayerTypeTransaction_test.cpp | 7 +++++++ services/surfaceflinger/tests/LayerUpdate_test.cpp | 7 +++++++ services/surfaceflinger/tests/MirrorLayer_test.cpp | 7 +++++++ .../tests/MultiDisplayLayerBounds_test.cpp | 7 +++++++ services/surfaceflinger/tests/RelativeZ_test.cpp | 7 +++++++ services/surfaceflinger/tests/SetGeometry_test.cpp | 7 +++++++ services/surfaceflinger/tests/Stress_test.cpp | 7 +++++++ .../tests/SurfaceInterceptor_test.cpp | 7 +++++++ .../tests/fakehwc/FakeComposerClient.cpp | 7 +++++++ .../tests/fakehwc/FakeComposerService.cpp | 7 +++++++ .../tests/fakehwc/FakeComposerUtils.cpp | 7 +++++++ .../tests/fakehwc/SFFakeHwc_test.cpp | 7 +++++++ services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 7 +++++++ .../surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp | 7 +++++++ .../surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp | 7 +++++++ .../tests/hwc2/Hwc2TestPixelComparator.cpp | 7 +++++++ .../tests/hwc2/Hwc2TestProperties.cpp | 7 +++++++ .../surfaceflinger/tests/unittests/CachingTest.cpp | 7 +++++++ .../tests/unittests/CompositionTest.cpp | 7 +++++++ .../tests/unittests/DisplayTransactionTest.cpp | 7 +++++++ .../tests/unittests/FrameTracerTest.cpp | 7 +++++++ .../tests/unittests/LayerHistoryTest.cpp | 23 ++++++++++++++++++++++ .../tests/unittests/PhaseOffsetsTest.cpp | 7 +++++++ .../tests/unittests/RefreshRateConfigsTest.cpp | 8 ++++---- .../tests/unittests/RefreshRateStatsTest.cpp | 7 +++++++ .../tests/unittests/RegionSamplingTest.cpp | 7 +++++++ .../tests/unittests/SchedulerTest.cpp | 23 ++++++++++++++++++++++ .../tests/unittests/SchedulerUtilsTest.cpp | 8 +++++++- .../tests/unittests/TimeStatsTest.cpp | 7 +++++++ .../tests/unittests/TransactionApplicationTest.cpp | 7 +++++++ .../unittests/VSyncDispatchTimerQueueTest.cpp | 7 +++++++ .../tests/unittests/VSyncPredictorTest.cpp | 7 +++++++ .../mock/DisplayHardware/MockComposer.cpp | 7 +++++++ .../unittests/mock/MockSurfaceInterceptor.cpp | 7 +++++++ services/surfaceflinger/tests/vsync/vsync.cpp | 7 +++++++ 111 files changed, 815 insertions(+), 5 deletions(-) (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp index ba5a3f5550..7700b2e01f 100644 --- a/libs/renderengine/tests/RenderEngineTest.cpp +++ b/libs/renderengine/tests/RenderEngineTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -1339,3 +1343,6 @@ TEST_F(RenderEngineTest, drawLayers_fillShadow_translucentCasterWithAlpha) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 4c5e5da36a..8fa35d83e7 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -7,6 +7,7 @@ cc_defaults { "-Wthread-safety", "-Wunused", "-Wunreachable-code", + "-Wconversion", ], } diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 3b1b796076..7845cab397 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + //#define LOG_NDEBUG 0 #undef LOG_TAG #define LOG_TAG "BufferLayer" @@ -795,3 +799,6 @@ void BufferLayer::updateCloneBufferInfo() { #if defined(__gl2_h_) #error "don't include gl2/gl2.h in this file" #endif + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp index ea55795119..5e04d9597a 100644 --- a/services/surfaceflinger/BufferLayerConsumer.cpp +++ b/services/surfaceflinger/BufferLayerConsumer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "BufferLayerConsumer" #define ATRACE_TAG ATRACE_TAG_GRAPHICS @@ -519,3 +523,6 @@ BufferLayerConsumer::Image::~Image() { } } }; // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index e4e4bc7db6..c1b87751a4 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "BufferQueueLayer" #define ATRACE_TAG ATRACE_TAG_GRAPHICS @@ -612,3 +616,6 @@ void BufferQueueLayer::ContentsChangedListener::abandon() { // ----------------------------------------------------------------------- } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 067aa46b71..c173c66b4e 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + //#define LOG_NDEBUG 0 #undef LOG_TAG #define LOG_TAG "BufferStateLayer" @@ -681,3 +685,6 @@ sp BufferStateLayer::createClone() { return layer; } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index f3313645fa..fb72ab8065 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -131,3 +135,6 @@ status_t Client::getLayerFrameStats(const sp& handle, FrameStats* outSt // --------------------------------------------------------------------------- }; // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 8bfa569eeb..6aea88abd6 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + // #define LOG_NDEBUG 0 #undef LOG_TAG #define LOG_TAG "ColorLayer" @@ -116,3 +120,6 @@ sp ColorLayer::createClone() { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/mock/Display.cpp b/services/surfaceflinger/CompositionEngine/mock/Display.cpp index 01cf11278b..dc303d736f 100644 --- a/services/surfaceflinger/CompositionEngine/mock/Display.cpp +++ b/services/surfaceflinger/CompositionEngine/mock/Display.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include namespace android::compositionengine::mock { @@ -24,3 +28,6 @@ Display::Display() = default; Display::~Display() = default; } // namespace android::compositionengine::mock + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/mock/Layer.cpp b/services/surfaceflinger/CompositionEngine/mock/Layer.cpp index 08483cb301..a733bacee9 100644 --- a/services/surfaceflinger/CompositionEngine/mock/Layer.cpp +++ b/services/surfaceflinger/CompositionEngine/mock/Layer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include namespace android::compositionengine::mock { @@ -24,3 +28,6 @@ Layer::Layer() = default; Layer::~Layer() = default; } // namespace android::compositionengine::mock + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/mock/LayerFE.cpp b/services/surfaceflinger/CompositionEngine/mock/LayerFE.cpp index 607eaad826..232756f247 100644 --- a/services/surfaceflinger/CompositionEngine/mock/LayerFE.cpp +++ b/services/surfaceflinger/CompositionEngine/mock/LayerFE.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include namespace android::compositionengine::mock { @@ -24,3 +28,6 @@ LayerFE::LayerFE() = default; LayerFE::~LayerFE() = default; } // namespace android::compositionengine::mock + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/mock/Output.cpp b/services/surfaceflinger/CompositionEngine/mock/Output.cpp index 44df4c3da3..2608ef0cc0 100644 --- a/services/surfaceflinger/CompositionEngine/mock/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/mock/Output.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include namespace android::compositionengine::mock { @@ -24,3 +28,6 @@ Output::Output() = default; Output::~Output() = default; } // namespace android::compositionengine::mock + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/mock/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/mock/OutputLayer.cpp index 4da9377123..c1153e3596 100644 --- a/services/surfaceflinger/CompositionEngine/mock/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/mock/OutputLayer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include namespace android::compositionengine::mock { @@ -24,3 +28,6 @@ OutputLayer::OutputLayer() = default; OutputLayer::~OutputLayer() = default; } // namespace android::compositionengine::mock + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp index 5eabecd3ca..030c7039f7 100644 --- a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp +++ b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -155,3 +159,6 @@ void CompositionEngine::updateLayerStateFromFE(CompositionRefreshArgs& args) { } // namespace impl } // namespace android::compositionengine + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp index e885629c4b..20f765c4a8 100644 --- a/services/surfaceflinger/CompositionEngine/src/Display.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -337,3 +341,6 @@ void Display::finishFrame(const compositionengine::CompositionRefreshArgs& refre } } // namespace android::compositionengine::impl + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp b/services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp index f72862be07..995a0ca71f 100644 --- a/services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp +++ b/services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -48,3 +52,6 @@ void HwcBufferCache::getHwcBuffer(int slot, const sp& buffer, uin } } // namespace android::compositionengine::impl + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/src/Layer.cpp b/services/surfaceflinger/CompositionEngine/src/Layer.cpp index ecacaeee9c..22ecd33a2a 100644 --- a/services/surfaceflinger/CompositionEngine/src/Layer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Layer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -41,3 +45,6 @@ void Layer::dump(std::string& out) const { } // namespace impl } // namespace android::compositionengine + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp index e74052994a..085e83838e 100644 --- a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp +++ b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -86,3 +90,6 @@ void LayerFECompositionState::dump(std::string& out) const { } } // namespace android::compositionengine + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 6e2816715f..01413b9478 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -1058,3 +1062,6 @@ compositionengine::Output::FrameFences Output::presentAndGetFrameFences() { } // namespace impl } // namespace android::compositionengine + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index 82d24222f1..ac66d8cbe3 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -645,3 +649,6 @@ void OutputLayer::dump(std::string& out) const { } // namespace impl } // namespace android::compositionengine + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp index cc3c54c8b1..20c8f9a112 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -70,3 +74,6 @@ void OutputLayerCompositionState::dump(std::string& out) const { } } // namespace android::compositionengine::impl + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp index 949feb4041..10512eb9e9 100644 --- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp +++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include @@ -249,3 +253,6 @@ sp& RenderSurface::mutableGraphicBufferForTest() { } // namespace impl } // namespace android::compositionengine + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp b/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp index 989494d13f..ebcd0a0594 100644 --- a/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -298,3 +302,6 @@ TEST_F(CompositionTestPreComposition, } // namespace } // namespace android::compositionengine + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp index ae939693fa..0fe5843331 100644 --- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -833,3 +837,6 @@ TEST_F(DisplayFunctionalTest, postFramebufferCriticalCallsAreOrdered) { } // namespace } // namespace android::compositionengine + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/tests/LayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/LayerTest.cpp index 787f973215..44df2893d7 100644 --- a/services/surfaceflinger/CompositionEngine/tests/LayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/LayerTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -59,3 +63,6 @@ TEST_F(LayerTest, canInstantiateLayer) {} } // namespace } // namespace android::compositionengine + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp index 0e579fa7e1..bd830be68c 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -1054,3 +1058,6 @@ TEST_F(OutputLayerTest, needsFilteringReturnsTrueIfDisplaySizeDifferentFromSourc } // namespace } // namespace android::compositionengine + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 80528e3cb9..24311c7e5b 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -3781,3 +3785,6 @@ TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, } // namespace } // namespace android::compositionengine + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp index fd47e453c8..4fba10bf66 100644 --- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -350,3 +354,6 @@ TEST_F(RenderSurfaceTest, flipForwardsSignal) { } // namespace } // namespace android::compositionengine + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp index ab664be5e2..841e79f8af 100644 --- a/services/surfaceflinger/ContainerLayer.cpp +++ b/services/surfaceflinger/ContainerLayer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + // #define LOG_NDEBUG 0 #undef LOG_TAG #define LOG_TAG "ContainerLayer" @@ -39,3 +43,6 @@ sp ContainerLayer::createClone() { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index e0dc3e7751..e2122d1d30 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + // #define LOG_NDEBUG 0 #undef LOG_TAG #define LOG_TAG "DisplayDevice" @@ -327,3 +331,6 @@ const HdrCapabilities& DisplayDevice::getHdrCapabilities() const { std::atomic DisplayDeviceState::sNextSequenceId(1); } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp index eb032f3fe8..6892dd8ed0 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "HwcComposer" @@ -1622,3 +1626,6 @@ void CommandReader::takePresentOrValidateStage(Display display, uint32_t* state) } // namespace Hwc2 } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp index ba7818dd02..277081f230 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp +++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "DisplayIdentification" @@ -204,3 +208,6 @@ DisplayId getVirtualDisplayId(uint32_t id) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index 7370b0ccb2..36544b6653 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -15,6 +15,10 @@ ** limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + // #define LOG_NDEBUG 0 #undef LOG_TAG #define LOG_TAG "FramebufferSurface" @@ -193,3 +197,6 @@ const sp& FramebufferSurface::getClientTargetAcquireFence() const { // ---------------------------------------------------------------------------- }; // namespace android // ---------------------------------------------------------------------------- + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index 12b0ddd26d..41e787980a 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + // #define LOG_NDEBUG 0 #undef LOG_TAG @@ -977,3 +981,6 @@ Error Layer::setColorTransform(const android::mat4& matrix) { } // namespace impl } // namespace HWC2 + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 1960f431a8..153cfe7f9d 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + // #define LOG_NDEBUG 0 #undef LOG_TAG @@ -948,3 +952,6 @@ uint32_t HWComposer::getMaxVirtualDisplayCount() const { } // namespace impl } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index 56b0ea61e3..fba3261388 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + // #define LOG_NDEBUG 0 #include "VirtualDisplaySurface.h" @@ -694,3 +698,6 @@ const char* VirtualDisplaySurface::dbgSourceStr(Source s) { // --------------------------------------------------------------------------- } // namespace android // --------------------------------------------------------------------------- + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Effects/Daltonizer.cpp b/services/surfaceflinger/Effects/Daltonizer.cpp index 01c9c0fc68..a7090c51f2 100644 --- a/services/surfaceflinger/Effects/Daltonizer.cpp +++ b/services/surfaceflinger/Effects/Daltonizer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "Daltonizer.h" #include @@ -171,3 +175,6 @@ void Daltonizer::update() { } } /* namespace android */ + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/EventLog/EventLog.cpp b/services/surfaceflinger/EventLog/EventLog.cpp index a532fc130f..3b609524e8 100644 --- a/services/surfaceflinger/EventLog/EventLog.cpp +++ b/services/surfaceflinger/EventLog/EventLog.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -124,3 +128,6 @@ void EventLog::TagBuffer::writeString(const std::string_view& value) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/FrameTracer/FrameTracer.cpp b/services/surfaceflinger/FrameTracer/FrameTracer.cpp index 441811646b..b986f3844a 100644 --- a/services/surfaceflinger/FrameTracer/FrameTracer.cpp +++ b/services/surfaceflinger/FrameTracer/FrameTracer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "FrameTracer" #define ATRACE_TAG ATRACE_TAG_GRAPHICS @@ -179,3 +183,6 @@ std::string FrameTracer::miniDump() { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/FrameTracker.cpp b/services/surfaceflinger/FrameTracker.cpp index a6e511e76e..8ad805b1d8 100644 --- a/services/surfaceflinger/FrameTracker.cpp +++ b/services/surfaceflinger/FrameTracker.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + // This is needed for stdint.h to define INT64_MAX in C++ #define __STDC_LIMIT_MACROS @@ -246,3 +250,6 @@ void FrameTracker::dumpStats(std::string& result) const { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 2593681b6b..b0c94a279e 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + //#define LOG_NDEBUG 0 #undef LOG_TAG #define LOG_TAG "Layer" @@ -2304,3 +2308,6 @@ void Layer::addChildToDrawing(const sp& layer) { #if defined(__gl2_h_) #error "don't include gl2/gl2.h in this file" #endif + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp index b4022704d5..0fe1421926 100644 --- a/services/surfaceflinger/LayerProtoHelper.cpp +++ b/services/surfaceflinger/LayerProtoHelper.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "LayerProtoHelper.h" namespace android { @@ -165,3 +169,6 @@ void LayerProtoHelper::writeToProto(const mat4 matrix, ColorTransformProto* colo } // namespace surfaceflinger } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp index 412f9779c8..d3364a0929 100644 --- a/services/surfaceflinger/LayerRejecter.cpp +++ b/services/surfaceflinger/LayerRejecter.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "LayerRejecter.h" #include @@ -136,3 +140,6 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/LayerVector.cpp b/services/surfaceflinger/LayerVector.cpp index 8271fd97ea..7c959b9e56 100644 --- a/services/surfaceflinger/LayerVector.cpp +++ b/services/surfaceflinger/LayerVector.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "LayerVector.h" #include "Layer.h" @@ -83,3 +87,6 @@ void LayerVector::traverseInReverseZOrder(StateSet stateSet, const Visitor& visi } } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp index 7a959f7b19..5009e10532 100644 --- a/services/surfaceflinger/MonitoredProducer.cpp +++ b/services/surfaceflinger/MonitoredProducer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "MonitoredProducer.h" #include "Layer.h" #include "SurfaceFlinger.h" @@ -168,3 +172,6 @@ sp MonitoredProducer::getLayer() const { // --------------------------------------------------------------------------- }; // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index c69859e32a..33e5796e6f 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "RefreshRateOverlay.h" #include "Client.h" #include "Layer.h" @@ -211,3 +215,6 @@ void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { } }; // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index 73de4f8b78..0031d70160 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + //#define LOG_NDEBUG 0 #define ATRACE_TAG ATRACE_TAG_GRAPHICS #undef LOG_TAG @@ -472,3 +476,6 @@ void RegionSamplingThread::threadMain() NO_THREAD_SAFETY_ANALYSIS { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/RenderArea.cpp b/services/surfaceflinger/RenderArea.cpp index 93759e8ad7..9a6c8533ea 100644 --- a/services/surfaceflinger/RenderArea.cpp +++ b/services/surfaceflinger/RenderArea.cpp @@ -1,3 +1,23 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "RenderArea.h" namespace android { @@ -13,3 +33,6 @@ float RenderArea::getCaptureFillValue(CaptureFill captureFill) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp index 4bdfad94eb..ca41608c1c 100644 --- a/services/surfaceflinger/Scheduler/DispSync.cpp +++ b/services/surfaceflinger/Scheduler/DispSync.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #define ATRACE_TAG ATRACE_TAG_GRAPHICS //#define LOG_NDEBUG 0 @@ -847,3 +851,6 @@ nsecs_t DispSync::expectedPresentTime() { } // namespace impl } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.cpp b/services/surfaceflinger/Scheduler/DispSyncSource.cpp index bd4b0ec0d1..776e98463f 100644 --- a/services/surfaceflinger/Scheduler/DispSyncSource.cpp +++ b/services/surfaceflinger/Scheduler/DispSyncSource.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include "DispSyncSource.h" @@ -104,3 +108,6 @@ void DispSyncSource::onDispSyncEvent(nsecs_t when) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Scheduler/EventControlThread.cpp b/services/surfaceflinger/Scheduler/EventControlThread.cpp index 85a7f82a3c..7f9db9ca2d 100644 --- a/services/surfaceflinger/Scheduler/EventControlThread.cpp +++ b/services/surfaceflinger/Scheduler/EventControlThread.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -73,3 +77,6 @@ void EventControlThread::threadMain() NO_THREAD_SAFETY_ANALYSIS { } // namespace impl } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp index 5bdef5807f..14e3ec6ead 100644 --- a/services/surfaceflinger/Scheduler/EventThread.cpp +++ b/services/surfaceflinger/Scheduler/EventThread.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include @@ -517,3 +521,6 @@ const char* EventThread::toCString(State state) { } // namespace impl } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index cf79d9fcf7..db16f8df1f 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "LayerHistory" #define ATRACE_TAG ATRACE_TAG_GRAPHICS @@ -158,3 +162,6 @@ void LayerHistory::clear() { } } // namespace android::scheduler::impl + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp index 5318b00983..005d157fd5 100644 --- a/services/surfaceflinger/Scheduler/MessageQueue.cpp +++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -159,3 +163,6 @@ int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) { } // namespace impl } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp index 13014c789b..106aa9bccb 100644 --- a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp +++ b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "PhaseOffsets.h" #include @@ -330,3 +334,6 @@ void PhaseDurations::dump(std::string& result) const { } // namespace impl } // namespace android::scheduler + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index 692ded928d..45d1f23029 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + // #define LOG_NDEBUG 0 #include "RefreshRateConfigs.h" @@ -217,3 +221,5 @@ void RefreshRateConfigs::init(const std::vector& configs, } } // namespace android::scheduler +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 73dc753c7e..c96eba40fd 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "Scheduler" #define ATRACE_TAG ATRACE_TAG_GRAPHICS @@ -595,3 +599,6 @@ void Scheduler::onDisplayRefreshed(nsecs_t timestamp) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Scheduler/SchedulerUtils.cpp b/services/surfaceflinger/Scheduler/SchedulerUtils.cpp index fb5414fd4b..27120be272 100644 --- a/services/surfaceflinger/Scheduler/SchedulerUtils.cpp +++ b/services/surfaceflinger/Scheduler/SchedulerUtils.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "SchedulerUtils.h" #include @@ -36,3 +40,6 @@ int64_t calculate_median(std::vector* v) { } // namespace scheduler } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.cpp b/services/surfaceflinger/Scheduler/VSyncModulator.cpp index 8de35b1c2f..40a992cf01 100644 --- a/services/surfaceflinger/Scheduler/VSyncModulator.cpp +++ b/services/surfaceflinger/Scheduler/VSyncModulator.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include "VSyncModulator.h" @@ -144,3 +148,6 @@ void VSyncModulator::updateOffsetsLocked() { } } // namespace android::scheduler + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp index 3b99a58838..915419154f 100644 --- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp +++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #define ATRACE_TAG ATRACE_TAG_GRAPHICS //#define LOG_NDEBUG 0 #include "VSyncPredictor.h" @@ -224,3 +228,6 @@ bool VSyncPredictor::needsMoreSamples(nsecs_t now) const { } } // namespace android::scheduler + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index b7a2c760e6..3dcf7d1665 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + //#define LOG_NDEBUG 0 #define ATRACE_TAG ATRACE_TAG_GRAPHICS @@ -5772,3 +5776,6 @@ status_t SurfaceFlinger::setGlobalShadowSettings(const half4& ambientColor, cons #if defined(__gl2_h_) #error "don't include gl2/gl2.h in this file" #endif + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp index d5c2306e1f..e12d31a99a 100644 --- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp +++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -138,3 +142,6 @@ sp DefaultFactory::createColorLayer(const LayerCreationArgs& args) { } } // namespace android::surfaceflinger + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/SurfaceFlingerFactory.cpp b/services/surfaceflinger/SurfaceFlingerFactory.cpp index 9b1f658661..3997b04f5f 100644 --- a/services/surfaceflinger/SurfaceFlingerFactory.cpp +++ b/services/surfaceflinger/SurfaceFlingerFactory.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "SurfaceFlinger.h" #include "SurfaceFlingerDefaultFactory.h" @@ -26,3 +30,6 @@ sp createSurfaceFlinger() { } } // namespace android::surfaceflinger + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index 8e0462ab52..79123f979b 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -13,6 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" #undef LOG_TAG #define LOG_TAG "SurfaceInterceptor" #define ATRACE_TAG ATRACE_TAG_GRAPHICS @@ -677,3 +681,6 @@ void SurfaceInterceptor::savePowerModeUpdate(int32_t sequenceId, int32_t mode) { } // namespace impl } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp index eb26cd0379..6fd4e46c73 100644 --- a/services/surfaceflinger/SurfaceTracing.cpp +++ b/services/surfaceflinger/SurfaceTracing.cpp @@ -13,6 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" #undef LOG_TAG #define LOG_TAG "SurfaceTracing" #define ATRACE_TAG ATRACE_TAG_GRAPHICS @@ -202,3 +206,6 @@ void SurfaceTracing::dump(std::string& result) const { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp index a5fabf2c16..0939fa4f9b 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.cpp +++ b/services/surfaceflinger/TimeStats/TimeStats.cpp @@ -13,6 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" #undef LOG_TAG #define LOG_TAG "TimeStats" #define ATRACE_TAG ATRACE_TAG_GRAPHICS @@ -657,3 +661,6 @@ void TimeStats::dump(bool asProto, std::optional maxLayers, std::strin } // namespace impl } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/TransactionCompletedThread.cpp b/services/surfaceflinger/TransactionCompletedThread.cpp index 1475889cd9..daa67ae043 100644 --- a/services/surfaceflinger/TransactionCompletedThread.cpp +++ b/services/surfaceflinger/TransactionCompletedThread.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + //#define LOG_NDEBUG 0 #undef LOG_TAG #define LOG_TAG "TransactionCompletedThread" @@ -355,3 +359,6 @@ CallbackHandle::CallbackHandle(const sp& transactionListener, : listener(transactionListener), callbackIds(ids), surfaceControl(sc) {} } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp index e7986d3344..d7ad9deb03 100644 --- a/services/surfaceflinger/main_surfaceflinger.cpp +++ b/services/surfaceflinger/main_surfaceflinger.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -121,3 +125,6 @@ int main(int, char**) { return 0; } + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/BufferGenerator.cpp b/services/surfaceflinger/tests/BufferGenerator.cpp index 8ddda60cd2..293738cfcb 100644 --- a/services/surfaceflinger/tests/BufferGenerator.cpp +++ b/services/surfaceflinger/tests/BufferGenerator.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -379,3 +383,6 @@ void BufferGenerator::setBuffer(const sp& buffer, int32_t fence, } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp index f6188738b2..a7c095d327 100644 --- a/services/surfaceflinger/tests/Credentials_test.cpp +++ b/services/surfaceflinger/tests/Credentials_test.cpp @@ -31,6 +31,10 @@ const float FRAME_SCALE = 1.0f; * Methods like EnableVsyncInjections and InjectVsync are not tested since they do not * return anything meaningful. */ + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" class CredentialsTest : public ::testing::Test { protected: void SetUp() override { @@ -362,3 +366,6 @@ TEST_F(CredentialsTest, GetActiveColorModeBasicCorrectness) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/DereferenceSurfaceControl_test.cpp b/services/surfaceflinger/tests/DereferenceSurfaceControl_test.cpp index 0cef0d1c87..46b98f9193 100644 --- a/services/surfaceflinger/tests/DereferenceSurfaceControl_test.cpp +++ b/services/surfaceflinger/tests/DereferenceSurfaceControl_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "LayerTransactionTest.h" namespace android { @@ -67,3 +71,6 @@ TEST_F(DereferenceSurfaceControlTest, LayerInTransaction) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/DisplayConfigs_test.cpp b/services/surfaceflinger/tests/DisplayConfigs_test.cpp index d51b9a146f..3aa4474b6b 100644 --- a/services/surfaceflinger/tests/DisplayConfigs_test.cpp +++ b/services/surfaceflinger/tests/DisplayConfigs_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include "LayerTransactionTest.h" namespace android { @@ -68,3 +72,6 @@ TEST_F(RefreshRateRangeTest, setAllConfigs) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" \ No newline at end of file diff --git a/services/surfaceflinger/tests/LayerCallback_test.cpp b/services/surfaceflinger/tests/LayerCallback_test.cpp index 7a5ed484d1..6d28e621ac 100644 --- a/services/surfaceflinger/tests/LayerCallback_test.cpp +++ b/services/surfaceflinger/tests/LayerCallback_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "LayerTransactionTest.h" #include "utils/CallbackUtils.h" @@ -870,3 +874,6 @@ TEST_F(LayerCallbackTest, DesiredPresentTime_Past) { EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp index 92698f0142..24874b010b 100644 --- a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -1841,3 +1845,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetColorTransformOnChildAndParent) { } } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/LayerTransaction_test.cpp b/services/surfaceflinger/tests/LayerTransaction_test.cpp index 7816c667bb..97cba63192 100644 --- a/services/surfaceflinger/tests/LayerTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerTransaction_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include "LayerTransactionTest.h" @@ -190,3 +194,6 @@ TEST_F(LayerTransactionTest, DISABLED_BufferQueueLayerMergeDamageRegionWhenDropp ASSERT_EQ(OK, producer->disconnect(NATIVE_WINDOW_API_CPU)); } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp index daeff17ea3..71f01b0c1d 100644 --- a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include "TransactionTestHarnesses.h" @@ -267,3 +271,6 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetLayerStackBasic) { } } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp index 42ec34a129..7e9202bb82 100644 --- a/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include "TransactionTestHarnesses.h" @@ -186,3 +190,6 @@ TEST_P(LayerTypeTransactionTest, RefreshRateIsInitialized) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/LayerUpdate_test.cpp b/services/surfaceflinger/tests/LayerUpdate_test.cpp index 0ad122b5ed..0459386936 100644 --- a/services/surfaceflinger/tests/LayerUpdate_test.cpp +++ b/services/surfaceflinger/tests/LayerUpdate_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "LayerTransactionTest.h" namespace android { @@ -1708,3 +1712,6 @@ TEST_F(ScreenCaptureTest, CaptureInvalidLayer) { ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, &outBuffer, Rect::EMPTY_RECT, 1.0)); } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/MirrorLayer_test.cpp b/services/surfaceflinger/tests/MirrorLayer_test.cpp index 0bcac1a880..b49bd54599 100644 --- a/services/surfaceflinger/tests/MirrorLayer_test.cpp +++ b/services/surfaceflinger/tests/MirrorLayer_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "LayerTransactionTest.h" namespace android { @@ -224,3 +228,6 @@ TEST_F(MirrorLayerTest, MirrorBufferLayer) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp b/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp index 066c9aa3ce..e525e2af9b 100644 --- a/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp +++ b/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "LayerTransactionTest.h" namespace android { @@ -122,3 +126,6 @@ TEST_F(MultiDisplayLayerBoundsTest, RenderLayerInMirroredVirtualDisplay) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/RelativeZ_test.cpp b/services/surfaceflinger/tests/RelativeZ_test.cpp index 8c56d27e8a..1180cacf7f 100644 --- a/services/surfaceflinger/tests/RelativeZ_test.cpp +++ b/services/surfaceflinger/tests/RelativeZ_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "LayerTransactionTest.h" namespace android { @@ -204,3 +208,6 @@ TEST_F(RelativeZTest, LayerAndRelativeRemoved) { } } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/SetGeometry_test.cpp b/services/surfaceflinger/tests/SetGeometry_test.cpp index dca06ec8d4..5fe2513bb3 100644 --- a/services/surfaceflinger/tests/SetGeometry_test.cpp +++ b/services/surfaceflinger/tests/SetGeometry_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "LayerTransactionTest.h" namespace android { @@ -97,3 +101,6 @@ TEST_F(SetGeometryTest, Scale) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/Stress_test.cpp b/services/surfaceflinger/tests/Stress_test.cpp index ee857b01f2..e9b6ba0f64 100644 --- a/services/surfaceflinger/tests/Stress_test.cpp +++ b/services/surfaceflinger/tests/Stress_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -107,3 +111,6 @@ TEST(LayerProtoStress, mem_info) { } } + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp index 1fa426d14e..75d0761907 100644 --- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp +++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -1011,3 +1015,6 @@ TEST_F(SurfaceInterceptorTest, InterceptSimultaneousUpdatesWorks) { ASSERT_TRUE(singleIncrementFound(capturedTrace, Increment::IncrementCase::kSurfaceCreation)); } } + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp index 0c370a6fdb..5824e589d1 100644 --- a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp +++ b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + //#define LOG_NDEBUG 0 #undef LOG_TAG #define LOG_TAG "FakeComposer" @@ -896,3 +900,6 @@ Layer FakeComposerClient::getLayer(size_t index) const { // this might get more involving. return static_cast(index); } + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerService.cpp b/services/surfaceflinger/tests/fakehwc/FakeComposerService.cpp index f727bc4079..c656eed0fb 100644 --- a/services/surfaceflinger/tests/fakehwc/FakeComposerService.cpp +++ b/services/surfaceflinger/tests/fakehwc/FakeComposerService.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #define LOG_NDEBUG 0 #undef LOG_TAG #define LOG_TAG "FakeHwcService" @@ -170,3 +174,6 @@ Return FakeComposerService_2_4::createClient_2_4(createClient_2_4_cb hidl_ } } // namespace sftest + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.cpp b/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.cpp index 4d2146810b..2f89696e8e 100644 --- a/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.cpp +++ b/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #define LOG_NDEBUG 0 #undef LOG_TAG #define LOG_TAG "FakeHwcUtil" @@ -183,3 +187,6 @@ void FakeHwcEnvironment::TearDown() { } } // namespace sftest + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index 09fdbdf114..18572064b6 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + // #define LOG_NDEBUG 0 #undef LOG_TAG #define LOG_TAG "FakeHwcTest" @@ -1970,3 +1974,6 @@ int main(int argc, char** argv) { ::testing::InitGoogleMock(&argc, argv); return RUN_ALL_TESTS(); } + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index 13774b4ed3..f9a1fe9a73 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -4770,3 +4774,6 @@ TEST_F(Hwc2Test, PRESENT_VIRTUAL_DISPLAY_default_5) ASSERT_NO_FATAL_FAILURE(createAndPresentVirtualDisplay(layerCnt, coverage, virtualDisplayExceptions)); } + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp index 648456295d..fcd0d31078 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -789,3 +793,6 @@ int Hwc2TestOutputBuffer::getOutputBuffer(buffer_handle_t* outHandle, return 0; } + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp index 90127a1302..b76ace8752 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp @@ -13,6 +13,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -279,3 +283,6 @@ bool Hwc2TestLayers::setVisibleRegions() return optimized; } + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestPixelComparator.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestPixelComparator.cpp index 904b927abf..8ca88150e9 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestPixelComparator.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestPixelComparator.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -111,3 +115,6 @@ std::string ComparatorResult::dumpComparison() const } return stream.str(); } + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp index c5b92d0664..1efb21e639 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -780,3 +784,6 @@ const std::array Hwc2TestSurfaceDamage::mCompositionSupport = {{ const std::array Hwc2TestTransform::mCompositionSupport = {{ false, true, true, false, true, true, }}; + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/CachingTest.cpp b/services/surfaceflinger/tests/unittests/CachingTest.cpp index 74ce540626..1b8c76d1b9 100644 --- a/services/surfaceflinger/tests/unittests/CachingTest.cpp +++ b/services/surfaceflinger/tests/unittests/CachingTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "CachingTest" @@ -91,3 +95,6 @@ TEST_F(SlotGenerationTest, getHwcCacheSlot_Reuse) { } } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index cce21ceddb..8a762d4030 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "CompositionTest" @@ -1423,3 +1427,6 @@ TEST_F(CompositionTest, DebugOptionForcingClientCompositionOfBufferLayerWithDirt } // namespace } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index 55c3ab8b22..33563eaed6 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" @@ -3239,3 +3243,6 @@ TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOnToUnknownExternalDispla } // namespace } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp index c334bcf85d..68cb52fe87 100644 --- a/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp +++ b/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" @@ -394,3 +398,6 @@ TEST_F(FrameTracerTest, traceFenceWithValidStartTime_ShouldHaveCorrectDuration) } // namespace } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index f055fe72ac..c9af057ae5 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -1,3 +1,23 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "LayerHistoryTest" @@ -241,3 +261,6 @@ TEST_F(LayerHistoryTest, multipleLayers) { } // namespace } // namespace android::scheduler + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/PhaseOffsetsTest.cpp b/services/surfaceflinger/tests/unittests/PhaseOffsetsTest.cpp index 6360ec14cd..910e73baf2 100644 --- a/services/surfaceflinger/tests/unittests/PhaseOffsetsTest.cpp +++ b/services/surfaceflinger/tests/unittests/PhaseOffsetsTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "SchedulerUnittests" @@ -124,3 +128,6 @@ TEST_F(PhaseOffsetsTest, getOffsetsForRefreshRate_DefaultOffsets) { } // namespace } // namespace scheduler } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" \ No newline at end of file diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp index cc3c985aa1..86aa8fb22b 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -242,11 +242,11 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContent) { TEST_F(RefreshRateConfigsTest, testInPolicy) { RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60_POINT_4, HWC_GROUP_ID_0, "60fps", 60}; - ASSERT_TRUE(expectedDefaultConfig.inPolicy(60.000004, 60.000004)); + ASSERT_TRUE(expectedDefaultConfig.inPolicy(60.000004f, 60.000004f)); ASSERT_TRUE(expectedDefaultConfig.inPolicy(59.0f, 60.1f)); - ASSERT_FALSE(expectedDefaultConfig.inPolicy(75.0, 90.0)); - ASSERT_FALSE(expectedDefaultConfig.inPolicy(60.0011, 90.0)); - ASSERT_FALSE(expectedDefaultConfig.inPolicy(50.0, 59.998)); + ASSERT_FALSE(expectedDefaultConfig.inPolicy(75.0f, 90.0f)); + ASSERT_FALSE(expectedDefaultConfig.inPolicy(60.0011f, 90.0f)); + ASSERT_FALSE(expectedDefaultConfig.inPolicy(50.0f, 59.998f)); } } // namespace diff --git a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp index ef4699f628..8e07c79656 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "SchedulerUnittests" @@ -195,3 +199,6 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { } // namespace } // namespace scheduler } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp b/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp index d8de804ad8..f19e55409c 100644 --- a/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp +++ b/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "RegionSamplingTest" @@ -137,3 +141,6 @@ TEST_F(RegionSamplingTest, orientation_90) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp index 40536abc5d..b1ecf4da6e 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp @@ -1,3 +1,23 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "SchedulerUnittests" @@ -144,3 +164,6 @@ TEST_F(SchedulerTest, validConnectionHandle) { } // namespace } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/SchedulerUtilsTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerUtilsTest.cpp index 5865579641..5f6a7150d6 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerUtilsTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerUtilsTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "SchedulerUnittests" @@ -128,4 +132,6 @@ TEST_F(SchedulerUtilsTest, calculate_mode) { } // namespace } // namespace scheduler -} // namespace android \ No newline at end of file +} // namespace android +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp index 3e808c0abb..bcf3ba8856 100644 --- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp +++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" @@ -656,3 +660,6 @@ TEST_F(TimeStatsTest, canSurviveMonkey) { } // namespace } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp index 994a509e4f..f1739e5e8a 100644 --- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "CompositionTest" @@ -321,3 +325,6 @@ TEST_F(TransactionApplicationTest, FromHandle) { EXPECT_EQ(nullptr, ret.get()); } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp index 5aff4296f9..82919abe03 100644 --- a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp +++ b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" #define LOG_NDEBUG 0 @@ -803,3 +807,6 @@ TEST_F(VSyncDispatchTimerQueueEntryTest, reportsScheduledIfStillTime) { } } // namespace android::scheduler + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp index 4cb6a38217..00d3cc6e0b 100644 --- a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp +++ b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" #define LOG_NDEBUG 0 @@ -352,3 +356,6 @@ TEST_F(VSyncPredictorTest, doesNotPredictBeforeTimePointWithHigherIntercept) { } } // namespace android::scheduler + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.cpp b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.cpp index 7ed57b9d96..0780af1f26 100644 --- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.cpp +++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "mock/DisplayHardware/MockComposer.h" namespace android { @@ -27,3 +31,6 @@ Composer::~Composer() = default; } // namespace mock } // namespace Hwc2 } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/mock/MockSurfaceInterceptor.cpp b/services/surfaceflinger/tests/unittests/mock/MockSurfaceInterceptor.cpp index 4129328ba9..7e925b94ee 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockSurfaceInterceptor.cpp +++ b/services/surfaceflinger/tests/unittests/mock/MockSurfaceInterceptor.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "mock/MockSurfaceInterceptor.h" namespace android { @@ -25,3 +29,6 @@ SurfaceInterceptor::~SurfaceInterceptor() = default; } // namespace mock } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/vsync/vsync.cpp b/services/surfaceflinger/tests/vsync/vsync.cpp index a1b45e6adb..667dfb92d5 100644 --- a/services/surfaceflinger/tests/vsync/vsync.cpp +++ b/services/surfaceflinger/tests/vsync/vsync.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -82,3 +86,6 @@ int main(int /*argc*/, char** /*argv*/) return 0; } + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" -- cgit v1.2.3-59-g8ed1b From 8a82ba66a22238fe59c02a6309ba8bd3dae4f074 Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Fri, 17 Jan 2020 12:43:17 -0800 Subject: SurfaceFlinger: enhance refresh rate selection Enhance the refresh rate selection algorithm to allow having multiple refresh rate. The new process attaches scores to each one of the available refresh rate and chooses the refresh rate with the highest score. This behavior is currently controlled by the sysprop flag 'debug.sf.use_content_detection_v2' and currently turned off. This algorithm stills needs some tunings which will be done in layer CLs. Test: adb shell /data/nativetest64/SurfaceFlinger_test/SurfaceFlinger_test Test: adb shell /data/nativetest64/libsurfaceflinger_unittest/libsurfaceflinger_unittest Test: go/90hzscenarios manual tests Bug: 147516364 Fixes: 146068419 Change-Id: I06e07459e469482799ff80fa54fa8dd311325e0e --- services/surfaceflinger/Android.bp | 2 + services/surfaceflinger/BufferQueueLayer.cpp | 7 +- services/surfaceflinger/BufferQueueLayer.h | 2 +- services/surfaceflinger/BufferStateLayer.cpp | 3 +- services/surfaceflinger/DisplayDevice.h | 6 +- .../surfaceflinger/DisplayHardware/ComposerHal.h | 7 + .../surfaceflinger/DisplayHardware/HWComposer.h | 6 + services/surfaceflinger/Layer.cpp | 7 +- services/surfaceflinger/Layer.h | 3 +- services/surfaceflinger/RefreshRateOverlay.cpp | 1 + services/surfaceflinger/RenderArea.h | 4 +- services/surfaceflinger/Scheduler/LayerHistory.cpp | 53 +-- services/surfaceflinger/Scheduler/LayerHistory.h | 88 +++- .../surfaceflinger/Scheduler/LayerHistoryV2.cpp | 213 +++++++++ services/surfaceflinger/Scheduler/LayerInfoV2.cpp | 139 ++++++ services/surfaceflinger/Scheduler/LayerInfoV2.h | 117 +++++ .../Scheduler/RefreshRateConfigs.cpp | 157 ++++++- .../surfaceflinger/Scheduler/RefreshRateConfigs.h | 33 +- .../surfaceflinger/Scheduler/RefreshRateStats.h | 3 +- services/surfaceflinger/Scheduler/Scheduler.cpp | 119 +++-- services/surfaceflinger/Scheduler/Scheduler.h | 15 +- services/surfaceflinger/SurfaceFlinger.cpp | 30 +- .../SurfaceFlingerDefaultFactory.cpp | 4 +- services/surfaceflinger/tests/unittests/Android.bp | 1 + .../tests/unittests/LayerHistoryTest.cpp | 73 ++- .../tests/unittests/LayerHistoryTestV2.cpp | 418 +++++++++++++++++ .../tests/unittests/RefreshRateConfigsTest.cpp | 499 ++++++++++++++++++++- .../tests/unittests/SchedulerTest.cpp | 2 +- .../tests/unittests/TestableScheduler.h | 32 +- .../tests/unittests/TestableSurfaceFlinger.h | 17 +- .../tests/unittests/mock/MockLayer.h | 1 + 31 files changed, 1877 insertions(+), 185 deletions(-) create mode 100644 services/surfaceflinger/Scheduler/LayerHistoryV2.cpp create mode 100644 services/surfaceflinger/Scheduler/LayerInfoV2.cpp create mode 100644 services/surfaceflinger/Scheduler/LayerInfoV2.h create mode 100644 services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 9a7eabd498..1b1e8890ab 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -165,7 +165,9 @@ filegroup { "Scheduler/EventThread.cpp", "Scheduler/OneShotTimer.cpp", "Scheduler/LayerHistory.cpp", + "Scheduler/LayerHistoryV2.cpp", "Scheduler/LayerInfo.cpp", + "Scheduler/LayerInfoV2.cpp", "Scheduler/MessageQueue.cpp", "Scheduler/PhaseOffsets.cpp", "Scheduler/RefreshRateConfigs.cpp", diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index b55e62b88c..e85281d8a9 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -129,8 +129,11 @@ bool BufferQueueLayer::setFrameRate(float frameRate) { return frameRateChanged; } -float BufferQueueLayer::getFrameRate() const { - return mLatchedFrameRate; +std::optional BufferQueueLayer::getFrameRate() const { + if (mLatchedFrameRate > 0.f || mLatchedFrameRate == FRAME_RATE_NO_VOTE) + return mLatchedFrameRate; + + return {}; } // ----------------------------------------------------------------------- diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 0777953c17..2bd1e3d6cc 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -57,7 +57,7 @@ public: bool shouldPresentNow(nsecs_t expectedPresentTime) const override; bool setFrameRate(float frameRate) override; - float getFrameRate() const override; + std::optional getFrameRate() const override; // ----------------------------------------------------------------------- diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index c173c66b4e..2967164764 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -251,7 +251,8 @@ bool BufferStateLayer::setBuffer(const sp& buffer, nsecs_t postTi FrameTracer::FrameEvent::POST); mCurrentState.desiredPresentTime = desiredPresentTime; - mFlinger->mScheduler->recordLayerHistory(this, desiredPresentTime); + mFlinger->mScheduler->recordLayerHistory(this, + desiredPresentTime <= 0 ? 0 : desiredPresentTime); return true; } diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 605e7c8ab4..ff48ecdedc 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -227,8 +227,10 @@ class DisplayRenderArea : public RenderArea { public: DisplayRenderArea(const sp& display, RotationFlags rotation = ui::Transform::ROT_0) - : DisplayRenderArea(display, display->getBounds(), display->getWidth(), - display->getHeight(), display->getCompositionDataSpace(), rotation) {} + : DisplayRenderArea(display, display->getBounds(), + static_cast(display->getWidth()), + static_cast(display->getHeight()), + display->getCompositionDataSpace(), rotation) {} DisplayRenderArea(sp display, const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, ui::Dataspace reqDataSpace, RotationFlags rotation, diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h index 6f0f38a58a..a2b7421269 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.h +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h @@ -23,6 +23,10 @@ #include #include +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER #include #endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER @@ -36,6 +40,9 @@ #include #include +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" + namespace android { namespace Hwc2 { diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index a0dabb427d..effe43b548 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -27,7 +27,13 @@ #include #include + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" #include +#pragma clang diagnostic pop + #include #include diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f4d4329f6d..af906dc64c 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1251,8 +1251,11 @@ bool Layer::setFrameRate(float frameRate) { return true; } -float Layer::getFrameRate() const { - return getDrawingState().frameRate; +std::optional Layer::getFrameRate() const { + const auto frameRate = getDrawingState().frameRate; + if (frameRate > 0.f || frameRate == FRAME_RATE_NO_VOTE) return frameRate; + + return {}; } void Layer::deferTransactionUntil_legacy(const sp& barrierLayer, uint64_t frameNumber) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index ffe004f9e9..b8423f0232 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -744,8 +744,9 @@ public: */ Rect getCroppedBufferSize(const Layer::State& s) const; + constexpr static auto FRAME_RATE_NO_VOTE = -1.0f; virtual bool setFrameRate(float frameRate); - virtual float getFrameRate() const; + virtual std::optional getFrameRate() const; protected: // constant diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 33e5796e6f..d3d9d3aec7 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -155,6 +155,7 @@ bool RefreshRateOverlay::createLayer() { Mutex::Autolock _l(mFlinger.mStateLock); mLayer = mClient->getLayerUser(mIBinder); + mLayer->setFrameRate(Layer::FRAME_RATE_NO_VOTE); // setting Layer's Z requires resorting layersSortedByZ ssize_t idx = mFlinger.mCurrentState.layersSortedByZ.indexOf(mLayer); diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h index a7a6dd5fc1..9b3a9f4309 100644 --- a/services/surfaceflinger/RenderArea.h +++ b/services/surfaceflinger/RenderArea.h @@ -71,8 +71,8 @@ public: RotationFlags getRotationFlags() const { return mRotationFlags; } // Returns the size of the physical render area. - int getReqWidth() const { return mReqWidth; } - int getReqHeight() const { return mReqHeight; } + int getReqWidth() const { return static_cast(mReqWidth); } + int getReqHeight() const { return static_cast(mReqHeight); } // Returns the composition data space of the render area. ui::Dataspace getReqDataSpace() const { return mReqDataSpace; } diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index abf0cd673a..ebd617faef 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -43,7 +43,7 @@ namespace android::scheduler::impl { namespace { bool isLayerActive(const Layer& layer, const LayerInfo& info, nsecs_t threshold) { - if (layer.getFrameRate() > .0f) { + if (layer.getFrameRate().has_value()) { return layer.isVisible(); } return layer.isVisible() && info.getLastUpdatedTime() >= threshold; @@ -77,7 +77,8 @@ LayerHistory::LayerHistory() : mTraceEnabled(traceEnabled()), mUseFrameRatePriority(useFrameRatePriority()) {} LayerHistory::~LayerHistory() = default; -void LayerHistory::registerLayer(Layer* layer, float lowRefreshRate, float highRefreshRate) { +void LayerHistory::registerLayer(Layer* layer, float lowRefreshRate, float highRefreshRate, + LayerVoteType /*type*/) { auto info = std::make_unique(lowRefreshRate, highRefreshRate); std::lock_guard lock(mLock); mLayerInfos.emplace_back(layer, std::move(info)); @@ -101,8 +102,6 @@ void LayerHistory::record(Layer* layer, nsecs_t presentTime, nsecs_t now) { } LayerHistory::Summary LayerHistory::summarize(nsecs_t now) { - float maxRefreshRate = 0; - std::lock_guard lock(mLock); partitionLayers(now); @@ -113,7 +112,7 @@ LayerHistory::Summary LayerHistory::summarize(nsecs_t now) { if (recent || CC_UNLIKELY(mTraceEnabled)) { const float refreshRate = info->getRefreshRate(now); - if (recent && refreshRate > maxRefreshRate) { + if (recent && refreshRate > 0.0f) { if (const auto layer = activeLayer.promote(); layer) { const int32_t priority = layer->getFrameRateSelectionPriority(); // TODO(b/142507166): This is where the scoring algorithm should live. @@ -124,36 +123,30 @@ LayerHistory::Summary LayerHistory::summarize(nsecs_t now) { } } + LayerHistory::Summary summary; for (const auto& [weakLayer, info] : activeLayers()) { const bool recent = info->isRecentlyActive(now); auto layer = weakLayer.promote(); // Only use the layer if the reference still exists. if (layer || CC_UNLIKELY(mTraceEnabled)) { - float refreshRate = 0.f; - // Default content refresh rate is only used when dealing with recent layers. - if (recent) { - refreshRate = info->getRefreshRate(now); - } // Check if frame rate was set on layer. - float frameRate = layer->getFrameRate(); - if (frameRate > 0.f) { - // Override content detection refresh rate, if it was set. - refreshRate = frameRate; - } - if (refreshRate > maxRefreshRate) { - maxRefreshRate = refreshRate; + auto frameRate = layer->getFrameRate(); + if (frameRate.has_value() && frameRate.value() > 0.f) { + summary.push_back( + {layer->getName(), LayerVoteType::Explicit, *frameRate, /* weight */ 1.0f}); + } else if (recent) { + frameRate = info->getRefreshRate(now); + summary.push_back({layer->getName(), LayerVoteType::Heuristic, *frameRate, + /* weight */ 1.0f}); } if (CC_UNLIKELY(mTraceEnabled)) { - trace(weakLayer, std::round(refreshRate)); + trace(weakLayer, std::round(*frameRate)); } } } - if (CC_UNLIKELY(mTraceEnabled)) { - ALOGD("%s: maxRefreshRate=%.2f", __FUNCTION__, maxRefreshRate); - } - return {maxRefreshRate}; + return summary; } void LayerHistory::partitionLayers(nsecs_t now) { @@ -199,22 +192,6 @@ void LayerHistory::clear() { mActiveLayersEnd = 0; } -bool LayerHistory::hasClientSpecifiedFrameRate() { - std::lock_guard lock(mLock); - for (const auto& [weakLayer, info] : activeLayers()) { - auto layer = weakLayer.promote(); - if (layer) { - float frameRate = layer->getFrameRate(); - // Found a layer that has a frame rate set on it. - if (fabs(frameRate) > 0.f) { - return true; - } - } - } - // Did not find any layers that have frame rate. - return false; -} - } // namespace android::scheduler::impl // TODO(b/129481165): remove the #pragma below and fix conversion issues diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h index f21713411a..bef04e9b42 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.h +++ b/services/surfaceflinger/Scheduler/LayerHistory.h @@ -25,6 +25,8 @@ #include #include +#include "RefreshRateConfigs.h" + namespace android { class Layer; @@ -33,29 +35,32 @@ class TestableScheduler; namespace scheduler { class LayerHistoryTest; +class LayerHistoryTestV2; class LayerInfo; +class LayerInfoV2; class LayerHistory { public: + using LayerVoteType = RefreshRateConfigs::LayerVoteType; + virtual ~LayerHistory() = default; // Layers are unregistered when the weak reference expires. - virtual void registerLayer(Layer*, float lowRefreshRate, float highRefreshRate) = 0; + virtual void registerLayer(Layer*, float lowRefreshRate, float highRefreshRate, + LayerVoteType type) = 0; + + // Sets the display size. Client is responsible for synchronization. + virtual void setDisplayArea(uint32_t displayArea) = 0; // Marks the layer as active, and records the given state to its history. virtual void record(Layer*, nsecs_t presentTime, nsecs_t now) = 0; - struct Summary { - float maxRefreshRate; // Maximum refresh rate among recently active layers. - }; + using Summary = std::vector; // Rebuilds sets of active/inactive layers, and accumulates stats for active layers. virtual Summary summarize(nsecs_t now) = 0; virtual void clear() = 0; - - // Checks whether any of the active layers have a desired frame rate bit set on them. - virtual bool hasClientSpecifiedFrameRate() = 0; }; namespace impl { @@ -68,7 +73,10 @@ public: virtual ~LayerHistory(); // Layers are unregistered when the weak reference expires. - void registerLayer(Layer*, float lowRefreshRate, float highRefreshRate) override; + void registerLayer(Layer*, float lowRefreshRate, float highRefreshRate, + LayerVoteType type) override; + + void setDisplayArea(uint32_t /*displayArea*/) override {} // Marks the layer as active, and records the given state to its history. void record(Layer*, nsecs_t presentTime, nsecs_t now) override; @@ -78,10 +86,6 @@ public: void clear() override; - // Traverses all active layers and checks whether any of them have a desired frame - // rate bit set on them. - bool hasClientSpecifiedFrameRate() override; - private: friend class android::scheduler::LayerHistoryTest; friend TestableScheduler; @@ -91,7 +95,7 @@ private: struct ActiveLayers { LayerInfos& infos; - const size_t index; + const long index; auto begin() { return infos.begin(); } auto end() { return begin() + index; } @@ -106,11 +110,69 @@ private: mutable std::mutex mLock; + // Partitioned such that active layers precede inactive layers. For fast lookup, the few active + // layers are at the front, and weak pointers are stored in contiguous memory to hit the cache. + LayerInfos mLayerInfos GUARDED_BY(mLock); + long mActiveLayersEnd GUARDED_BY(mLock) = 0; + + // Whether to emit systrace output and debug logs. + const bool mTraceEnabled; + + // Whether to use priority sent from WindowManager to determine the relevancy of the layer. + const bool mUseFrameRatePriority; +}; + +class LayerHistoryV2 : public android::scheduler::LayerHistory { +public: + LayerHistoryV2(); + virtual ~LayerHistoryV2(); + + // Layers are unregistered when the weak reference expires. + void registerLayer(Layer*, float lowRefreshRate, float highRefreshRate, + LayerVoteType type) override; + + // Sets the display size. Client is responsible for synchronization. + void setDisplayArea(uint32_t displayArea) override { mDisplayArea = displayArea; } + + // Marks the layer as active, and records the given state to its history. + void record(Layer*, nsecs_t presentTime, nsecs_t now) override; + + // Rebuilds sets of active/inactive layers, and accumulates stats for active layers. + android::scheduler::LayerHistory::Summary summarize(nsecs_t /*now*/) override; + + void clear() override; + +private: + friend android::scheduler::LayerHistoryTestV2; + friend TestableScheduler; + + using LayerPair = std::pair, std::unique_ptr>; + using LayerInfos = std::vector; + + struct ActiveLayers { + LayerInfos& infos; + const size_t index; + + auto begin() { return infos.begin(); } + auto end() { return begin() + static_cast(index); } + }; + + ActiveLayers activeLayers() REQUIRES(mLock) { return {mLayerInfos, mActiveLayersEnd}; } + + // Iterates over layers in a single pass, swapping pairs such that active layers precede + // inactive layers, and inactive layers precede expired layers. Removes expired layers by + // truncating after inactive layers. + void partitionLayers(nsecs_t now) REQUIRES(mLock); + + mutable std::mutex mLock; + // Partitioned such that active layers precede inactive layers. For fast lookup, the few active // layers are at the front, and weak pointers are stored in contiguous memory to hit the cache. LayerInfos mLayerInfos GUARDED_BY(mLock); size_t mActiveLayersEnd GUARDED_BY(mLock) = 0; + uint32_t mDisplayArea = 0; + // Whether to emit systrace output and debug logs. const bool mTraceEnabled; diff --git a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp new file mode 100644 index 0000000000..884b46add2 --- /dev/null +++ b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp @@ -0,0 +1,213 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#undef LOG_TAG +#define LOG_TAG "LayerHistoryV2" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "LayerHistory.h" + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "../Layer.h" +#include "SchedulerUtils.h" + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" + +#include "LayerInfoV2.h" + +namespace android::scheduler::impl { + +namespace { + +bool isLayerActive(const Layer& layer, const LayerInfoV2& info, nsecs_t threshold) { + if (layer.getFrameRate().has_value()) { + return layer.isVisible(); + } + return layer.isVisible() && info.getLastUpdatedTime() >= threshold; +} + +bool traceEnabled() { + return property_get_bool("debug.sf.layer_history_trace", false); +} + +bool useFrameRatePriority() { + char value[PROPERTY_VALUE_MAX]; + property_get("debug.sf.use_frame_rate_priority", value, "1"); + return atoi(value); +} + +void trace(const wp& weak, LayerHistory::LayerVoteType type, int fps) { + const auto layer = weak.promote(); + if (!layer) return; + + const auto& name = layer->getName(); + const auto noVoteTag = "LFPS NoVote " + name; + const auto heuristicVoteTag = "LFPS Heuristic " + name; + const auto explicitVoteTag = "LFPS Explicit " + name; + const auto minVoteTag = "LFPS Min " + name; + const auto maxVoteTag = "LFPS Max " + name; + + ATRACE_INT(noVoteTag.c_str(), type == LayerHistory::LayerVoteType::NoVote ? 1 : 0); + ATRACE_INT(heuristicVoteTag.c_str(), type == LayerHistory::LayerVoteType::Heuristic ? fps : 0); + ATRACE_INT(explicitVoteTag.c_str(), type == LayerHistory::LayerVoteType::Explicit ? fps : 0); + ATRACE_INT(minVoteTag.c_str(), type == LayerHistory::LayerVoteType::Min ? 1 : 0); + ATRACE_INT(maxVoteTag.c_str(), type == LayerHistory::LayerVoteType::Max ? 1 : 0); + + ALOGD("%s: %s @ %d Hz", __FUNCTION__, name.c_str(), fps); +} + +} // namespace + +LayerHistoryV2::LayerHistoryV2() + : mTraceEnabled(traceEnabled()), mUseFrameRatePriority(useFrameRatePriority()) {} +LayerHistoryV2::~LayerHistoryV2() = default; + +void LayerHistoryV2::registerLayer(Layer* layer, float /*lowRefreshRate*/, float highRefreshRate, + LayerVoteType type) { + const nsecs_t highRefreshRatePeriod = static_cast(1e9f / highRefreshRate); + auto info = std::make_unique(highRefreshRatePeriod, type); + std::lock_guard lock(mLock); + mLayerInfos.emplace_back(layer, std::move(info)); +} + +void LayerHistoryV2::record(Layer* layer, nsecs_t presentTime, nsecs_t now) { + std::lock_guard lock(mLock); + + const auto it = std::find_if(mLayerInfos.begin(), mLayerInfos.end(), + [layer](const auto& pair) { return pair.first == layer; }); + LOG_FATAL_IF(it == mLayerInfos.end(), "%s: unknown layer %p", __FUNCTION__, layer); + + const auto& info = it->second; + info->setLastPresentTime(presentTime, now); + + // Activate layer if inactive. + if (const auto end = activeLayers().end(); it >= end) { + std::iter_swap(it, end); + mActiveLayersEnd++; + } +} + +LayerHistoryV2::Summary LayerHistoryV2::summarize(nsecs_t now) { + LayerHistory::Summary summary; + + std::lock_guard lock(mLock); + + partitionLayers(now); + + for (const auto& [layer, info] : activeLayers()) { + const auto strong = layer.promote(); + if (!strong) { + continue; + } + + const bool recent = info->isRecentlyActive(now); + if (recent) { + const auto [type, refreshRate] = info->getRefreshRate(now); + // Skip NoVote layer as those don't have any requirements + if (type == LayerHistory::LayerVoteType::NoVote) { + continue; + } + + // Compute the layer's position on the screen + const Rect bounds = Rect(strong->getBounds()); + const ui::Transform transform = strong->getTransform(); + constexpr bool roundOutwards = true; + Rect transformed = transform.transform(bounds, roundOutwards); + + const float layerArea = transformed.getWidth() * transformed.getHeight(); + float weight = mDisplayArea ? layerArea / mDisplayArea : 0.0f; + summary.push_back({strong->getName(), type, refreshRate, weight}); + + if (CC_UNLIKELY(mTraceEnabled)) { + trace(layer, type, static_cast(std::round(refreshRate))); + } + } else if (CC_UNLIKELY(mTraceEnabled)) { + trace(layer, LayerHistory::LayerVoteType::NoVote, 0); + } + } + + return summary; +} + +void LayerHistoryV2::partitionLayers(nsecs_t now) { + const nsecs_t threshold = getActiveLayerThreshold(now); + + // Collect expired and inactive layers after active layers. + size_t i = 0; + while (i < mActiveLayersEnd) { + auto& [weak, info] = mLayerInfos[i]; + if (const auto layer = weak.promote(); layer && isLayerActive(*layer, *info, threshold)) { + i++; + // Set layer vote if set + const auto frameRate = layer->getFrameRate(); + if (frameRate.has_value()) { + if (*frameRate == Layer::FRAME_RATE_NO_VOTE) { + info->setLayerVote(LayerVoteType::NoVote, 0.f); + } else { + info->setLayerVote(LayerVoteType::Explicit, *frameRate); + } + } else { + info->resetLayerVote(); + } + continue; + } + + if (CC_UNLIKELY(mTraceEnabled)) { + trace(weak, LayerHistory::LayerVoteType::NoVote, 0); + } + + info->clearHistory(); + std::swap(mLayerInfos[i], mLayerInfos[--mActiveLayersEnd]); + } + + // Collect expired layers after inactive layers. + size_t end = mLayerInfos.size(); + while (i < end) { + if (mLayerInfos[i].first.promote()) { + i++; + } else { + std::swap(mLayerInfos[i], mLayerInfos[--end]); + } + } + + mLayerInfos.erase(mLayerInfos.begin() + static_cast(end), mLayerInfos.end()); +} + +void LayerHistoryV2::clear() { + std::lock_guard lock(mLock); + + for (const auto& [layer, info] : activeLayers()) { + info->clearHistory(); + } + + mActiveLayersEnd = 0; +} + +} // namespace android::scheduler::impl diff --git a/services/surfaceflinger/Scheduler/LayerInfoV2.cpp b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp new file mode 100644 index 0000000000..d94d758ec5 --- /dev/null +++ b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp @@ -0,0 +1,139 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// #define LOG_NDEBUG 0 + +#include "LayerInfoV2.h" + +#include +#include + +#undef LOG_TAG +#define LOG_TAG "LayerInfoV2" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +namespace android::scheduler { + +LayerInfoV2::LayerInfoV2(nsecs_t highRefreshRatePeriod, LayerHistory::LayerVoteType defaultVote) + : mHighRefreshRatePeriod(highRefreshRatePeriod), + mDefaultVote(defaultVote), + mLayerVote({defaultVote, 0.0f}) {} + +void LayerInfoV2::setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now) { + lastPresentTime = std::max(lastPresentTime, static_cast(0)); + + mLastUpdatedTime = std::max(lastPresentTime, now); + + FrameTimeData frameTime = {.presetTime = lastPresentTime, .queueTime = mLastUpdatedTime}; + + mFrameTimes.push_back(frameTime); + if (mFrameTimes.size() > HISTORY_SIZE) { + mFrameTimes.pop_front(); + } +} + +// Returns whether the earliest present time is within the active threshold. +bool LayerInfoV2::isRecentlyActive(nsecs_t now) const { + if (mFrameTimes.empty()) { + return false; + } + + return mFrameTimes.back().queueTime >= getActiveLayerThreshold(now); +} + +bool LayerInfoV2::isFrequent(nsecs_t now) const { + // Assume layer is infrequent if too few present times have been recorded. + if (mFrameTimes.size() < FREQUENT_LAYER_WINDOW_SIZE) { + return true; + } + + // Layer is frequent if the earliest value in the window of most recent present times is + // within threshold. + const auto it = mFrameTimes.end() - FREQUENT_LAYER_WINDOW_SIZE; + const nsecs_t threshold = now - MAX_FREQUENT_LAYER_PERIOD_NS.count(); + return it->queueTime >= threshold; +} + +bool LayerInfoV2::hasEnoughDataForHeuristic() const { + // The layer had to publish at least HISTORY_SIZE or HISTORY_TIME of updates + if (mFrameTimes.size() < HISTORY_SIZE && + mFrameTimes.back().queueTime - mFrameTimes.front().queueTime < HISTORY_TIME.count()) { + return false; + } + + return true; +} + +std::optional LayerInfoV2::calculateRefreshRateIfPossible() { + static constexpr float MARGIN = 1.0f; // 1Hz + + if (!hasEnoughDataForHeuristic()) { + ALOGV("Not enough data"); + return std::nullopt; + } + + // Calculate the refresh rate by finding the average delta between frames + nsecs_t totalPresentTimeDeltas = 0; + for (auto it = mFrameTimes.begin(); it != mFrameTimes.end() - 1; ++it) { + // If there are no presentation timestamp provided we can't calculate the refresh rate + if (it->presetTime == 0 || (it + 1)->presetTime == 0) { + return std::nullopt; + } + + totalPresentTimeDeltas += + std::max(((it + 1)->presetTime - it->presetTime), mHighRefreshRatePeriod); + } + const float averageFrameTime = + static_cast(totalPresentTimeDeltas) / (mFrameTimes.size() - 1); + + // Now once we calculated the refresh rate we need to make sure that all the frames we captured + // are evenly distrubuted and we don't calculate the average across some burst of frames. + + for (auto it = mFrameTimes.begin(); it != mFrameTimes.end() - 1; ++it) { + const nsecs_t presentTimeDeltas = + std::max(((it + 1)->presetTime - it->presetTime), mHighRefreshRatePeriod); + if (std::abs(presentTimeDeltas - averageFrameTime) > 2 * averageFrameTime) { + return std::nullopt; + } + } + + const auto refreshRate = 1e9f / averageFrameTime; + if (std::abs(refreshRate - mLastReportedRefreshRate) > MARGIN) { + mLastReportedRefreshRate = refreshRate; + } + + ALOGV("Refresh rate: %.2f", mLastReportedRefreshRate); + return mLastReportedRefreshRate; +} + +std::pair LayerInfoV2::getRefreshRate(nsecs_t now) { + if (mLayerVote.type != LayerHistory::LayerVoteType::Heuristic) { + return {mLayerVote.type, mLayerVote.fps}; + } + + if (!isFrequent(now)) { + return {LayerHistory::LayerVoteType::Min, 0}; + } + + auto refreshRate = calculateRefreshRateIfPossible(); + if (refreshRate.has_value()) { + return {LayerHistory::LayerVoteType::Heuristic, refreshRate.value()}; + } + + return {LayerHistory::LayerVoteType::Max, 0}; +} + +} // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/LayerInfoV2.h b/services/surfaceflinger/Scheduler/LayerInfoV2.h new file mode 100644 index 0000000000..564f05efa2 --- /dev/null +++ b/services/surfaceflinger/Scheduler/LayerInfoV2.h @@ -0,0 +1,117 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include +#include + +#include "LayerHistory.h" +#include "RefreshRateConfigs.h" +#include "SchedulerUtils.h" + +namespace android { + +class Layer; + +namespace scheduler { + +using namespace std::chrono_literals; + +// Maximum period between presents for a layer to be considered active. +constexpr std::chrono::nanoseconds MAX_ACTIVE_LAYER_PERIOD_NS = 1200ms; + +// Earliest present time for a layer to be considered active. +constexpr nsecs_t getActiveLayerThreshold(nsecs_t now) { + return now - MAX_ACTIVE_LAYER_PERIOD_NS.count(); +} + +// Stores history of present times and refresh rates for a layer. +class LayerInfoV2 { + // Layer is considered frequent if the earliest value in the window of most recent present times + // is within a threshold. If a layer is infrequent, its average refresh rate is disregarded in + // favor of a low refresh rate. + static constexpr size_t FREQUENT_LAYER_WINDOW_SIZE = 3; + static constexpr std::chrono::nanoseconds MAX_FREQUENT_LAYER_PERIOD_NS = 250ms; + + friend class LayerHistoryTestV2; + +public: + LayerInfoV2(nsecs_t highRefreshRatePeriod, LayerHistory::LayerVoteType defaultVote); + + LayerInfoV2(const LayerInfo&) = delete; + LayerInfoV2& operator=(const LayerInfoV2&) = delete; + + // Records the last requested present time. It also stores information about when + // the layer was last updated. If the present time is farther in the future than the + // updated time, the updated time is the present time. + void setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now); + + bool isRecentlyActive(nsecs_t now) const; + + // Sets an explicit layer vote. This usually comes directly from the application via + // ANativeWindow_setFrameRate API + void setLayerVote(LayerHistory::LayerVoteType type, float fps) { mLayerVote = {type, fps}; } + + // Sets the default layer vote. This will be the layer vote after calling to resetLayerVote(). + // This is used for layers that called to setLayerVote() and then removed the vote, so that the + // layer can go back to whatever vote it had before the app voted for it. + void setDefaultLayerVote(LayerHistory::LayerVoteType type) { mDefaultVote = type; } + + // Resets the layer vote to its default. + void resetLayerVote() { mLayerVote = {mDefaultVote, 0.0f}; } + + std::pair getRefreshRate(nsecs_t now); + + // Return the last updated time. If the present time is farther in the future than the + // updated time, the updated time is the present time. + nsecs_t getLastUpdatedTime() const { return mLastUpdatedTime; } + + void clearHistory() { mFrameTimes.clear(); } + +private: + bool isFrequent(nsecs_t now) const; + bool hasEnoughDataForHeuristic() const; + std::optional calculateRefreshRateIfPossible(); + + // Used for sanitizing the heuristic data + const nsecs_t mHighRefreshRatePeriod; + LayerHistory::LayerVoteType mDefaultVote; + + nsecs_t mLastUpdatedTime = 0; + + float mLastReportedRefreshRate = 0.0f; + + // Holds information about the layer vote + struct { + LayerHistory::LayerVoteType type; + float fps; + } mLayerVote; + + // Used to store the layer timestamps + struct FrameTimeData { + nsecs_t presetTime; // desiredPresentTime, if provided + nsecs_t queueTime; // buffer queue time + }; + std::deque mFrameTimes; + static constexpr size_t HISTORY_SIZE = 90; + static constexpr std::chrono::nanoseconds HISTORY_TIME = 1s; +}; + +} // namespace scheduler +} // namespace android diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index 45d1f23029..a8f8e0e245 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -14,24 +14,51 @@ * limitations under the License. */ +// #define LOG_NDEBUG 0 +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" -// #define LOG_NDEBUG 0 #include "RefreshRateConfigs.h" +#include +#include +#include +#include + +using namespace std::chrono_literals; namespace android::scheduler { using AllRefreshRatesMapType = RefreshRateConfigs::AllRefreshRatesMapType; using RefreshRate = RefreshRateConfigs::RefreshRate; -// Returns the refresh rate map. This map won't be modified at runtime, so it's safe to access -// from multiple threads. This can only be called if refreshRateSwitching() returns true. -// TODO(b/122916473): Get this information from configs prepared by vendors, instead of -// baking them in. -const RefreshRate& RefreshRateConfigs::getRefreshRateForContent(float contentFramerate) const { +const RefreshRate& RefreshRateConfigs::getRefreshRateForContent( + const std::vector& layers) const { std::lock_guard lock(mLock); + float contentFramerate = 0.0f; + float explicitContentFramerate = 0.0f; + for (const auto& layer : layers) { + if (layer.vote == LayerVoteType::Explicit) { + if (layer.desiredRefreshRate > explicitContentFramerate) { + explicitContentFramerate = layer.desiredRefreshRate; + } + } else { + if (layer.desiredRefreshRate > contentFramerate) { + contentFramerate = layer.desiredRefreshRate; + } + } + } + + if (explicitContentFramerate != 0.0f) { + contentFramerate = explicitContentFramerate; + } else if (contentFramerate == 0.0f) { + contentFramerate = mMaxSupportedRefreshRate->fps; + } + contentFramerate = std::round(contentFramerate); + ATRACE_INT("ContentFPS", contentFramerate); + // Find the appropriate refresh rate with minimal error auto iter = min_element(mAvailableRefreshRates.cbegin(), mAvailableRefreshRates.cend(), [contentFramerate](const auto& lhs, const auto& rhs) -> bool { @@ -60,6 +87,113 @@ const RefreshRate& RefreshRateConfigs::getRefreshRateForContent(float contentFra return *bestSoFar; } +const RefreshRate& RefreshRateConfigs::getRefreshRateForContentV2( + const std::vector& layers) const { + constexpr nsecs_t MARGIN = std::chrono::nanoseconds(800us).count(); + ATRACE_CALL(); + ALOGV("getRefreshRateForContent %zu layers", layers.size()); + + std::lock_guard lock(mLock); + + int noVoteLayers = 0; + int minVoteLayers = 0; + int maxVoteLayers = 0; + int explicitVoteLayers = 0; + for (const auto& layer : layers) { + if (layer.vote == LayerVoteType::NoVote) + noVoteLayers++; + else if (layer.vote == LayerVoteType::Min) + minVoteLayers++; + else if (layer.vote == LayerVoteType::Max) + maxVoteLayers++; + else if (layer.vote == LayerVoteType::Explicit) + explicitVoteLayers++; + } + + // Only if all layers want Min we should return Min + if (noVoteLayers + minVoteLayers == layers.size()) { + return *mAvailableRefreshRates.front(); + } + + // If we have some Max layers and no Explicit we should return Max + if (maxVoteLayers > 0 && explicitVoteLayers == 0) { + return *mAvailableRefreshRates.back(); + } + + // Find the best refresh rate based on score + std::vector> scores; + scores.reserve(mAvailableRefreshRates.size()); + + for (const auto refreshRate : mAvailableRefreshRates) { + scores.emplace_back(refreshRate, 0.0f); + } + + for (const auto& layer : layers) { + if (layer.vote == LayerVoteType::NoVote || layer.vote == LayerVoteType::Min || + layer.vote == LayerVoteType::Max) { + continue; + } + + // If we have Explicit layers, ignore the Huristic ones + if (explicitVoteLayers > 0 && layer.vote == LayerVoteType::Heuristic) { + continue; + } + + for (auto& [refreshRate, overallScore] : scores) { + const auto displayPeriod = refreshRate->vsyncPeriod; + const auto layerPeriod = 1e9f / layer.desiredRefreshRate; + + // Calculate how many display vsyncs we need to present a single frame for this layer + auto [displayFramesQuot, displayFramesRem] = std::div(layerPeriod, displayPeriod); + if (displayFramesRem <= MARGIN || + std::abs(displayFramesRem - displayPeriod) <= MARGIN) { + displayFramesQuot++; + displayFramesRem = 0; + } + + float layerScore; + if (displayFramesRem == 0) { + // Layer desired refresh rate matches the display rate. + layerScore = layer.weight * 1.0f; + } else if (displayFramesQuot == 0) { + // Layer desired refresh rate is higher the display rate. + layerScore = layer.weight * layerPeriod / displayPeriod; + } else { + // Layer desired refresh rate is lower the display rate. Check how well it fits the + // cadence + auto diff = std::abs(displayFramesRem - (displayPeriod - displayFramesRem)); + int iter = 2; + static constexpr size_t MAX_ITERATOR = 10; // Stop calculating when score < 0.1 + while (diff > MARGIN && iter < MAX_ITERATOR) { + diff = diff - (displayPeriod - diff); + iter++; + } + + layerScore = layer.weight * 1.0f / iter; + } + + ALOGV("%s (weight %.2f) %.2fHz gives %s score of %.2f", layer.name.c_str(), + layer.weight, 1e9f / layerPeriod, refreshRate->name.c_str(), layerScore); + overallScore += layerScore; + } + } + + float max = 0; + const RefreshRate* bestRefreshRate = nullptr; + for (const auto [refreshRate, score] : scores) { + ALOGV("%s scores %.2f", refreshRate->name.c_str(), score); + + ATRACE_INT(refreshRate->name.c_str(), std::round(score * 100)); + + if (score > max) { + max = score; + bestRefreshRate = refreshRate; + } + } + + return bestRefreshRate == nullptr ? *mCurrentRefreshRate : *bestRefreshRate; +} + const AllRefreshRatesMapType& RefreshRateConfigs::getAllRefreshRates() const { return mRefreshRates; } @@ -180,14 +314,21 @@ void RefreshRateConfigs::getSortedRefreshRateList( void RefreshRateConfigs::constructAvailableRefreshRates() { // Filter configs based on current policy and sort based on vsync period HwcConfigGroupType group = mRefreshRates.at(mDefaultConfig).configGroup; - ALOGV("constructRefreshRateMap: default %d group %d min %.2f max %.2f", mDefaultConfig.value(), - group.value(), mMinRefreshRateFps, mMaxRefreshRateFps); + ALOGV("constructAvailableRefreshRates: default %d group %d min %.2f max %.2f", + mDefaultConfig.value(), group.value(), mMinRefreshRateFps, mMaxRefreshRateFps); getSortedRefreshRateList( [&](const RefreshRate& refreshRate) REQUIRES(mLock) { return refreshRate.configGroup == group && refreshRate.inPolicy(mMinRefreshRateFps, mMaxRefreshRateFps); }, &mAvailableRefreshRates); + + std::string availableRefreshRates; + for (const auto& refreshRate : mAvailableRefreshRates) { + base::StringAppendF(&availableRefreshRates, "%s ", refreshRate->name.c_str()); + } + + ALOGV("Available refresh rates: %s", availableRefreshRates.c_str()); LOG_ALWAYS_FATAL_IF(mAvailableRefreshRates.empty(), "No compatible display configs for default=%d min=%.0f max=%.0f", mDefaultConfig.value(), mMinRefreshRateFps, mMaxRefreshRateFps); diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index 0c3369a22a..80d42cc620 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -97,8 +97,39 @@ public: // Returns true if this device is doing refresh rate switching. This won't change at runtime. bool refreshRateSwitchingSupported() const { return mRefreshRateSwitching; } + // Describes the different options the layer voted for refresh rate + enum class LayerVoteType { + NoVote, // Doesn't care about the refresh rate + Min, // Minimal refresh rate available + Max, // Maximal refresh rate available + Heuristic, // Specific refresh rate that was calculated by platform using a heuristic + Explicit, // Specific refresh rate that was provided by the app + }; + + // Captures the layer requirements for a refresh rate. This will be used to determine the + // display refresh rate. + struct LayerRequirement { + std::string name; // Layer's name. Used for debugging purposes. + LayerVoteType vote; // Layer vote type. + float desiredRefreshRate; // Layer's desired refresh rate, if applicable. + float weight; // Layer's weight in the range of [0, 1]. The higher the weight the more + // impact this layer would have on choosing the refresh rate. + + bool operator==(const LayerRequirement& other) const { + return name == other.name && vote == other.vote && + desiredRefreshRate == other.desiredRefreshRate && weight == other.weight; + } + + bool operator!=(const LayerRequirement& other) const { return !(*this == other); } + }; + + // Returns all available refresh rates according to the current policy. + const RefreshRate& getRefreshRateForContent(const std::vector& layers) const + EXCLUDES(mLock); + // Returns all available refresh rates according to the current policy. - const RefreshRate& getRefreshRateForContent(float contentFramerate) const EXCLUDES(mLock); + const RefreshRate& getRefreshRateForContentV2(const std::vector& layers) const + EXCLUDES(mLock); // Returns all the refresh rates supported by the device. This won't change at runtime. const AllRefreshRatesMapType& getAllRefreshRates() const EXCLUDES(mLock); diff --git a/services/surfaceflinger/Scheduler/RefreshRateStats.h b/services/surfaceflinger/Scheduler/RefreshRateStats.h index a384dbe29b..e44cd528b5 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateStats.h +++ b/services/surfaceflinger/Scheduler/RefreshRateStats.h @@ -114,7 +114,8 @@ private: mConfigModesTotalTime[mCurrentConfigMode] = 0; } mConfigModesTotalTime[mCurrentConfigMode] += timeElapsedMs; - fps = mRefreshRateConfigs.getRefreshRateFromConfigId(mCurrentConfigMode).fps; + fps = static_cast(std::round( + mRefreshRateConfigs.getRefreshRateFromConfigId(mCurrentConfigMode).fps)); } else { mScreenOffTime += timeElapsedMs; } diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 0b645c41c1..6a437a25ed 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -103,16 +103,21 @@ std::unique_ptr createDispSync() { Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function, const scheduler::RefreshRateConfigs& refreshRateConfig, - ISchedulerCallback& schedulerCallback) + ISchedulerCallback& schedulerCallback, bool useContentDetectionV2) : mPrimaryDispSync(createDispSync()), mEventControlThread(new impl::EventControlThread(std::move(function))), mSupportKernelTimer(sysprop::support_kernel_idle_timer(false)), mSchedulerCallback(schedulerCallback), - mRefreshRateConfigs(refreshRateConfig) { + mRefreshRateConfigs(refreshRateConfig), + mUseContentDetectionV2(useContentDetectionV2) { using namespace sysprop; if (property_get_bool("debug.sf.use_smart_90_for_video", 0) || use_smart_90_for_video(false)) { - mLayerHistory = std::make_unique(); + if (mUseContentDetectionV2) { + mLayerHistory = std::make_unique(); + } else { + mLayerHistory = std::make_unique(); + } } const int setIdleTimerMs = property_get_int32("debug.sf.set_idle_timer_ms", 0); @@ -120,7 +125,6 @@ Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function, if (const auto millis = setIdleTimerMs ? setIdleTimerMs : set_idle_timer_ms(0); millis > 0) { const auto callback = mSupportKernelTimer ? &Scheduler::kernelIdleTimerCallback : &Scheduler::idleTimerCallback; - mIdleTimer.emplace( std::chrono::milliseconds(millis), [this, callback] { std::invoke(callback, this, TimerState::Reset); }, @@ -149,12 +153,13 @@ Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function, Scheduler::Scheduler(std::unique_ptr primaryDispSync, std::unique_ptr eventControlThread, const scheduler::RefreshRateConfigs& configs, - ISchedulerCallback& schedulerCallback) + ISchedulerCallback& schedulerCallback, bool useContentDetectionV2) : mPrimaryDispSync(std::move(primaryDispSync)), mEventControlThread(std::move(eventControlThread)), mSupportKernelTimer(false), mSchedulerCallback(schedulerCallback), - mRefreshRateConfigs(configs) {} + mRefreshRateConfigs(configs), + mUseContentDetectionV2(useContentDetectionV2) {} Scheduler::~Scheduler() { // Ensure the OneShotTimer threads are joined before we start destroying state. @@ -375,12 +380,42 @@ nsecs_t Scheduler::getDispSyncExpectedPresentTime() { void Scheduler::registerLayer(Layer* layer) { if (!mLayerHistory) return; - const auto lowFps = mRefreshRateConfigs.getMinRefreshRate().fps; - const auto highFps = layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER - ? lowFps - : mRefreshRateConfigs.getMaxRefreshRate().fps; + if (!mUseContentDetectionV2) { + const auto lowFps = mRefreshRateConfigs.getMinRefreshRate().fps; + const auto highFps = layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER + ? lowFps + : mRefreshRateConfigs.getMaxRefreshRate().fps; - mLayerHistory->registerLayer(layer, lowFps, highFps); + mLayerHistory->registerLayer(layer, lowFps, highFps, + scheduler::LayerHistory::LayerVoteType::Heuristic); + } else { + if (layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER) { + mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().fps, + mRefreshRateConfigs.getMaxRefreshRate().fps, + scheduler::LayerHistory::LayerVoteType::Min); + } else if (layer->getWindowType() == InputWindowInfo::TYPE_STATUS_BAR) { + mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().fps, + mRefreshRateConfigs.getMaxRefreshRate().fps, + scheduler::LayerHistory::LayerVoteType::NoVote); + } else { + mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().fps, + mRefreshRateConfigs.getMaxRefreshRate().fps, + scheduler::LayerHistory::LayerVoteType::Heuristic); + } + + // TODO(146935143): Simulate youtube app vote. This should be removed once youtube calls the + // API to set desired rate + { + const auto vote = property_get_int32("experimental.sf.force_youtube_vote", 0); + if (vote != 0 && + layer->getName() == + "SurfaceView - " + "com.google.android.youtube/" + "com.google.android.apps.youtube.app.WatchWhileActivity#0") { + layer->setFrameRate(vote); + } + } + } } void Scheduler::recordLayerHistory(Layer* layer, nsecs_t presentTime) { @@ -392,27 +427,27 @@ void Scheduler::recordLayerHistory(Layer* layer, nsecs_t presentTime) { void Scheduler::chooseRefreshRateForContent() { if (!mLayerHistory) return; - auto [refreshRate] = mLayerHistory->summarize(systemTime()); - const uint32_t refreshRateRound = std::round(refreshRate); + ATRACE_CALL(); + + scheduler::LayerHistory::Summary summary = mLayerHistory->summarize(systemTime()); HwcConfigIndexType newConfigId; { std::lock_guard lock(mFeatureStateLock); - if (mFeatures.contentRefreshRate == refreshRateRound) { + if (mFeatures.contentRequirements == summary) { return; } - mFeatures.contentRefreshRate = refreshRateRound; - ATRACE_INT("ContentFPS", refreshRateRound); - + mFeatures.contentRequirements = summary; mFeatures.contentDetection = - refreshRateRound > 0 ? ContentDetectionState::On : ContentDetectionState::Off; + !summary.empty() ? ContentDetectionState::On : ContentDetectionState::Off; + newConfigId = calculateRefreshRateType(); if (mFeatures.configId == newConfigId) { return; } mFeatures.configId = newConfigId; - }; - auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); - mSchedulerCallback.changeRefreshRate(newRefreshRate, ConfigEvent::Changed); + auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); + mSchedulerCallback.changeRefreshRate(newRefreshRate, ConfigEvent::Changed); + } } void Scheduler::resetIdleTimer() { @@ -422,16 +457,17 @@ void Scheduler::resetIdleTimer() { } void Scheduler::notifyTouchEvent() { + if (!mTouchTimer) return; + // Touch event will boost the refresh rate to performance. // Clear Layer History to get fresh FPS detection. // NOTE: Instead of checking all the layers, we should be checking the layer // that is currently on top. b/142507166 will give us this capability. - if (mLayerHistory && !mLayerHistory->hasClientSpecifiedFrameRate()) { + std::lock_guard lock(mFeatureStateLock); + if (mLayerHistory && !layerHistoryHasClientSpecifiedFrameRate()) { mLayerHistory->clear(); - if (mTouchTimer) { - mTouchTimer->reset(); - } + mTouchTimer->reset(); if (mSupportKernelTimer && mIdleTimer) { mIdleTimer->reset(); @@ -530,6 +566,16 @@ void Scheduler::handleTimerStateChanged(T* currentState, T newState, bool eventO mSchedulerCallback.changeRefreshRate(newRefreshRate, event); } +bool Scheduler::layerHistoryHasClientSpecifiedFrameRate() { + for (const auto& layer : mFeatures.contentRequirements) { + if (layer.vote == scheduler::RefreshRateConfigs::LayerVoteType::Explicit) { + return true; + } + } + + return false; +} + HwcConfigIndexType Scheduler::calculateRefreshRateType() { if (!mRefreshRateConfigs.refreshRateSwitchingSupported()) { return mRefreshRateConfigs.getCurrentRefreshRate().configId; @@ -538,7 +584,7 @@ HwcConfigIndexType Scheduler::calculateRefreshRateType() { // If the layer history doesn't have the frame rate specified, use the old path. NOTE: // if we remove the kernel idle timer, and use our internal idle timer, this code will have to // be refactored. - if (!mLayerHistory->hasClientSpecifiedFrameRate()) { + if (!layerHistoryHasClientSpecifiedFrameRate()) { // If Display Power is not in normal operation we want to be in performance mode. // When coming back to normal mode, a grace period is given with DisplayPowerTimer if (!mFeatures.isDisplayPowerStateNormal || @@ -555,17 +601,26 @@ HwcConfigIndexType Scheduler::calculateRefreshRateType() { if (mFeatures.idleTimer == TimerState::Expired) { return mRefreshRateConfigs.getMinRefreshRateByPolicy().configId; } + } + if (!mUseContentDetectionV2) { // If content detection is off we choose performance as we don't know the content fps if (mFeatures.contentDetection == ContentDetectionState::Off) { return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId; } + + // Content detection is on, find the appropriate refresh rate with minimal error + return mRefreshRateConfigs.getRefreshRateForContent(mFeatures.contentRequirements).configId; } // Content detection is on, find the appropriate refresh rate with minimal error - return mRefreshRateConfigs - .getRefreshRateForContent(static_cast(mFeatures.contentRefreshRate)) - .configId; + if (mFeatures.contentDetection == ContentDetectionState::On) { + return mRefreshRateConfigs.getRefreshRateForContentV2(mFeatures.contentRequirements) + .configId; + } + + // There are no signals for refresh rate, just leave it as is + return mRefreshRateConfigs.getCurrentRefreshRate().configId; } std::optional Scheduler::getPreferredConfigId() { @@ -606,6 +661,12 @@ void Scheduler::onDisplayRefreshed(nsecs_t timestamp) { } } +void Scheduler::onPrimaryDisplayAreaChanged(uint32_t displayArea) { + if (mLayerHistory) { + mLayerHistory->setDisplayArea(displayArea); + } +} + } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index c6430c30f5..2987424c99 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -58,7 +58,8 @@ public: enum class TransactionStart { EARLY, NORMAL }; Scheduler(impl::EventControlThread::SetVSyncEnabledFunction, - const scheduler::RefreshRateConfigs&, ISchedulerCallback& schedulerCallback); + const scheduler::RefreshRateConfigs&, ISchedulerCallback& schedulerCallback, + bool useContentDetectionV2); virtual ~Scheduler(); @@ -136,6 +137,9 @@ public: // Notifies the scheduler when the display was refreshed void onDisplayRefreshed(nsecs_t timestamp); + // Notifies the scheduler when the display size has changed. Called from SF's main thread + void onPrimaryDisplayAreaChanged(uint32_t displayArea); + private: friend class TestableScheduler; @@ -147,7 +151,8 @@ private: // Used by tests to inject mocks. Scheduler(std::unique_ptr, std::unique_ptr, - const scheduler::RefreshRateConfigs&, ISchedulerCallback& schedulerCallback); + const scheduler::RefreshRateConfigs&, ISchedulerCallback& schedulerCallback, + bool useContentDetectionV2); std::unique_ptr makePrimaryDispSyncSource(const char* name, nsecs_t phaseOffsetNs); @@ -170,6 +175,8 @@ private: HwcConfigIndexType calculateRefreshRateType() REQUIRES(mFeatureStateLock); + bool layerHistoryHasClientSpecifiedFrameRate() REQUIRES(mFeatureStateLock); + // Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection. struct Connection { sp connection; @@ -218,7 +225,7 @@ private: TimerState displayPowerTimer = TimerState::Expired; std::optional configId; - uint32_t contentRefreshRate = 0; + scheduler::LayerHistory::Summary contentRequirements; bool isDisplayPowerStateNormal = true; } mFeatures GUARDED_BY(mFeatureStateLock); @@ -229,6 +236,8 @@ private: std::optional mLastVsyncPeriodChangeTimeline GUARDED_BY(mVsyncTimelineLock); static constexpr std::chrono::nanoseconds MAX_VSYNC_APPLIED_TIME = 200ms; + + const bool mUseContentDetectionV2; }; } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 6d18922a78..adf5f9f4a4 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -540,6 +540,11 @@ void SurfaceFlinger::bootFinished() const auto& performanceRefreshRate = mRefreshRateConfigs->getMaxRefreshRateByPolicy(); changeRefreshRateLocked(performanceRefreshRate, Scheduler::ConfigEvent::None); } + + if (property_get_bool("sf.debug.show_refresh_rate_overlay", false)) { + mRefreshRateOverlay = std::make_unique(*this); + mRefreshRateOverlay->changeRefreshRate(mRefreshRateConfigs->getCurrentRefreshRate()); + } })); } @@ -1779,7 +1784,13 @@ void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS { // Layers need to get updated (in the previous line) before we can use them for // choosing the refresh rate. - mScheduler->chooseRefreshRateForContent(); + // Hold mStateLock as chooseRefreshRateForContent promotes wp to sp + // and may eventually call to ~Layer() if it holds the last reference + { + Mutex::Autolock _l(mStateLock); + mScheduler->chooseRefreshRateForContent(); + } + if (performSetActiveConfig()) { break; } @@ -2378,6 +2389,9 @@ void SurfaceFlinger::processDisplayChangesLocked() { } if (state.width != draw[i].width || state.height != draw[i].height) { display->setDisplaySize(state.width, state.height); + if (display->isPrimary()) { + mScheduler->onPrimaryDisplayAreaChanged(state.width * state.height); + } } } } @@ -2450,6 +2464,12 @@ void SurfaceFlinger::processDisplayChangesLocked() { LOG_ALWAYS_FATAL_IF(!displayId); dispatchDisplayHotplugEvent(displayId->value, true); } + + const auto displayDevice = mDisplays[displayToken]; + if (displayDevice->isPrimary()) { + mScheduler->onPrimaryDisplayAreaChanged(displayDevice->getWidth() * + displayDevice->getHeight()); + } } } } @@ -2647,8 +2667,12 @@ void SurfaceFlinger::updateCursorAsync() } void SurfaceFlinger::changeRefreshRate(const RefreshRate& refreshRate, - Scheduler::ConfigEvent event) { - Mutex::Autolock lock(mStateLock); + Scheduler::ConfigEvent event) NO_THREAD_SAFETY_ANALYSIS { + // If this is called from the main thread mStateLock must be locked before + // Currently the only way to call this function from the main thread is from + // Sheduler::chooseRefreshRateForContent + + ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId); changeRefreshRateLocked(refreshRate, event); } diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp index e12d31a99a..45889a564e 100644 --- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp +++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp @@ -75,7 +75,9 @@ std::unique_ptr DefaultFactory::createPhaseConfig std::unique_ptr DefaultFactory::createScheduler( SetVSyncEnabled setVSyncEnabled, const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& schedulerCallback) { - return std::make_unique(std::move(setVSyncEnabled), configs, schedulerCallback); + return std::make_unique(std::move(setVSyncEnabled), configs, schedulerCallback, + property_get_bool("debug.sf.use_content_detection_v2", + false)); } std::unique_ptr DefaultFactory::createSurfaceInterceptor( diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index 1eaf2dd004..d046f765e8 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -44,6 +44,7 @@ cc_test { "EventThreadTest.cpp", "OneShotTimerTest.cpp", "LayerHistoryTest.cpp", + "LayerHistoryTestV2.cpp", "LayerMetadataTest.cpp", "PhaseOffsetsTest.cpp", "SchedulerTest.cpp", diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index ca51cb6f6d..9ca1b70a1f 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -73,7 +73,7 @@ protected: HI_FPS_PERIOD}, }, HwcConfigIndexType(0)}; - TestableScheduler* const mScheduler{new TestableScheduler(mConfigs)}; + TestableScheduler* const mScheduler{new TestableScheduler(mConfigs, false)}; TestableSurfaceFlinger mFlinger; const nsecs_t mTime = systemTime(); @@ -85,53 +85,36 @@ TEST_F(LayerHistoryTest, oneLayer) { const auto layer = createLayer(); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*layer, getFrameSelectionPriority()).WillRepeatedly(Return(1)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(std::nullopt)); EXPECT_EQ(1, layerCount()); EXPECT_EQ(0, activeLayerCount()); - // 0 FPS is returned if no layers are active. - EXPECT_FLOAT_EQ(0, history().summarize(mTime).maxRefreshRate); + // no layers are returned if no layers are active. + ASSERT_TRUE(history().summarize(mTime).empty()); EXPECT_EQ(0, activeLayerCount()); - // 0 FPS is returned if active layers have insufficient history. + // no layers are returned if active layers have insufficient history. for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - 1; i++) { history().record(layer.get(), 0, mTime); - EXPECT_FLOAT_EQ(0, history().summarize(mTime).maxRefreshRate); + ASSERT_TRUE(history().summarize(mTime).empty()); EXPECT_EQ(1, activeLayerCount()); } // High FPS is returned once enough history has been recorded. for (int i = 0; i < 10; i++) { history().record(layer.get(), 0, mTime); - EXPECT_FLOAT_EQ(HI_FPS, history().summarize(mTime).maxRefreshRate); + ASSERT_EQ(1, history().summarize(mTime).size()); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(mTime)[0].desiredRefreshRate); EXPECT_EQ(1, activeLayerCount()); } } -TEST_F(LayerHistoryTest, oneHDRLayer) { - const auto layer = createLayer(); - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameSelectionPriority()).WillRepeatedly(Return(1)); - - EXPECT_EQ(1, layerCount()); - EXPECT_EQ(0, activeLayerCount()); - - history().record(layer.get(), 0, mTime); - auto summary = history().summarize(mTime); - EXPECT_FLOAT_EQ(0, summary.maxRefreshRate); - EXPECT_EQ(1, activeLayerCount()); - - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(false)); - - summary = history().summarize(mTime); - EXPECT_FLOAT_EQ(0, summary.maxRefreshRate); - EXPECT_EQ(0, activeLayerCount()); -} - TEST_F(LayerHistoryTest, explicitTimestamp) { const auto layer = createLayer(); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*layer, getFrameSelectionPriority()).WillRepeatedly(Return(1)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(std::nullopt)); EXPECT_EQ(1, layerCount()); EXPECT_EQ(0, activeLayerCount()); @@ -142,7 +125,8 @@ TEST_F(LayerHistoryTest, explicitTimestamp) { time += LO_FPS_PERIOD; } - EXPECT_FLOAT_EQ(LO_FPS, history().summarize(mTime).maxRefreshRate); + ASSERT_EQ(1, history().summarize(mTime).size()); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(mTime)[0].desiredRefreshRate); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); } @@ -154,13 +138,15 @@ TEST_F(LayerHistoryTest, multipleLayers) { EXPECT_CALL(*layer1, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*layer1, getFrameSelectionPriority()).WillRepeatedly(Return(1)); + EXPECT_CALL(*layer1, getFrameRate()).WillRepeatedly(Return(std::nullopt)); EXPECT_CALL(*layer2, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*layer2, getFrameSelectionPriority()).WillRepeatedly(Return(1)); + EXPECT_CALL(*layer2, getFrameRate()).WillRepeatedly(Return(std::nullopt)); EXPECT_CALL(*layer3, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*layer3, getFrameSelectionPriority()).WillRepeatedly(Return(1)); - + EXPECT_CALL(*layer3, getFrameRate()).WillRepeatedly(Return(std::nullopt)); nsecs_t time = mTime; EXPECT_EQ(3, layerCount()); @@ -173,7 +159,8 @@ TEST_F(LayerHistoryTest, multipleLayers) { time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); } - EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time).maxRefreshRate); + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(0, frequentLayerCount(time)); @@ -186,7 +173,9 @@ TEST_F(LayerHistoryTest, multipleLayers) { // layer1 is still active but infrequent. history().record(layer1.get(), time, time); - EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time).maxRefreshRate); + ASSERT_EQ(2, history().summarize(time).size()); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time)[1].desiredRefreshRate); EXPECT_EQ(2, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); @@ -197,7 +186,8 @@ TEST_F(LayerHistoryTest, multipleLayers) { time += LO_FPS_PERIOD; } - EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time).maxRefreshRate); + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); @@ -213,19 +203,24 @@ TEST_F(LayerHistoryTest, multipleLayers) { time += HI_FPS_PERIOD; } - EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time).maxRefreshRate); + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); EXPECT_EQ(2, activeLayerCount()); EXPECT_EQ(2, frequentLayerCount(time)); // layer3 becomes recently active. history().record(layer3.get(), time, time); - EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time).maxRefreshRate); + ASSERT_EQ(2, history().summarize(time).size()); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time)[1].desiredRefreshRate); EXPECT_EQ(2, activeLayerCount()); EXPECT_EQ(2, frequentLayerCount(time)); // layer1 expires. layer1.clear(); - EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time).maxRefreshRate); + ASSERT_EQ(2, history().summarize(time).size()); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time)[1].desiredRefreshRate); EXPECT_EQ(2, layerCount()); EXPECT_EQ(2, activeLayerCount()); EXPECT_EQ(2, frequentLayerCount(time)); @@ -237,13 +232,14 @@ TEST_F(LayerHistoryTest, multipleLayers) { time += LO_FPS_PERIOD; } - EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time).maxRefreshRate); + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); // layer2 expires. layer2.clear(); - EXPECT_FLOAT_EQ(0, history().summarize(time).maxRefreshRate); + ASSERT_TRUE(history().summarize(time).empty()); EXPECT_EQ(1, layerCount()); EXPECT_EQ(0, activeLayerCount()); EXPECT_EQ(0, frequentLayerCount(time)); @@ -254,14 +250,15 @@ TEST_F(LayerHistoryTest, multipleLayers) { time += HI_FPS_PERIOD; } - EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time).maxRefreshRate); + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time)[0].desiredRefreshRate); EXPECT_EQ(1, layerCount()); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); // layer3 expires. layer3.clear(); - EXPECT_FLOAT_EQ(0, history().summarize(time).maxRefreshRate); + ASSERT_TRUE(history().summarize(time).empty()); EXPECT_EQ(0, layerCount()); EXPECT_EQ(0, activeLayerCount()); EXPECT_EQ(0, frequentLayerCount(time)); diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp new file mode 100644 index 0000000000..11ace0576d --- /dev/null +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp @@ -0,0 +1,418 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#undef LOG_TAG +#define LOG_TAG "LayerHistoryTestV2" + +#include +#include +#include + +#include "Scheduler/LayerHistory.h" +#include "Scheduler/LayerInfoV2.h" +#include "TestableScheduler.h" +#include "TestableSurfaceFlinger.h" +#include "mock/MockLayer.h" + +using testing::_; +using testing::Return; + +namespace android::scheduler { + +class LayerHistoryTestV2 : public testing::Test { +protected: + static constexpr auto PRESENT_TIME_HISTORY_SIZE = LayerInfoV2::HISTORY_SIZE; + static constexpr auto MAX_FREQUENT_LAYER_PERIOD_NS = LayerInfoV2::MAX_FREQUENT_LAYER_PERIOD_NS; + + static constexpr float LO_FPS = 30.f; + static constexpr auto LO_FPS_PERIOD = static_cast(1e9f / LO_FPS); + + static constexpr float HI_FPS = 90.f; + static constexpr auto HI_FPS_PERIOD = static_cast(1e9f / HI_FPS); + + LayerHistoryTestV2() { mFlinger.resetScheduler(mScheduler); } + + impl::LayerHistoryV2& history() { return *mScheduler->mutableLayerHistoryV2(); } + const impl::LayerHistoryV2& history() const { return *mScheduler->mutableLayerHistoryV2(); } + + size_t layerCount() const { return mScheduler->layerHistorySize(); } + size_t activeLayerCount() const NO_THREAD_SAFETY_ANALYSIS { return history().mActiveLayersEnd; } + + auto frequentLayerCount(nsecs_t now) const NO_THREAD_SAFETY_ANALYSIS { + const auto& infos = history().mLayerInfos; + return std::count_if(infos.begin(), + infos.begin() + static_cast(history().mActiveLayersEnd), + [now](const auto& pair) { return pair.second->isFrequent(now); }); + } + + void setLayerInfoVote(Layer* layer, + LayerHistory::LayerVoteType vote) NO_THREAD_SAFETY_ANALYSIS { + for (auto& [weak, info] : history().mLayerInfos) { + if (auto strong = weak.promote(); strong && strong.get() == layer) { + info->setDefaultLayerVote(vote); + info->setLayerVote(vote, 0); + return; + } + } + } + + auto createLayer() { return sp(new mock::MockLayer(mFlinger.flinger())); } + + RefreshRateConfigs mConfigs{true, + { + RefreshRateConfigs::InputConfig{HwcConfigIndexType(0), + HwcConfigGroupType(0), + LO_FPS_PERIOD}, + RefreshRateConfigs::InputConfig{HwcConfigIndexType(1), + HwcConfigGroupType(0), + HI_FPS_PERIOD}, + }, + HwcConfigIndexType(0)}; + TestableScheduler* const mScheduler{new TestableScheduler(mConfigs, true)}; + TestableSurfaceFlinger mFlinger; + + const nsecs_t mTime = systemTime(); +}; + +namespace { + +TEST_F(LayerHistoryTestV2, oneLayer) { + const auto layer = createLayer(); + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + // No layers returned if no layers are active. + EXPECT_TRUE(history().summarize(mTime).empty()); + EXPECT_EQ(0, activeLayerCount()); + + // Max returned if active layers have insufficient history. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - 1; i++) { + history().record(layer.get(), 0, mTime); + ASSERT_EQ(1, history().summarize(mTime).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(mTime)[0].vote); + EXPECT_EQ(1, activeLayerCount()); + } + + // Max is returned since we have enough history but there is no timestamp votes. + for (int i = 0; i < 10; i++) { + history().record(layer.get(), 0, mTime); + ASSERT_EQ(1, history().summarize(mTime).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(mTime)[0].vote); + EXPECT_EQ(1, activeLayerCount()); + } +} + +TEST_F(LayerHistoryTestV2, oneInvisibleLayer) { + const auto layer = createLayer(); + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + history().record(layer.get(), 0, mTime); + auto summary = history().summarize(mTime); + ASSERT_EQ(1, history().summarize(mTime).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(mTime)[0].vote); + EXPECT_EQ(1, activeLayerCount()); + + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(false)); + + summary = history().summarize(mTime); + EXPECT_TRUE(history().summarize(mTime).empty()); + EXPECT_EQ(0, activeLayerCount()); +} + +TEST_F(LayerHistoryTestV2, explicitTimestamp) { + const auto layer = createLayer(); + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + nsecs_t time = mTime; + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer.get(), time, time); + time += LO_FPS_PERIOD; + } + + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); +} + +TEST_F(LayerHistoryTestV2, oneLayerNoVote) { + const auto layer = createLayer(); + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + + setLayerInfoVote(layer.get(), LayerHistory::LayerVoteType::NoVote); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + nsecs_t time = mTime; + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer.get(), time, time); + time += HI_FPS_PERIOD; + } + + ASSERT_TRUE(history().summarize(time).empty()); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer became inactive + time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); + ASSERT_TRUE(history().summarize(time).empty()); + EXPECT_EQ(0, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); +} + +TEST_F(LayerHistoryTestV2, oneLayerMinVote) { + const auto layer = createLayer(); + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + + setLayerInfoVote(layer.get(), LayerHistory::LayerVoteType::Min); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + nsecs_t time = mTime; + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer.get(), time, time); + time += HI_FPS_PERIOD; + } + + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer became inactive + time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); + ASSERT_TRUE(history().summarize(time).empty()); + EXPECT_EQ(0, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); +} + +TEST_F(LayerHistoryTestV2, oneLayerMaxVote) { + const auto layer = createLayer(); + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + + setLayerInfoVote(layer.get(), LayerHistory::LayerVoteType::Max); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + nsecs_t time = mTime; + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer.get(), time, time); + time += LO_FPS_PERIOD; + } + + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer became inactive + time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); + ASSERT_TRUE(history().summarize(time).empty()); + EXPECT_EQ(0, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); +} + +TEST_F(LayerHistoryTestV2, oneLayerExplicitVote) { + auto layer = createLayer(); + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(73.4f)); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + nsecs_t time = mTime; + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer.get(), time, time); + time += HI_FPS_PERIOD; + } + + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Explicit, history().summarize(time)[0].vote); + EXPECT_FLOAT_EQ(73.4f, history().summarize(time)[0].desiredRefreshRate); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer became inactive + setLayerInfoVote(layer.get(), LayerHistory::LayerVoteType::Heuristic); + time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); + ASSERT_TRUE(history().summarize(time).empty()); + // TODO: activeLayerCount() should be 0 but it is 1 since getFrameRate() returns a value > 0 + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); +} + +TEST_F(LayerHistoryTestV2, multipleLayers) { + auto layer1 = createLayer(); + auto layer2 = createLayer(); + auto layer3 = createLayer(); + + EXPECT_CALL(*layer1, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer1, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + + EXPECT_CALL(*layer2, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer2, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + + EXPECT_CALL(*layer3, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer3, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + + nsecs_t time = mTime; + + EXPECT_EQ(3, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + // layer1 is active but infrequent. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer1.get(), time, time); + time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); + } + + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + // layer2 is frequent and has high refresh rate. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer2.get(), time, time); + time += HI_FPS_PERIOD; + } + + // layer1 is still active but infrequent. + history().record(layer1.get(), time, time); + + ASSERT_EQ(2, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[1].vote); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time)[1].desiredRefreshRate); + EXPECT_EQ(2, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer1 is no longer active. + // layer2 is frequent and has low refresh rate. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer2.get(), time, time); + time += LO_FPS_PERIOD; + } + + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer2 still has low refresh rate. + // layer3 has high refresh rate but not enough history. + constexpr int RATIO = LO_FPS_PERIOD / HI_FPS_PERIOD; + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - 1; i++) { + if (i % RATIO == 0) { + history().record(layer2.get(), time, time); + } + + history().record(layer3.get(), time, time); + time += HI_FPS_PERIOD; + } + + ASSERT_EQ(2, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[1].vote); + EXPECT_EQ(2, activeLayerCount()); + EXPECT_EQ(2, frequentLayerCount(time)); + + // layer3 becomes recently active. + history().record(layer3.get(), time, time); + ASSERT_EQ(2, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[1].vote); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time)[1].desiredRefreshRate); + EXPECT_EQ(2, activeLayerCount()); + EXPECT_EQ(2, frequentLayerCount(time)); + + // layer1 expires. + layer1.clear(); + ASSERT_EQ(2, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[1].vote); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time)[1].desiredRefreshRate); + EXPECT_EQ(2, layerCount()); + EXPECT_EQ(2, activeLayerCount()); + EXPECT_EQ(2, frequentLayerCount(time)); + + // layer2 still has low refresh rate. + // layer3 becomes inactive. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer2.get(), time, time); + time += LO_FPS_PERIOD; + } + + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer2 expires. + layer2.clear(); + EXPECT_TRUE(history().summarize(time).empty()); + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + // layer3 becomes active and has high refresh rate. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer3.get(), time, time); + time += HI_FPS_PERIOD; + } + + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time)[0].desiredRefreshRate); + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer3 expires. + layer3.clear(); + EXPECT_TRUE(history().summarize(time).empty()); + EXPECT_EQ(0, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); +} + +} // namespace +} // namespace android::scheduler diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp index 86aa8fb22b..78009b8122 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -31,16 +31,24 @@ namespace android { namespace scheduler { using RefreshRate = RefreshRateConfigs::RefreshRate; +using LayerVoteType = RefreshRateConfigs::LayerVoteType; +using LayerRequirement = RefreshRateConfigs::LayerRequirement; class RefreshRateConfigsTest : public testing::Test { protected: static inline const HwcConfigIndexType HWC_CONFIG_ID_60 = HwcConfigIndexType(0); - static inline const HwcConfigIndexType HWC_CONFIG_ID_90 = HwcConfigIndexType(1); + static inline const HwcConfigIndexType HWC_CONFIG_ID_72 = HwcConfigIndexType(1); + static inline const HwcConfigIndexType HWC_CONFIG_ID_90 = HwcConfigIndexType(2); + static inline const HwcConfigIndexType HWC_CONFIG_ID_120 = HwcConfigIndexType(3); + static inline const HwcConfigIndexType HWC_CONFIG_ID_30 = HwcConfigIndexType(4); static inline const HwcConfigGroupType HWC_GROUP_ID_0 = HwcConfigGroupType(0); static inline const HwcConfigGroupType HWC_GROUP_ID_1 = HwcConfigGroupType(1); - static constexpr int64_t VSYNC_60 = 16666667; + static constexpr auto VSYNC_30 = static_cast(1e9f / 30); + static constexpr auto VSYNC_60 = static_cast(1e9f / 60); + static constexpr auto VSYNC_72 = static_cast(1e9f / 72); + static constexpr auto VSYNC_90 = static_cast(1e9f / 90); + static constexpr auto VSYNC_120 = static_cast(1e9f / 120); static constexpr int64_t VSYNC_60_POINT_4 = 16666665; - static constexpr int64_t VSYNC_90 = 11111111; RefreshRateConfigsTest(); ~RefreshRateConfigsTest(); @@ -212,31 +220,476 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContent) { RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; - ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(90.0f)); - ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(60.0f)); - ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(45.0f)); - ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(30.0f)); - ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(24.0f)); + const auto makeLayerRequirements = [](float refreshRate) -> std::vector { + return {{"testLayer", LayerVoteType::Heuristic, refreshRate, 1.0f}}; + }; + + EXPECT_EQ(expected90Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(90.0f))); + EXPECT_EQ(expected60Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(60.0f))); + EXPECT_EQ(expected90Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(45.0f))); + EXPECT_EQ(expected60Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(30.0f))); + EXPECT_EQ(expected60Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(24.0f))); ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 60, 60, nullptr), 0); - ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(90.0f)); - ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(60.0f)); - ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(45.0f)); - ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(30.0f)); - ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(24.0f)); + EXPECT_EQ(expected60Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(90.0f))); + EXPECT_EQ(expected60Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(60.0f))); + EXPECT_EQ(expected60Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(45.0f))); + EXPECT_EQ(expected60Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(30.0f))); + EXPECT_EQ(expected60Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(24.0f))); ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_90, 90, 90, nullptr), 0); - ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(90.0f)); - ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(60.0f)); - ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(45.0f)); - ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(30.0f)); - ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(24.0f)); + EXPECT_EQ(expected90Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(90.0f))); + EXPECT_EQ(expected90Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(60.0f))); + EXPECT_EQ(expected90Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(45.0f))); + EXPECT_EQ(expected90Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(30.0f))); + EXPECT_EQ(expected90Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(24.0f))); ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 0, 120, nullptr), 0); - ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(90.0f)); - ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(60.0f)); - ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(45.0f)); - ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(30.0f)); - ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(24.0f)); + EXPECT_EQ(expected90Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(90.0f))); + EXPECT_EQ(expected60Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(60.0f))); + EXPECT_EQ(expected90Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(45.0f))); + EXPECT_EQ(expected60Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(30.0f))); + EXPECT_EQ(expected60Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(24.0f))); +} + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_60_90) { + std::vector configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/true, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + + RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + + auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; + auto& lr = layers[0]; + + lr.vote = LayerVoteType::Min; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.vote = LayerVoteType::Max; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 90.0f; + lr.vote = LayerVoteType::Heuristic; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 60.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 45.0f; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 30.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 24.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 60, 60, nullptr), 0); + + lr.vote = LayerVoteType::Min; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.vote = LayerVoteType::Max; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 90.0f; + lr.vote = LayerVoteType::Heuristic; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 60.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 45.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 30.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 24.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_90, 90, 90, nullptr), 0); + + lr.vote = LayerVoteType::Min; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.vote = LayerVoteType::Max; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 90.0f; + lr.vote = LayerVoteType::Heuristic; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 60.0f; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 45.0f; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 30.0f; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 24.0f; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 0, 120, nullptr), 0); + lr.vote = LayerVoteType::Min; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.vote = LayerVoteType::Max; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 90.0f; + lr.vote = LayerVoteType::Heuristic; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 60.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 45.0f; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 30.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 24.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); +} + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_60_72_90) { + std::vector configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/true, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + + RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + RefreshRate expected72Config = {HWC_CONFIG_ID_72, VSYNC_72, HWC_GROUP_ID_0, "72fps", 70}; + RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + + auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; + auto& lr = layers[0]; + + lr.vote = LayerVoteType::Min; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.vote = LayerVoteType::Max; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 90.0f; + lr.vote = LayerVoteType::Heuristic; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 60.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 45.0f; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 30.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 24.0f; + EXPECT_EQ(expected72Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); +} + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_30_60_72_90_120) { + std::vector configs{ + {{HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30}, + {HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}, + {HWC_CONFIG_ID_120, HWC_GROUP_ID_0, VSYNC_120}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/true, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + + RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30}; + RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + RefreshRate expected72Config = {HWC_CONFIG_ID_72, VSYNC_72, HWC_GROUP_ID_0, "72fps", 70}; + RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + RefreshRate expected120Config = {HWC_CONFIG_ID_120, VSYNC_120, HWC_GROUP_ID_0, "120fps", 120}; + + auto layers = std::vector{LayerRequirement{.weight = 1.0f}, + LayerRequirement{.weight = 1.0f}}; + auto& lr1 = layers[0]; + auto& lr2 = layers[1]; + + lr1.desiredRefreshRate = 24.0f; + lr1.vote = LayerVoteType::Heuristic; + lr2.desiredRefreshRate = 60.0f; + lr2.vote = LayerVoteType::Heuristic; + EXPECT_EQ(expected120Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr1.desiredRefreshRate = 24.0f; + lr1.vote = LayerVoteType::Heuristic; + lr2.desiredRefreshRate = 48.0f; + lr2.vote = LayerVoteType::Heuristic; + EXPECT_EQ(expected72Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr1.desiredRefreshRate = 24.0f; + lr1.vote = LayerVoteType::Heuristic; + lr2.desiredRefreshRate = 48.0f; + lr2.vote = LayerVoteType::Heuristic; + EXPECT_EQ(expected72Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); +} + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_30_60) { + std::vector configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/true, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + + RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30}; + + auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; + auto& lr = layers[0]; + + lr.vote = LayerVoteType::Min; + EXPECT_EQ(expected30Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.vote = LayerVoteType::Max; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 90.0f; + lr.vote = LayerVoteType::Heuristic; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 60.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 45.0f; + EXPECT_EQ(expected30Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 30.0f; + EXPECT_EQ(expected30Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 24.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); +} + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_30_60_72_90) { + std::vector configs{ + {{HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30}, + {HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/true, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + + RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30}; + RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + RefreshRate expected72Config = {HWC_CONFIG_ID_72, VSYNC_72, HWC_GROUP_ID_0, "72fps", 70}; + RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + + auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; + auto& lr = layers[0]; + + lr.vote = LayerVoteType::Min; + EXPECT_EQ(expected30Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.vote = LayerVoteType::Max; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 90.0f; + lr.vote = LayerVoteType::Heuristic; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 60.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 45.0f; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 30.0f; + EXPECT_EQ(expected30Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 24.0f; + EXPECT_EQ(expected72Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); +} + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_PriorityTest) { + std::vector configs{ + {{HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30}, + {HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/true, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + + RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30}; + RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + + auto layers = std::vector{LayerRequirement{.weight = 1.0f}, + LayerRequirement{.weight = 1.0f}}; + auto& lr1 = layers[0]; + auto& lr2 = layers[1]; + + lr1.vote = LayerVoteType::Min; + lr2.vote = LayerVoteType::Max; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr1.vote = LayerVoteType::Min; + lr2.vote = LayerVoteType::Heuristic; + lr2.desiredRefreshRate = 24.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr1.vote = LayerVoteType::Min; + lr2.vote = LayerVoteType::Explicit; + lr2.desiredRefreshRate = 24.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr1.vote = LayerVoteType::Max; + lr2.vote = LayerVoteType::Heuristic; + lr2.desiredRefreshRate = 60.0f; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr1.vote = LayerVoteType::Max; + lr2.vote = LayerVoteType::Explicit; + lr2.desiredRefreshRate = 60.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr1.vote = LayerVoteType::Heuristic; + lr1.desiredRefreshRate = 15.0f; + lr2.vote = LayerVoteType::Heuristic; + lr2.desiredRefreshRate = 45.0f; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr1.vote = LayerVoteType::Heuristic; + lr1.desiredRefreshRate = 30.0f; + lr2.vote = LayerVoteType::Explicit; + lr2.desiredRefreshRate = 45.0f; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); +} + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_24FpsVideo) { + std::vector configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/true, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + + RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30}; + RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + + auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; + auto& lr = layers[0]; + + lr.vote = LayerVoteType::Explicit; + for (float fps = 23.0f; fps < 25.0f; fps += 0.1f) { + lr.desiredRefreshRate = fps; + const auto& refreshRate = refreshRateConfigs->getRefreshRateForContentV2(layers); + printf("%.2fHz chooses %s\n", fps, refreshRate.name.c_str()); + EXPECT_EQ(expected60Config, refreshRate); + } +} + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContent_Explicit) { + std::vector configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/true, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + + RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + + auto layers = std::vector{LayerRequirement{.weight = 1.0f}, + LayerRequirement{.weight = 1.0f}}; + auto& lr1 = layers[0]; + auto& lr2 = layers[1]; + + lr1.vote = LayerVoteType::Heuristic; + lr1.desiredRefreshRate = 60.0f; + lr2.vote = LayerVoteType::Explicit; + lr2.desiredRefreshRate = 90.0f; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(layers)); + + lr1.vote = LayerVoteType::Heuristic; + lr1.desiredRefreshRate = 90.0f; + lr2.vote = LayerVoteType::Explicit; + lr2.desiredRefreshRate = 60.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(layers)); +} + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_Explicit) { + std::vector configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/true, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + + RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + + auto layers = std::vector{LayerRequirement{.weight = 1.0f}, + LayerRequirement{.weight = 1.0f}}; + auto& lr1 = layers[0]; + auto& lr2 = layers[1]; + + lr1.vote = LayerVoteType::Heuristic; + lr1.desiredRefreshRate = 60.0f; + lr2.vote = LayerVoteType::Explicit; + lr2.desiredRefreshRate = 90.0f; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr1.vote = LayerVoteType::Heuristic; + lr1.desiredRefreshRate = 90.0f; + lr2.vote = LayerVoteType::Explicit; + lr2.desiredRefreshRate = 60.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); } TEST_F(RefreshRateConfigsTest, testInPolicy) { diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp index b1ecf4da6e..82a00ee734 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp @@ -76,7 +76,7 @@ SchedulerTest::SchedulerTest() { scheduler::RefreshRateConfigs>(/*refreshRateSwitching=*/false, configs, /*currentConfig=*/HwcConfigIndexType(0)); - mScheduler = std::make_unique(*mRefreshRateConfigs); + mScheduler = std::make_unique(*mRefreshRateConfigs, false); auto eventThread = std::make_unique(); mEventThread = eventThread.get(); diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h index a67c24c2d6..52da34b69a 100644 --- a/services/surfaceflinger/tests/unittests/TestableScheduler.h +++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h @@ -28,16 +28,25 @@ namespace android { class TestableScheduler : public Scheduler, private ISchedulerCallback { public: - explicit TestableScheduler(const scheduler::RefreshRateConfigs& configs) - : Scheduler([](bool) {}, configs, *this) { - mLayerHistory = std::make_unique(); + TestableScheduler(const scheduler::RefreshRateConfigs& configs, bool useContentDetectionV2) + : Scheduler([](bool) {}, configs, *this, useContentDetectionV2) { + if (mUseContentDetectionV2) { + mLayerHistory = std::make_unique(); + } else { + mLayerHistory = std::make_unique(); + } } TestableScheduler(std::unique_ptr primaryDispSync, std::unique_ptr eventControlThread, - const scheduler::RefreshRateConfigs& configs) - : Scheduler(std::move(primaryDispSync), std::move(eventControlThread), configs, *this) { - mLayerHistory = std::make_unique(); + const scheduler::RefreshRateConfigs& configs, bool useContentDetectionV2) + : Scheduler(std::move(primaryDispSync), std::move(eventControlThread), configs, *this, + useContentDetectionV2) { + if (mUseContentDetectionV2) { + mLayerHistory = std::make_unique(); + } else { + mLayerHistory = std::make_unique(); + } } // Used to inject mock event thread. @@ -46,7 +55,13 @@ public: } size_t layerHistorySize() const NO_THREAD_SAFETY_ANALYSIS { - return static_cast(mLayerHistory.get())->mLayerInfos.size(); + if (mUseContentDetectionV2) { + return static_cast(mLayerHistory.get()) + ->mLayerInfos.size(); + } else { + return static_cast(mLayerHistory.get()) + ->mLayerInfos.size(); + } } /* ------------------------------------------------------------------------ @@ -60,6 +75,9 @@ public: auto mutableLayerHistory() { return static_cast(mLayerHistory.get()); } + auto mutableLayerHistoryV2() { + return static_cast(mLayerHistory.get()); + } ~TestableScheduler() { // All these pointer and container clears help ensure that GMock does diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 8ddb872582..2491533ea4 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -198,7 +198,8 @@ public: void setupScheduler(std::unique_ptr primaryDispSync, std::unique_ptr eventControlThread, std::unique_ptr appEventThread, - std::unique_ptr sfEventThread) { + std::unique_ptr sfEventThread, + bool useContentDetectionV2 = false) { std::vector configs{ {{HwcConfigIndexType(0), HwcConfigGroupType(0), 16666667}}}; mFlinger->mRefreshRateConfigs = std::make_unique< @@ -213,7 +214,7 @@ public: mScheduler = new TestableScheduler(std::move(primaryDispSync), std::move(eventControlThread), - *mFlinger->mRefreshRateConfigs); + *mFlinger->mRefreshRateConfigs, useContentDetectionV2); mFlinger->mAppConnectionHandle = mScheduler->createConnection(std::move(appEventThread)); mFlinger->mSfConnectionHandle = mScheduler->createConnection(std::move(sfEventThread)); @@ -443,7 +444,7 @@ public: static constexpr int32_t DEFAULT_REFRESH_RATE = 16'666'666; static constexpr int32_t DEFAULT_CONFIG_GROUP = 7; static constexpr int32_t DEFAULT_DPI = 320; - static constexpr int32_t DEFAULT_ACTIVE_CONFIG = 0; + static constexpr hwc2_config_t DEFAULT_ACTIVE_CONFIG = 0; static constexpr int32_t DEFAULT_POWER_MODE = 2; FakeHwcDisplayInjector(DisplayId displayId, HWC2::DisplayType hwcDisplayType, @@ -465,7 +466,7 @@ public: return *this; } - auto& setRefreshRate(uint32_t refreshRate) { + auto& setRefreshRate(int32_t refreshRate) { mRefreshRate = refreshRate; return *this; } @@ -480,7 +481,7 @@ public: return *this; } - auto& setActiveConfig(int32_t config) { + auto& setActiveConfig(hwc2_config_t config) { mActiveConfig = config; return *this; } @@ -513,7 +514,7 @@ public: config.setDpiX(mDpiX); config.setDpiY(mDpiY); config.setConfigGroup(mConfigGroup); - display->mutableConfigs().emplace(mActiveConfig, config.build()); + display->mutableConfigs().emplace(static_cast(mActiveConfig), config.build()); display->mutableIsConnected() = true; display->setPowerMode(static_cast(mPowerMode)); @@ -534,11 +535,11 @@ public: hwc2_display_t mHwcDisplayId = DEFAULT_HWC_DISPLAY_ID; int32_t mWidth = DEFAULT_WIDTH; int32_t mHeight = DEFAULT_HEIGHT; - uint32_t mRefreshRate = DEFAULT_REFRESH_RATE; + int32_t mRefreshRate = DEFAULT_REFRESH_RATE; int32_t mDpiX = DEFAULT_DPI; int32_t mConfigGroup = DEFAULT_CONFIG_GROUP; int32_t mDpiY = DEFAULT_DPI; - int32_t mActiveConfig = DEFAULT_ACTIVE_CONFIG; + hwc2_config_t mActiveConfig = DEFAULT_ACTIVE_CONFIG; int32_t mPowerMode = DEFAULT_POWER_MODE; const std::unordered_set* mCapabilities = nullptr; }; diff --git a/services/surfaceflinger/tests/unittests/mock/MockLayer.h b/services/surfaceflinger/tests/unittests/mock/MockLayer.h index 1fd0e617c2..494e73dda9 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockLayer.h +++ b/services/surfaceflinger/tests/unittests/mock/MockLayer.h @@ -31,6 +31,7 @@ public: MOCK_METHOD0(getFrameSelectionPriority, int32_t()); MOCK_CONST_METHOD0(isVisible, bool()); MOCK_METHOD0(createClone, sp()); + MOCK_CONST_METHOD0(getFrameRate, std::optional()); }; } // namespace android::mock -- cgit v1.2.3-59-g8ed1b From bf78464dab9528c2c101843c74e51e7bcb76288a Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Wed, 29 Jan 2020 07:25:23 -0800 Subject: Adding frame event history updates to BLAST Bug: 141939081 Test: build, boot, SurfaceFlinger_test Change-Id: Ic8e815177389150aac34042026b7bac30141ba9e --- services/surfaceflinger/BufferStateLayer.cpp | 38 +++++++++++++++++++++++--- services/surfaceflinger/BufferStateLayer.h | 7 +++-- services/surfaceflinger/Layer.h | 4 +-- services/surfaceflinger/RefreshRateOverlay.cpp | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 3 +- 5 files changed, 44 insertions(+), 10 deletions(-) (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 278ad52927..ed18901c54 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -98,6 +98,8 @@ void BufferStateLayer::onLayerDisplayed(const sp& releaseFence) { } } + mPreviousReleaseFence = releaseFence; + // Prevent tracing the same release multiple times. if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) { mFlinger->mFrameTracer->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber, @@ -111,7 +113,7 @@ void BufferStateLayer::setTransformHint(uint32_t orientation) const { mTransformHint = orientation; } -void BufferStateLayer::releasePendingBuffer(nsecs_t /*dequeueReadyTime*/) { +void BufferStateLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { for (const auto& handle : mDrawingState.callbackHandles) { handle->transformHint = mTransformHint; } @@ -120,6 +122,16 @@ void BufferStateLayer::releasePendingBuffer(nsecs_t /*dequeueReadyTime*/) { mDrawingState.callbackHandles); mDrawingState.callbackHandles = {}; + + const sp& releaseFence(mPreviousReleaseFence); + std::shared_ptr releaseFenceTime = std::make_shared(releaseFence); + { + Mutex::Autolock lock(mFrameEventHistoryMutex); + if (mPreviousFrameNumber != 0) { + mFrameEventHistory.addRelease(mPreviousFrameNumber, dequeueReadyTime, + std::move(releaseFenceTime)); + } + } } bool BufferStateLayer::shouldPresentNow(nsecs_t /*expectedPresentTime*/) const { @@ -233,8 +245,21 @@ bool BufferStateLayer::setFrame(const Rect& frame) { return true; } -bool BufferStateLayer::setBuffer(const sp& buffer, nsecs_t postTime, - nsecs_t desiredPresentTime, const client_cache_t& clientCacheId) { +bool BufferStateLayer::updateFrameEventHistory(const sp& acquireFence, nsecs_t postedTime, + nsecs_t desiredPresentTime) { + Mutex::Autolock lock(mFrameEventHistoryMutex); + mAcquireTimeline.updateSignalTimes(); + std::shared_ptr acquireFenceTime = + std::make_shared((acquireFence ? acquireFence : Fence::NO_FENCE)); + NewFrameEventsEntry newTimestamps = {mCurrentState.frameNumber, postedTime, desiredPresentTime, + acquireFenceTime}; + mFrameEventHistory.addQueue(newTimestamps); + return true; +} + +bool BufferStateLayer::setBuffer(const sp& buffer, const sp& acquireFence, + nsecs_t postTime, nsecs_t desiredPresentTime, + const client_cache_t& clientCacheId) { if (mCurrentState.buffer) { mReleasePreviousBuffer = true; } @@ -257,6 +282,7 @@ bool BufferStateLayer::setBuffer(const sp& buffer, nsecs_t postTi mFlinger->mScheduler->recordLayerHistory(this, desiredPresentTime <= 0 ? 0 : desiredPresentTime); + updateFrameEventHistory(acquireFence, postTime, desiredPresentTime); return true; } @@ -553,10 +579,14 @@ status_t BufferStateLayer::updateActiveBuffer() { return NO_ERROR; } -status_t BufferStateLayer::updateFrameNumber(nsecs_t /*latchTime*/) { +status_t BufferStateLayer::updateFrameNumber(nsecs_t latchTime) { // TODO(marissaw): support frame history events mPreviousFrameNumber = mCurrentFrameNumber; mCurrentFrameNumber = mDrawingState.frameNumber; + { + Mutex::Autolock lock(mFrameEventHistoryMutex); + mFrameEventHistory.addLatch(mCurrentFrameNumber, latchTime); + } return NO_ERROR; } diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 94272833c2..03d968436c 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -68,8 +68,8 @@ public: bool setTransformToDisplayInverse(bool transformToDisplayInverse) override; bool setCrop(const Rect& crop) override; bool setFrame(const Rect& frame) override; - bool setBuffer(const sp& buffer, nsecs_t postTime, nsecs_t desiredPresentTime, - const client_cache_t& clientCacheId) override; + bool setBuffer(const sp& buffer, const sp& acquireFence, nsecs_t postTime, + nsecs_t desiredPresentTime, const client_cache_t& clientCacheId) override; bool setAcquireFence(const sp& fence) override; bool setDataspace(ui::Dataspace dataspace) override; bool setHdrMetadata(const HdrMetadata& hdrMetadata) override; @@ -109,6 +109,9 @@ protected: void gatherBufferInfo() override; private: + bool updateFrameEventHistory(const sp& acquireFence, nsecs_t postedTime, + nsecs_t requestedPresentTime); + uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override; bool getAutoRefresh() const override; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index da3df8fd8d..059104f253 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -329,8 +329,8 @@ public: virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/) { return false; }; virtual bool setCrop(const Rect& /*crop*/) { return false; }; virtual bool setFrame(const Rect& /*frame*/) { return false; }; - virtual bool setBuffer(const sp& /*buffer*/, nsecs_t /*postTime*/, - nsecs_t /*desiredPresentTime*/, + virtual bool setBuffer(const sp& /*buffer*/, const sp& /*acquireFence*/, + nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/, const client_cache_t& /*clientCacheId*/) { return false; }; diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index d3d9d3aec7..47ee55fd6c 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -208,7 +208,7 @@ void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { const int32_t buttom = top + display->getHeight() / 32; auto buffer = mBufferCache[refreshRate.fps]; - mLayer->setBuffer(buffer, 0, 0, {}); + mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}); mLayer->setFrame(Rect(left, top, right, buttom)); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e7c2dbc324..899ae02c29 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3570,7 +3570,8 @@ uint32_t SurfaceFlinger::setClientStateLocked( buffer = s.buffer; } if (buffer) { - if (layer->setBuffer(buffer, postTime, desiredPresentTime, s.cachedBuffer)) { + if (layer->setBuffer(buffer, s.acquireFence, postTime, desiredPresentTime, + s.cachedBuffer)) { flags |= eTraversalNeeded; } } -- cgit v1.2.3-59-g8ed1b From 71c437dcd8b05244a171d477e4dde5ac20be9c4d Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Fri, 31 Jan 2020 15:56:57 -0800 Subject: SurfaceFlinger: add support for FrameRateCompatibilityType Bug: 147516364 Test: adb shell /data/nativetest64/SurfaceFlinger_test/SurfaceFlinger_test --gtest_filter='SetFrameRateTest.*' Test: adb shell /data/nativetest64/libsurfaceflinger_unittest/libsurfaceflinger_unittest --gtest_filter=*RefreshRateConfigs* Test: adb shell /data/nativetest64/libsurfaceflinger_unittest/libsurfaceflinger_unittest --gtest_filter=*LayerHistory* Change-Id: I49272804e25f04e1d7a148a0008551cbc5428011 --- services/surfaceflinger/BufferQueueLayer.cpp | 15 ++-- services/surfaceflinger/BufferQueueLayer.h | 4 +- services/surfaceflinger/Layer.cpp | 10 +-- services/surfaceflinger/Layer.h | 35 ++++++++- services/surfaceflinger/RefreshRateOverlay.cpp | 2 +- services/surfaceflinger/Scheduler/LayerHistory.cpp | 25 ++++-- .../surfaceflinger/Scheduler/LayerHistoryV2.cpp | 26 +++++-- .../Scheduler/RefreshRateConfigs.cpp | 43 +++++++---- .../surfaceflinger/Scheduler/RefreshRateConfigs.h | 13 ++-- services/surfaceflinger/Scheduler/Scheduler.cpp | 6 +- services/surfaceflinger/SurfaceFlinger.cpp | 4 +- .../tests/unittests/LayerHistoryTest.cpp | 10 +-- .../tests/unittests/LayerHistoryTestV2.cpp | 56 +++++++++++--- .../tests/unittests/RefreshRateConfigsTest.cpp | 89 +++++++++++++++++++--- .../tests/unittests/mock/MockLayer.h | 2 +- 15 files changed, 253 insertions(+), 87 deletions(-) (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 6423893841..61386f4ff0 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -125,21 +125,16 @@ bool BufferQueueLayer::shouldPresentNow(nsecs_t expectedPresentTime) const { return isDue || !isPlausible; } -bool BufferQueueLayer::setFrameRate(float frameRate) { +bool BufferQueueLayer::setFrameRate(FrameRate frameRate) { float oldFrameRate = 0.f; status_t result = mConsumer->getFrameRate(&oldFrameRate); - bool frameRateChanged = result < 0 || frameRate != oldFrameRate; - mConsumer->setFrameRate(frameRate); + bool frameRateChanged = result < 0 || frameRate.rate != oldFrameRate; + mConsumer->setFrameRate(frameRate.rate); return frameRateChanged; } -std::optional BufferQueueLayer::getFrameRate() const { - const auto frameRate = mLatchedFrameRate.load(); - if (frameRate > 0.f || frameRate == FRAME_RATE_NO_VOTE) { - return frameRate; - } - - return {}; +Layer::FrameRate BufferQueueLayer::getFrameRate() const { + return FrameRate(mLatchedFrameRate, Layer::FrameRateCompatibility::Default); } // ----------------------------------------------------------------------- diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 2bd1e3d6cc..598bc6b670 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -56,8 +56,8 @@ public: bool shouldPresentNow(nsecs_t expectedPresentTime) const override; - bool setFrameRate(float frameRate) override; - std::optional getFrameRate() const override; + bool setFrameRate(FrameRate frameRate) override; + FrameRate getFrameRate() const override; // ----------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index cedab59b23..cf1e8b0256 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -117,7 +117,6 @@ Layer::Layer(const LayerCreationArgs& args) mCurrentState.frameRateSelectionPriority = PRIORITY_UNSET; mCurrentState.metadata = args.metadata; mCurrentState.shadowRadius = 0.f; - mCurrentState.frameRate = 0.f; // drawing state & current state are identical mDrawingState = mCurrentState; @@ -1245,7 +1244,7 @@ bool Layer::setShadowRadius(float shadowRadius) { return true; } -bool Layer::setFrameRate(float frameRate) { +bool Layer::setFrameRate(FrameRate frameRate) { if (mCurrentState.frameRate == frameRate) { return false; } @@ -1257,11 +1256,8 @@ bool Layer::setFrameRate(float frameRate) { return true; } -std::optional Layer::getFrameRate() const { - const auto frameRate = getDrawingState().frameRate; - if (frameRate > 0.f || frameRate == FRAME_RATE_NO_VOTE) return frameRate; - - return {}; +Layer::FrameRate Layer::getFrameRate() const { + return getDrawingState().frameRate; } void Layer::deferTransactionUntil_legacy(const sp& barrierLayer, uint64_t frameNumber) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index da3df8fd8d..c20e04a7ad 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -136,6 +136,34 @@ public: float radius = 0.0f; }; + // FrameRateCompatibility specifies how we should interpret the frame rate associated with + // the layer. + enum class FrameRateCompatibility { + Default, // Layer didn't specify any specific handling strategy + + ExactOrMultiple, // Layer needs the exact frame rate (or a multiple of it) to present the + // content properly. Any other value will result in a pull down. + + NoVote, // Layer doesn't have any requirements for the refresh rate and + // should not be considered when the display refresh rate is determined. + }; + + // Encapsulates the frame rate and compatibility of the layer. This information will be used + // when the display refresh rate is determined. + struct FrameRate { + float rate; + FrameRateCompatibility type; + + FrameRate() : rate(0), type(FrameRateCompatibility::Default) {} + FrameRate(float rate, FrameRateCompatibility type) : rate(rate), type(type) {} + + bool operator==(const FrameRate& other) const { + return rate == other.rate && type == other.type; + } + + bool operator!=(const FrameRate& other) const { return !(*this == other); } + }; + struct State { Geometry active_legacy; Geometry requested_legacy; @@ -227,7 +255,7 @@ public: // Priority of the layer assigned by Window Manager. int32_t frameRateSelectionPriority; - float frameRate; + FrameRate frameRate; }; explicit Layer(const LayerCreationArgs& args); @@ -754,9 +782,8 @@ public: */ Rect getCroppedBufferSize(const Layer::State& s) const; - constexpr static auto FRAME_RATE_NO_VOTE = -1.0f; - virtual bool setFrameRate(float frameRate); - virtual std::optional getFrameRate() const; + virtual bool setFrameRate(FrameRate frameRate); + virtual FrameRate getFrameRate() const; protected: // constant diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index d3d9d3aec7..59c2bbd42f 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -155,7 +155,7 @@ bool RefreshRateOverlay::createLayer() { Mutex::Autolock _l(mFlinger.mStateLock); mLayer = mClient->getLayerUser(mIBinder); - mLayer->setFrameRate(Layer::FRAME_RATE_NO_VOTE); + mLayer->setFrameRate(Layer::FrameRate(0, Layer::FrameRateCompatibility::NoVote)); // setting Layer's Z requires resorting layersSortedByZ ssize_t idx = mFlinger.mCurrentState.layersSortedByZ.indexOf(mLayer); diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index b976523460..9aada11473 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -39,7 +39,7 @@ namespace android::scheduler::impl { namespace { bool isLayerActive(const Layer& layer, const LayerInfo& info, nsecs_t threshold) { - if (layer.getFrameRate().has_value()) { + if (layer.getFrameRate().rate > 0) { return layer.isVisible(); } return layer.isVisible() && info.getLastUpdatedTime() >= threshold; @@ -126,18 +126,27 @@ LayerHistory::Summary LayerHistory::summarize(nsecs_t now) { // Only use the layer if the reference still exists. if (layer || CC_UNLIKELY(mTraceEnabled)) { // Check if frame rate was set on layer. - auto frameRate = layer->getFrameRate(); - if (frameRate.has_value() && frameRate.value() > 0.f) { - summary.push_back( - {layer->getName(), LayerVoteType::Explicit, *frameRate, /* weight */ 1.0f}); + const auto frameRate = layer->getFrameRate(); + if (frameRate.rate > 0.f) { + const auto voteType = [&]() { + switch (frameRate.type) { + case Layer::FrameRateCompatibility::Default: + return LayerVoteType::ExplicitDefault; + case Layer::FrameRateCompatibility::ExactOrMultiple: + return LayerVoteType::ExplicitExactOrMultiple; + case Layer::FrameRateCompatibility::NoVote: + return LayerVoteType::NoVote; + } + }(); + summary.push_back({layer->getName(), voteType, frameRate.rate, /* weight */ 1.0f}); } else if (recent) { - frameRate = info->getRefreshRate(now); - summary.push_back({layer->getName(), LayerVoteType::Heuristic, *frameRate, + summary.push_back({layer->getName(), LayerVoteType::Heuristic, + info->getRefreshRate(now), /* weight */ 1.0f}); } if (CC_UNLIKELY(mTraceEnabled)) { - trace(weakLayer, round(*frameRate)); + trace(weakLayer, round(frameRate.rate)); } } } diff --git a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp index a6d2c74c87..ce085f4a1d 100644 --- a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp @@ -40,7 +40,7 @@ namespace android::scheduler::impl { namespace { bool isLayerActive(const Layer& layer, const LayerInfoV2& info, nsecs_t threshold) { - if (layer.getFrameRate().has_value()) { + if (layer.getFrameRate().rate > 0) { return layer.isVisible(); } return layer.isVisible() && info.getLastUpdatedTime() >= threshold; @@ -63,13 +63,17 @@ void trace(const wp& weak, LayerHistory::LayerVoteType type, int fps) { const auto& name = layer->getName(); const auto noVoteTag = "LFPS NoVote " + name; const auto heuristicVoteTag = "LFPS Heuristic " + name; - const auto explicitVoteTag = "LFPS Explicit " + name; + const auto explicitDefaultVoteTag = "LFPS ExplicitDefault" + name; + const auto explicitExactOrMultipleVoteTag = "LFPS ExplicitExactOrMultiple" + name; const auto minVoteTag = "LFPS Min " + name; const auto maxVoteTag = "LFPS Max " + name; ATRACE_INT(noVoteTag.c_str(), type == LayerHistory::LayerVoteType::NoVote ? 1 : 0); ATRACE_INT(heuristicVoteTag.c_str(), type == LayerHistory::LayerVoteType::Heuristic ? fps : 0); - ATRACE_INT(explicitVoteTag.c_str(), type == LayerHistory::LayerVoteType::Explicit ? fps : 0); + ATRACE_INT(explicitDefaultVoteTag.c_str(), + type == LayerHistory::LayerVoteType::ExplicitDefault ? fps : 0); + ATRACE_INT(explicitExactOrMultipleVoteTag.c_str(), + type == LayerHistory::LayerVoteType::ExplicitExactOrMultiple ? fps : 0); ATRACE_INT(minVoteTag.c_str(), type == LayerHistory::LayerVoteType::Min ? 1 : 0); ATRACE_INT(maxVoteTag.c_str(), type == LayerHistory::LayerVoteType::Max ? 1 : 0); @@ -160,12 +164,18 @@ void LayerHistoryV2::partitionLayers(nsecs_t now) { i++; // Set layer vote if set const auto frameRate = layer->getFrameRate(); - if (frameRate.has_value()) { - if (*frameRate == Layer::FRAME_RATE_NO_VOTE) { - info->setLayerVote(LayerVoteType::NoVote, 0.f); - } else { - info->setLayerVote(LayerVoteType::Explicit, *frameRate); + const auto voteType = [&]() { + switch (frameRate.type) { + case Layer::FrameRateCompatibility::Default: + return LayerVoteType::ExplicitDefault; + case Layer::FrameRateCompatibility::ExactOrMultiple: + return LayerVoteType::ExplicitExactOrMultiple; + case Layer::FrameRateCompatibility::NoVote: + return LayerVoteType::NoVote; } + }(); + if (frameRate.rate > 0 || voteType == LayerVoteType::NoVote) { + info->setLayerVote(voteType, frameRate.rate); } else { info->resetLayerVote(); } diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index d2af9126b3..c73e825d51 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -37,7 +37,8 @@ const RefreshRate& RefreshRateConfigs::getRefreshRateForContent( int explicitContentFramerate = 0; for (const auto& layer : layers) { const auto desiredRefreshRateRound = round(layer.desiredRefreshRate); - if (layer.vote == LayerVoteType::Explicit) { + if (layer.vote == LayerVoteType::ExplicitDefault || + layer.vote == LayerVoteType::ExplicitExactOrMultiple) { if (desiredRefreshRateRound > explicitContentFramerate) { explicitContentFramerate = desiredRefreshRateRound; } @@ -94,7 +95,8 @@ const RefreshRate& RefreshRateConfigs::getRefreshRateForContentV2( int noVoteLayers = 0; int minVoteLayers = 0; int maxVoteLayers = 0; - int explicitVoteLayers = 0; + int explicitDefaultVoteLayers = 0; + int explicitExactOrMultipleVoteLayers = 0; for (const auto& layer : layers) { if (layer.vote == LayerVoteType::NoVote) noVoteLayers++; @@ -102,8 +104,10 @@ const RefreshRate& RefreshRateConfigs::getRefreshRateForContentV2( minVoteLayers++; else if (layer.vote == LayerVoteType::Max) maxVoteLayers++; - else if (layer.vote == LayerVoteType::Explicit) - explicitVoteLayers++; + else if (layer.vote == LayerVoteType::ExplicitDefault) + explicitDefaultVoteLayers++; + else if (layer.vote == LayerVoteType::ExplicitExactOrMultiple) + explicitExactOrMultipleVoteLayers++; } // Only if all layers want Min we should return Min @@ -112,7 +116,7 @@ const RefreshRate& RefreshRateConfigs::getRefreshRateForContentV2( } // If we have some Max layers and no Explicit we should return Max - if (maxVoteLayers > 0 && explicitVoteLayers == 0) { + if (maxVoteLayers > 0 && explicitDefaultVoteLayers + explicitExactOrMultipleVoteLayers == 0) { return *mAvailableRefreshRates.back(); } @@ -131,9 +135,22 @@ const RefreshRate& RefreshRateConfigs::getRefreshRateForContentV2( continue; } - // If we have Explicit layers, ignore the Hueristic ones - if (explicitVoteLayers > 0 && layer.vote == LayerVoteType::Heuristic) { - continue; + // Adjust the weight in case we have explicit layers. The priority is: + // - ExplicitExactOrMultiple + // - ExplicitDefault + // - Heuristic + auto weight = layer.weight; + if (explicitExactOrMultipleVoteLayers + explicitDefaultVoteLayers > 0) { + if (layer.vote == LayerVoteType::Heuristic) { + weight /= 2.f; + } + } + + if (explicitExactOrMultipleVoteLayers > 0) { + if (layer.vote == LayerVoteType::Heuristic || + layer.vote == LayerVoteType::ExplicitDefault) { + weight /= 2.f; + } } for (auto& [refreshRate, overallScore] : scores) { @@ -152,10 +169,10 @@ const RefreshRate& RefreshRateConfigs::getRefreshRateForContentV2( static constexpr size_t MAX_FRAMES_TO_FIT = 10; // Stop calculating when score < 0.1 if (displayFramesRem == 0) { // Layer desired refresh rate matches the display rate. - layerScore = layer.weight * 1.0f; + layerScore = weight * 1.0f; } else if (displayFramesQuot == 0) { // Layer desired refresh rate is higher the display rate. - layerScore = layer.weight * + layerScore = weight * (static_cast(layerPeriod) / static_cast(displayPeriod)) * (1.0f / (MAX_FRAMES_TO_FIT + 1)); } else { @@ -168,11 +185,11 @@ const RefreshRate& RefreshRateConfigs::getRefreshRateForContentV2( iter++; } - layerScore = layer.weight * (1.0f / iter); + layerScore = weight * (1.0f / iter); } - ALOGV("%s (weight %.2f) %.2fHz gives %s score of %.2f", layer.name.c_str(), - layer.weight, 1e9f / layerPeriod, refreshRate->name.c_str(), layerScore); + ALOGV("%s (weight %.2f) %.2fHz gives %s score of %.2f", layer.name.c_str(), weight, + 1e9f / layerPeriod, refreshRate->name.c_str(), layerScore); overallScore += layerScore; } } diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index c762efddd6..fc959597a3 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -96,11 +96,14 @@ public: // Describes the different options the layer voted for refresh rate enum class LayerVoteType { - NoVote, // Doesn't care about the refresh rate - Min, // Minimal refresh rate available - Max, // Maximal refresh rate available - Heuristic, // Specific refresh rate that was calculated by platform using a heuristic - Explicit, // Specific refresh rate that was provided by the app + NoVote, // Doesn't care about the refresh rate + Min, // Minimal refresh rate available + Max, // Maximal refresh rate available + Heuristic, // Specific refresh rate that was calculated by platform using a heuristic + ExplicitDefault, // Specific refresh rate that was provided by the app with Default + // compatibility + ExplicitExactOrMultiple // Specific refresh rate that was provided by the app with + // ExactOrMultiple compatibility }; // Captures the layer requirements for a refresh rate. This will be used to determine the diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 258ce0a7e2..52fb6f3036 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -408,7 +408,8 @@ void Scheduler::registerLayer(Layer* layer) { "SurfaceView - " "com.google.android.youtube/" "com.google.android.apps.youtube.app.WatchWhileActivity#0") { - layer->setFrameRate(vote); + layer->setFrameRate( + Layer::FrameRate(vote, Layer::FrameRateCompatibility::ExactOrMultiple)); } } } @@ -562,7 +563,8 @@ void Scheduler::handleTimerStateChanged(T* currentState, T newState, bool eventO bool Scheduler::layerHistoryHasClientSpecifiedFrameRate() { for (const auto& layer : mFeatures.contentRequirements) { - if (layer.vote == scheduler::RefreshRateConfigs::LayerVoteType::Explicit) { + if (layer.vote == scheduler::RefreshRateConfigs::LayerVoteType::ExplicitDefault || + layer.vote == scheduler::RefreshRateConfigs::LayerVoteType::ExplicitExactOrMultiple) { return true; } } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index a066d4b8ef..61e5e66475 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3548,7 +3548,9 @@ uint32_t SurfaceFlinger::setClientStateLocked( } } if (what & layer_state_t::eFrameRateChanged) { - if (layer->setFrameRate(s.frameRate)) flags |= eTraversalNeeded; + if (layer->setFrameRate( + Layer::FrameRate(s.frameRate, Layer::FrameRateCompatibility::Default))) + flags |= eTraversalNeeded; } // This has to happen after we reparent children because when we reparent to null we remove // child layers from current state and remove its relative z. If the children are reparented in diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index 68b7a74ec4..18e9941385 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -84,7 +84,7 @@ TEST_F(LayerHistoryTest, oneLayer) { const auto layer = createLayer(); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*layer, getFrameSelectionPriority()).WillRepeatedly(Return(1)); - EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(Layer::FrameRate())); EXPECT_EQ(1, layerCount()); EXPECT_EQ(0, activeLayerCount()); @@ -113,7 +113,7 @@ TEST_F(LayerHistoryTest, explicitTimestamp) { const auto layer = createLayer(); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*layer, getFrameSelectionPriority()).WillRepeatedly(Return(1)); - EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(Layer::FrameRate())); EXPECT_EQ(1, layerCount()); EXPECT_EQ(0, activeLayerCount()); @@ -137,15 +137,15 @@ TEST_F(LayerHistoryTest, multipleLayers) { EXPECT_CALL(*layer1, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*layer1, getFrameSelectionPriority()).WillRepeatedly(Return(1)); - EXPECT_CALL(*layer1, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + EXPECT_CALL(*layer1, getFrameRate()).WillRepeatedly(Return(Layer::FrameRate())); EXPECT_CALL(*layer2, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*layer2, getFrameSelectionPriority()).WillRepeatedly(Return(1)); - EXPECT_CALL(*layer2, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + EXPECT_CALL(*layer2, getFrameRate()).WillRepeatedly(Return(Layer::FrameRate())); EXPECT_CALL(*layer3, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*layer3, getFrameSelectionPriority()).WillRepeatedly(Return(1)); - EXPECT_CALL(*layer3, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + EXPECT_CALL(*layer3, getFrameRate()).WillRepeatedly(Return(Layer::FrameRate())); nsecs_t time = mTime; EXPECT_EQ(3, layerCount()); diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp index a5dcf11e22..959c256262 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp @@ -90,7 +90,7 @@ namespace { TEST_F(LayerHistoryTestV2, oneLayer) { const auto layer = createLayer(); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(Layer::FrameRate())); EXPECT_EQ(1, layerCount()); EXPECT_EQ(0, activeLayerCount()); @@ -121,7 +121,7 @@ TEST_F(LayerHistoryTestV2, oneLayer) { TEST_F(LayerHistoryTestV2, oneInvisibleLayer) { const auto layer = createLayer(); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(Layer::FrameRate())); EXPECT_EQ(1, layerCount()); EXPECT_EQ(0, activeLayerCount()); @@ -145,7 +145,7 @@ TEST_F(LayerHistoryTestV2, oneInvisibleLayer) { TEST_F(LayerHistoryTestV2, explicitTimestamp) { const auto layer = createLayer(); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(Layer::FrameRate())); EXPECT_EQ(1, layerCount()); EXPECT_EQ(0, activeLayerCount()); @@ -166,7 +166,7 @@ TEST_F(LayerHistoryTestV2, explicitTimestamp) { TEST_F(LayerHistoryTestV2, oneLayerNoVote) { const auto layer = createLayer(); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(Layer::FrameRate())); setLayerInfoVote(layer.get(), LayerHistory::LayerVoteType::NoVote); @@ -193,7 +193,7 @@ TEST_F(LayerHistoryTestV2, oneLayerNoVote) { TEST_F(LayerHistoryTestV2, oneLayerMinVote) { const auto layer = createLayer(); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(Layer::FrameRate())); setLayerInfoVote(layer.get(), LayerHistory::LayerVoteType::Min); @@ -221,7 +221,7 @@ TEST_F(LayerHistoryTestV2, oneLayerMinVote) { TEST_F(LayerHistoryTestV2, oneLayerMaxVote) { const auto layer = createLayer(); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(Layer::FrameRate())); setLayerInfoVote(layer.get(), LayerHistory::LayerVoteType::Max); @@ -249,7 +249,9 @@ TEST_F(LayerHistoryTestV2, oneLayerMaxVote) { TEST_F(LayerHistoryTestV2, oneLayerExplicitVote) { auto layer = createLayer(); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(73.4f)); + EXPECT_CALL(*layer, getFrameRate()) + .WillRepeatedly( + Return(Layer::FrameRate(73.4f, Layer::FrameRateCompatibility::Default))); EXPECT_EQ(1, layerCount()); EXPECT_EQ(0, activeLayerCount()); @@ -261,7 +263,39 @@ TEST_F(LayerHistoryTestV2, oneLayerExplicitVote) { } ASSERT_EQ(1, history().summarize(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Explicit, history().summarize(time)[0].vote); + EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, history().summarize(time)[0].vote); + EXPECT_FLOAT_EQ(73.4f, history().summarize(time)[0].desiredRefreshRate); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer became inactive + setLayerInfoVote(layer.get(), LayerHistory::LayerVoteType::Heuristic); + time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); + ASSERT_TRUE(history().summarize(time).empty()); + // TODO: activeLayerCount() should be 0 but it is 1 since getFrameRate() returns a value > 0 + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); +} + +TEST_F(LayerHistoryTestV2, oneLayerExplicitExactVote) { + auto layer = createLayer(); + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameRate()) + .WillRepeatedly(Return( + Layer::FrameRate(73.4f, Layer::FrameRateCompatibility::ExactOrMultiple))); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + nsecs_t time = systemTime(); + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer.get(), time, time); + time += HI_FPS_PERIOD; + } + + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, + history().summarize(time)[0].vote); EXPECT_FLOAT_EQ(73.4f, history().summarize(time)[0].desiredRefreshRate); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); @@ -281,13 +315,13 @@ TEST_F(LayerHistoryTestV2, multipleLayers) { auto layer3 = createLayer(); EXPECT_CALL(*layer1, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer1, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + EXPECT_CALL(*layer1, getFrameRate()).WillRepeatedly(Return(Layer::FrameRate())); EXPECT_CALL(*layer2, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer2, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + EXPECT_CALL(*layer2, getFrameRate()).WillRepeatedly(Return(Layer::FrameRate())); EXPECT_CALL(*layer3, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer3, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + EXPECT_CALL(*layer3, getFrameRate()).WillRepeatedly(Return(Layer::FrameRate())); nsecs_t time = systemTime(); diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp index cd9f2b1cd6..841c624a3f 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -432,6 +432,77 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_30_60 EXPECT_EQ(expected72Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); } +TEST_F(RefreshRateConfigsTest, + twoDeviceConfigs_getRefreshRateForContentV2_30_60_90_120_DifferentTypes) { + std::vector configs{ + {{HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30}, + {HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}, + {HWC_CONFIG_ID_120, HWC_GROUP_ID_0, VSYNC_120}}}; + auto refreshRateConfigs = + std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); + + RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30}; + RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + RefreshRate expected72Config = {HWC_CONFIG_ID_72, VSYNC_72, HWC_GROUP_ID_0, "72fps", 72}; + RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + RefreshRate expected120Config = {HWC_CONFIG_ID_120, VSYNC_120, HWC_GROUP_ID_0, "120fps", 120}; + + auto layers = std::vector{LayerRequirement{.weight = 1.0f}, + LayerRequirement{.weight = 1.0f}}; + auto& lr1 = layers[0]; + auto& lr2 = layers[1]; + + lr1.desiredRefreshRate = 24.0f; + lr1.vote = LayerVoteType::ExplicitDefault; + lr2.desiredRefreshRate = 60.0f; + lr2.vote = LayerVoteType::Heuristic; + EXPECT_EQ(expected120Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr1.desiredRefreshRate = 24.0f; + lr1.vote = LayerVoteType::ExplicitExactOrMultiple; + lr2.desiredRefreshRate = 60.0f; + lr2.vote = LayerVoteType::Heuristic; + EXPECT_EQ(expected120Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr1.desiredRefreshRate = 24.0f; + lr1.vote = LayerVoteType::ExplicitExactOrMultiple; + lr2.desiredRefreshRate = 60.0f; + lr2.vote = LayerVoteType::ExplicitDefault; + EXPECT_EQ(expected120Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr1.desiredRefreshRate = 24.0f; + lr1.vote = LayerVoteType::ExplicitExactOrMultiple; + lr2.desiredRefreshRate = 90.0f; + lr2.vote = LayerVoteType::Heuristic; + EXPECT_EQ(expected120Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr1.desiredRefreshRate = 24.0f; + lr1.vote = LayerVoteType::ExplicitDefault; + lr2.desiredRefreshRate = 90.0f; + lr2.vote = LayerVoteType::Heuristic; + EXPECT_EQ(expected120Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr1.desiredRefreshRate = 24.0f; + lr1.vote = LayerVoteType::Heuristic; + lr2.desiredRefreshRate = 90.0f; + lr2.vote = LayerVoteType::ExplicitDefault; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr1.desiredRefreshRate = 24.0f; + lr1.vote = LayerVoteType::ExplicitExactOrMultiple; + lr2.desiredRefreshRate = 90.0f; + lr2.vote = LayerVoteType::ExplicitDefault; + EXPECT_EQ(expected120Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr1.desiredRefreshRate = 24.0f; + lr1.vote = LayerVoteType::ExplicitDefault; + lr2.desiredRefreshRate = 90.0f; + lr2.vote = LayerVoteType::ExplicitExactOrMultiple; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); +} + TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_30_60) { std::vector configs{ {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, @@ -535,7 +606,7 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_Prior EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); lr1.vote = LayerVoteType::Min; - lr2.vote = LayerVoteType::Explicit; + lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 24.0f; EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); @@ -545,7 +616,7 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_Prior EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); lr1.vote = LayerVoteType::Max; - lr2.vote = LayerVoteType::Explicit; + lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 60.0f; EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); @@ -557,7 +628,7 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_Prior lr1.vote = LayerVoteType::Heuristic; lr1.desiredRefreshRate = 30.0f; - lr2.vote = LayerVoteType::Explicit; + lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 45.0f; EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); } @@ -576,7 +647,7 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_24Fps auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; auto& lr = layers[0]; - lr.vote = LayerVoteType::Explicit; + lr.vote = LayerVoteType::ExplicitExactOrMultiple; for (float fps = 23.0f; fps < 25.0f; fps += 0.1f) { lr.desiredRefreshRate = fps; const auto& refreshRate = refreshRateConfigs->getRefreshRateForContentV2(layers); @@ -602,13 +673,13 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContent_Explici lr1.vote = LayerVoteType::Heuristic; lr1.desiredRefreshRate = 60.0f; - lr2.vote = LayerVoteType::Explicit; + lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 90.0f; EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(layers)); lr1.vote = LayerVoteType::Heuristic; lr1.desiredRefreshRate = 90.0f; - lr2.vote = LayerVoteType::Explicit; + lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 60.0f; EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(layers)); } @@ -630,13 +701,13 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_Expli lr1.vote = LayerVoteType::Heuristic; lr1.desiredRefreshRate = 60.0f; - lr2.vote = LayerVoteType::Explicit; + lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 90.0f; EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); lr1.vote = LayerVoteType::Heuristic; lr1.desiredRefreshRate = 90.0f; - lr2.vote = LayerVoteType::Explicit; + lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 60.0f; EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); } @@ -665,7 +736,7 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_75HzC auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; auto& lr = layers[0]; - lr.vote = LayerVoteType::Explicit; + lr.vote = LayerVoteType::ExplicitExactOrMultiple; for (float fps = 75.0f; fps < 100.0f; fps += 0.1f) { lr.desiredRefreshRate = fps; const auto& refreshRate = refreshRateConfigs->getRefreshRateForContentV2(layers); diff --git a/services/surfaceflinger/tests/unittests/mock/MockLayer.h b/services/surfaceflinger/tests/unittests/mock/MockLayer.h index 494e73dda9..e2f6abdf8d 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockLayer.h +++ b/services/surfaceflinger/tests/unittests/mock/MockLayer.h @@ -31,7 +31,7 @@ public: MOCK_METHOD0(getFrameSelectionPriority, int32_t()); MOCK_CONST_METHOD0(isVisible, bool()); MOCK_METHOD0(createClone, sp()); - MOCK_CONST_METHOD0(getFrameRate, std::optional()); + MOCK_CONST_METHOD0(getFrameRate, FrameRate()); }; } // namespace android::mock -- cgit v1.2.3-59-g8ed1b From 2e1dd89a34ed859d6105bc4f680f1b0738e2aa0a Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Thu, 5 Mar 2020 13:48:36 -0800 Subject: SurfaceFlinger: delete RefreshRate copy constructor Avoid copying RefreshRate objects Change-Id: Ic00f14bd03465d163e82ee7f4bf34346f1920ad6 Test: adb shell /data/nativetest64/libsurfaceflinger_unittest/libsurfaceflinger_unittest Bug: 150887328 --- services/surfaceflinger/RefreshRateOverlay.cpp | 8 ++--- services/surfaceflinger/Scheduler/PhaseOffsets.cpp | 8 ++--- .../Scheduler/RefreshRateConfigs.cpp | 29 +++++++++--------- .../surfaceflinger/Scheduler/RefreshRateConfigs.h | 7 +++-- services/surfaceflinger/Scheduler/Scheduler.cpp | 4 +-- services/surfaceflinger/SurfaceFlinger.cpp | 14 ++++----- .../tests/unittests/RefreshRateConfigsTest.cpp | 34 +++++++++++----------- 7 files changed, 53 insertions(+), 51 deletions(-) (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 682679c703..c675971156 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -168,9 +168,9 @@ bool RefreshRateOverlay::createLayer() { } void RefreshRateOverlay::primeCache() { - auto allRefreshRates = mFlinger.mRefreshRateConfigs->getAllRefreshRates(); + auto& allRefreshRates = mFlinger.mRefreshRateConfigs->getAllRefreshRates(); if (allRefreshRates.size() == 1) { - auto fps = allRefreshRates.begin()->second.fps; + auto fps = allRefreshRates.begin()->second->fps; half4 color = {LOW_FPS_COLOR, ALPHA}; mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color)); return; @@ -178,8 +178,8 @@ void RefreshRateOverlay::primeCache() { std::vector supportedFps; supportedFps.reserve(allRefreshRates.size()); - for (auto [ignored, refreshRate] : allRefreshRates) { - supportedFps.push_back(refreshRate.fps); + for (auto& [ignored, refreshRate] : allRefreshRates) { + supportedFps.push_back(refreshRate->fps); } std::sort(supportedFps.begin(), supportedFps.end()); diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp index 63d9c4bc5a..c04447d106 100644 --- a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp +++ b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp @@ -71,10 +71,10 @@ std::unordered_map PhaseOffsets::initializeOffsets std::unordered_map offsets; for (const auto& [ignored, refreshRate] : refreshRateConfigs.getAllRefreshRates()) { - if (refreshRate.fps > 65.0f) { - offsets.emplace(refreshRate.fps, getHighFpsOffsets(refreshRate.vsyncPeriod)); + if (refreshRate->fps > 65.0f) { + offsets.emplace(refreshRate->fps, getHighFpsOffsets(refreshRate->vsyncPeriod)); } else { - offsets.emplace(refreshRate.fps, getDefaultOffsets(refreshRate.vsyncPeriod)); + offsets.emplace(refreshRate->fps, getDefaultOffsets(refreshRate->vsyncPeriod)); } } return offsets; @@ -238,7 +238,7 @@ static std::vector getRefreshRatesFromConfigs( refreshRates.reserve(allRefreshRates.size()); for (const auto& [ignored, refreshRate] : allRefreshRates) { - refreshRates.emplace_back(refreshRate.fps); + refreshRates.emplace_back(refreshRate->fps); } return refreshRates; diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index 15b158d95f..9edbaee22f 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -286,12 +286,12 @@ const RefreshRate& RefreshRateConfigs::getCurrentRefreshRateByPolicyLocked() con mCurrentRefreshRate) != mAvailableRefreshRates.end()) { return *mCurrentRefreshRate; } - return mRefreshRates.at(mDefaultConfig); + return *mRefreshRates.at(mDefaultConfig); } void RefreshRateConfigs::setCurrentConfigId(HwcConfigIndexType configId) { std::lock_guard lock(mLock); - mCurrentRefreshRate = &mRefreshRates.at(configId); + mCurrentRefreshRate = mRefreshRates.at(configId).get(); } RefreshRateConfigs::RefreshRateConfigs(const std::vector& configs, @@ -326,7 +326,7 @@ status_t RefreshRateConfigs::setPolicy(HwcConfigIndexType defaultConfigId, float if (mRefreshRates.count(defaultConfigId) == 0) { return BAD_VALUE; } - const RefreshRate& refreshRate = mRefreshRates.at(defaultConfigId); + const RefreshRate& refreshRate = *mRefreshRates.at(defaultConfigId); if (!refreshRate.inPolicy(minRefreshRate, maxRefreshRate)) { return BAD_VALUE; } @@ -361,10 +361,10 @@ void RefreshRateConfigs::getSortedRefreshRateList( outRefreshRates->clear(); outRefreshRates->reserve(mRefreshRates.size()); for (const auto& [type, refreshRate] : mRefreshRates) { - if (shouldAddRefreshRate(refreshRate)) { + if (shouldAddRefreshRate(*refreshRate)) { ALOGV("getSortedRefreshRateList: config %d added to list policy", - refreshRate.configId.value()); - outRefreshRates->push_back(&refreshRate); + refreshRate->configId.value()); + outRefreshRates->push_back(refreshRate.get()); } } @@ -376,7 +376,7 @@ void RefreshRateConfigs::getSortedRefreshRateList( void RefreshRateConfigs::constructAvailableRefreshRates() { // Filter configs based on current policy and sort based on vsync period - HwcConfigGroupType group = mRefreshRates.at(mDefaultConfig).configGroup; + HwcConfigGroupType group = mRefreshRates.at(mDefaultConfig)->configGroup; ALOGV("constructAvailableRefreshRates: default %d group %d min %.2f max %.2f", mDefaultConfig.value(), group.value(), mMinRefreshRateFps, mMaxRefreshRateFps); getSortedRefreshRateList( @@ -403,16 +403,15 @@ void RefreshRateConfigs::init(const std::vector& configs, LOG_ALWAYS_FATAL_IF(configs.empty()); LOG_ALWAYS_FATAL_IF(currentHwcConfig.value() >= configs.size()); - auto buildRefreshRate = [&](InputConfig config) -> RefreshRate { - const float fps = 1e9f / config.vsyncPeriod; - return RefreshRate(config.configId, config.vsyncPeriod, config.configGroup, - base::StringPrintf("%2.ffps", fps), fps); - }; - for (const auto& config : configs) { - mRefreshRates.emplace(config.configId, buildRefreshRate(config)); + const float fps = 1e9f / config.vsyncPeriod; + mRefreshRates.emplace(config.configId, + std::make_unique(config.configId, config.vsyncPeriod, + config.configGroup, + base::StringPrintf("%2.ffps", fps), + fps)); if (config.configId == currentHwcConfig) { - mCurrentRefreshRate = &mRefreshRates.at(config.configId); + mCurrentRefreshRate = mRefreshRates.at(config.configId).get(); } } diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index c8aec86db3..9cd59593bb 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -59,6 +59,8 @@ public: configGroup(configGroup), name(std::move(name)), fps(fps) {} + + RefreshRate(const RefreshRate&) = delete; // This config ID corresponds to the position of the config in the vector that is stored // on the device. const HwcConfigIndexType configId; @@ -85,7 +87,8 @@ public: bool operator==(const RefreshRate& other) const { return !(*this != other); } }; - using AllRefreshRatesMapType = std::unordered_map; + using AllRefreshRatesMapType = + std::unordered_map>; // Sets the current policy to choose refresh rates. Returns NO_ERROR if the requested policy is // valid, or a negative error value otherwise. policyChanged, if non-null, will be set to true @@ -163,7 +166,7 @@ public: // Returns the refresh rate that corresponds to a HwcConfigIndexType. This won't change at // runtime. const RefreshRate& getRefreshRateFromConfigId(HwcConfigIndexType configId) const { - return mRefreshRates.at(configId); + return *mRefreshRates.at(configId); }; // Stores the current configId the device operates at diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 54442391ea..96fa0610d0 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -463,7 +463,7 @@ void Scheduler::chooseRefreshRateForContent() { return; } mFeatures.configId = newConfigId; - auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); + auto& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); mSchedulerCallback.changeRefreshRate(newRefreshRate, ConfigEvent::Changed); } } @@ -515,7 +515,7 @@ void Scheduler::kernelIdleTimerCallback(TimerState state) { // TODO(145561154): cleanup the kernel idle timer implementation and the refresh rate // magic number - const auto refreshRate = mRefreshRateConfigs.getCurrentRefreshRate(); + const auto& refreshRate = mRefreshRateConfigs.getCurrentRefreshRate(); constexpr float FPS_THRESHOLD_FOR_KERNEL_TIMER = 65.0f; if (state == TimerState::Reset && refreshRate.fps > FPS_THRESHOLD_FOR_KERNEL_TIMER) { // If we're not in performance mode then the kernel timer shouldn't do diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index c995db4972..8587fb2c43 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -903,7 +903,7 @@ int SurfaceFlinger::getActiveConfig(const sp& displayToken) { void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) { ATRACE_CALL(); - auto refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(info.configId); + auto& refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(info.configId); ALOGV("setDesiredActiveConfig(%s)", refreshRate.name.c_str()); // Don't check against the current mode yet. Worst case we set the desired @@ -976,7 +976,7 @@ void SurfaceFlinger::setActiveConfigInternal() { mRefreshRateStats->setConfigMode(mUpcomingActiveConfig.configId); display->setActiveConfig(mUpcomingActiveConfig.configId); - auto refreshRate = + auto& refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(mUpcomingActiveConfig.configId); mPhaseConfiguration->setRefreshRateFps(refreshRate.fps); mVSyncModulator->setPhaseOffsets(mPhaseConfiguration->getCurrentOffsets()); @@ -996,7 +996,7 @@ void SurfaceFlinger::desiredActiveConfigChangeDone() { mDesiredActiveConfig.event = Scheduler::ConfigEvent::None; mDesiredActiveConfigChanged = false; - auto const refreshRate = + const auto& refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(mDesiredActiveConfig.configId); mScheduler->resyncToHardwareVsync(true, refreshRate.vsyncPeriod); mPhaseConfiguration->setRefreshRateFps(refreshRate.fps); @@ -1029,7 +1029,7 @@ bool SurfaceFlinger::performSetActiveConfig() { desiredActiveConfig = mDesiredActiveConfig; } - auto refreshRate = + auto& refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(desiredActiveConfig.configId); ALOGV("performSetActiveConfig changing active config to %d(%s)", refreshRate.configId.value(), refreshRate.name.c_str()); @@ -5128,7 +5128,7 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r n = data.readInt32(); if (n == 1 && !mRefreshRateOverlay) { mRefreshRateOverlay = std::make_unique(*this); - auto current = mRefreshRateConfigs->getCurrentRefreshRate(); + auto& current = mRefreshRateConfigs->getCurrentRefreshRate(); mRefreshRateOverlay->changeRefreshRate(current); } else if (n == 0) { mRefreshRateOverlay.reset(); @@ -5177,7 +5177,7 @@ void SurfaceFlinger::kernelTimerChanged(bool expired) { if (mRefreshRateOverlay) { const auto kernelTimerEnabled = property_get_bool(KERNEL_IDLE_TIMER_PROP, false); const bool timerExpired = kernelTimerEnabled && expired; - const auto& current = [this]() { + const auto& current = [this]() -> const RefreshRate& { std::lock_guard lock(mActiveConfigLock); if (mDesiredActiveConfigChanged) { return mRefreshRateConfigs->getRefreshRateFromConfigId( @@ -5857,7 +5857,7 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecsInternal(const spgetActiveConfig(), vsyncPeriod); auto configId = mScheduler->getPreferredConfigId(); - auto preferredRefreshRate = configId + auto& preferredRefreshRate = configId ? mRefreshRateConfigs->getRefreshRateFromConfigId(*configId) // NOTE: Choose the default config ID, if Scheduler doesn't have one in mind. : mRefreshRateConfigs->getRefreshRateFromConfigId(defaultConfig); diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp index e7e7f66c95..4a179b6d0f 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -93,8 +93,8 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap) { auto refreshRateConfigs = std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); - const auto minRate = refreshRateConfigs->getMinRefreshRate(); - const auto performanceRate = refreshRateConfigs->getMaxRefreshRate(); + const auto& minRate = refreshRateConfigs->getMinRefreshRate(); + const auto& performanceRate = refreshRateConfigs->getMaxRefreshRate(); RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; ASSERT_EQ(expectedDefaultConfig, minRate); @@ -102,8 +102,8 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap) { 90}; ASSERT_EQ(expectedPerformanceConfig, performanceRate); - const auto minRateByPolicy = refreshRateConfigs->getMinRefreshRateByPolicy(); - const auto performanceRateByPolicy = refreshRateConfigs->getMaxRefreshRateByPolicy(); + const auto& minRateByPolicy = refreshRateConfigs->getMinRefreshRateByPolicy(); + const auto& performanceRateByPolicy = refreshRateConfigs->getMaxRefreshRateByPolicy(); ASSERT_EQ(minRateByPolicy, minRate); ASSERT_EQ(performanceRateByPolicy, performanceRate); } @@ -115,10 +115,10 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap_differe auto refreshRateConfigs = std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); - const auto minRate = refreshRateConfigs->getMinRefreshRateByPolicy(); - const auto performanceRate = refreshRateConfigs->getMaxRefreshRate(); - const auto minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy(); - const auto performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy(); + const auto& minRate = refreshRateConfigs->getMinRefreshRateByPolicy(); + const auto& performanceRate = refreshRateConfigs->getMaxRefreshRate(); + const auto& minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy(); + const auto& performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy(); RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; ASSERT_EQ(expectedDefaultConfig, minRate); @@ -128,8 +128,8 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap_differe ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_90, 60, 90, nullptr), 0); refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); - const auto minRate90 = refreshRateConfigs->getMinRefreshRateByPolicy(); - const auto performanceRate90 = refreshRateConfigs->getMaxRefreshRateByPolicy(); + const auto& minRate90 = refreshRateConfigs->getMinRefreshRateByPolicy(); + const auto& performanceRate90 = refreshRateConfigs->getMaxRefreshRateByPolicy(); RefreshRate expectedPerformanceConfig = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_1, "90fps", 90}; @@ -145,8 +145,8 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_policyChange) { auto refreshRateConfigs = std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); - auto minRate = refreshRateConfigs->getMinRefreshRateByPolicy(); - auto performanceRate = refreshRateConfigs->getMaxRefreshRateByPolicy(); + auto& minRate = refreshRateConfigs->getMinRefreshRateByPolicy(); + auto& performanceRate = refreshRateConfigs->getMaxRefreshRateByPolicy(); RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; ASSERT_EQ(expectedDefaultConfig, minRate); @@ -156,8 +156,8 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_policyChange) { ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 60, 60, nullptr), 0); - auto minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy(); - auto performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy(); + auto& minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy(); + auto& performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy(); ASSERT_EQ(expectedDefaultConfig, minRate60); ASSERT_EQ(expectedDefaultConfig, performanceRate60); } @@ -169,19 +169,19 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getCurrentRefreshRate) { auto refreshRateConfigs = std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); { - auto current = refreshRateConfigs->getCurrentRefreshRate(); + auto& current = refreshRateConfigs->getCurrentRefreshRate(); EXPECT_EQ(current.configId, HWC_CONFIG_ID_60); } refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); { - auto current = refreshRateConfigs->getCurrentRefreshRate(); + auto& current = refreshRateConfigs->getCurrentRefreshRate(); EXPECT_EQ(current.configId, HWC_CONFIG_ID_90); } ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_90, 90, 90, nullptr), 0); { - auto current = refreshRateConfigs->getCurrentRefreshRate(); + auto& current = refreshRateConfigs->getCurrentRefreshRate(); EXPECT_EQ(current.configId, HWC_CONFIG_ID_90); } } -- cgit v1.2.3-59-g8ed1b From abc2760c6a3b0be88b0cdf0ff4100575992715af Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Wed, 8 Apr 2020 17:20:29 -0700 Subject: SurfaceFlinger: Consider resolution when switching refresh rate Do not change refresh rate across configs with multiple resolutions Bug: 150237118 Test: adb shell /data/nativetest64/libsurfaceflinger_unittest/libsurfaceflinger_unittest Change-Id: I9b0f355a72343cf120229b98e6ad082ea75d3080 --- services/surfaceflinger/RefreshRateOverlay.cpp | 6 +- services/surfaceflinger/Scheduler/HwcStrongTypes.h | 1 - services/surfaceflinger/Scheduler/PhaseOffsets.cpp | 6 +- .../Scheduler/RefreshRateConfigs.cpp | 83 ++- .../surfaceflinger/Scheduler/RefreshRateConfigs.h | 71 +-- .../surfaceflinger/Scheduler/RefreshRateStats.h | 6 +- services/surfaceflinger/Scheduler/Scheduler.cpp | 42 +- services/surfaceflinger/SurfaceFlinger.cpp | 55 +- .../tests/unittests/LayerHistoryTest.cpp | 17 +- .../tests/unittests/LayerHistoryTestV2.cpp | 17 +- .../tests/unittests/RefreshRateConfigsTest.cpp | 636 ++++++++++----------- .../tests/unittests/RefreshRateStatsTest.cpp | 23 +- .../tests/unittests/SchedulerTest.cpp | 9 +- .../tests/unittests/TestableSurfaceFlinger.h | 10 +- .../unittests/mock/DisplayHardware/MockComposer.h | 1 + .../unittests/mock/DisplayHardware/MockDisplay.h | 13 + 16 files changed, 511 insertions(+), 485 deletions(-) (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index c675971156..0a0f2f132e 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -170,7 +170,7 @@ bool RefreshRateOverlay::createLayer() { void RefreshRateOverlay::primeCache() { auto& allRefreshRates = mFlinger.mRefreshRateConfigs->getAllRefreshRates(); if (allRefreshRates.size() == 1) { - auto fps = allRefreshRates.begin()->second->fps; + auto fps = allRefreshRates.begin()->second->getFps(); half4 color = {LOW_FPS_COLOR, ALPHA}; mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color)); return; @@ -179,7 +179,7 @@ void RefreshRateOverlay::primeCache() { std::vector supportedFps; supportedFps.reserve(allRefreshRates.size()); for (auto& [ignored, refreshRate] : allRefreshRates) { - supportedFps.push_back(refreshRate->fps); + supportedFps.push_back(refreshRate->getFps()); } std::sort(supportedFps.begin(), supportedFps.end()); @@ -207,7 +207,7 @@ void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { const int32_t right = left + display->getWidth() / 8; const int32_t buttom = top + display->getHeight() / 32; - auto buffer = mBufferCache[refreshRate.fps]; + auto buffer = mBufferCache[refreshRate.getFps()]; mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}); mLayer->setFrame(Rect(left, top, right, buttom)); diff --git a/services/surfaceflinger/Scheduler/HwcStrongTypes.h b/services/surfaceflinger/Scheduler/HwcStrongTypes.h index cfbbdfe4fd..8ba4f20b84 100644 --- a/services/surfaceflinger/Scheduler/HwcStrongTypes.h +++ b/services/surfaceflinger/Scheduler/HwcStrongTypes.h @@ -22,6 +22,5 @@ namespace android { // Strong types for the different indexes as they are referring to a different base. using HwcConfigIndexType = StrongTyping; -using HwcConfigGroupType = StrongTyping; } // namespace android \ No newline at end of file diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp index 43883fb387..d9aaa05d96 100644 --- a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp +++ b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp @@ -43,7 +43,7 @@ std::vector getRefreshRatesFromConfigs( refreshRates.reserve(allRefreshRates.size()); for (const auto& [ignored, refreshRate] : allRefreshRates) { - refreshRates.emplace_back(refreshRate->fps); + refreshRates.emplace_back(refreshRate->getFps()); } return refreshRates; @@ -59,7 +59,7 @@ namespace impl { PhaseOffsets::PhaseOffsets(const scheduler::RefreshRateConfigs& refreshRateConfigs) : PhaseOffsets(getRefreshRatesFromConfigs(refreshRateConfigs), - refreshRateConfigs.getCurrentRefreshRate().fps, + refreshRateConfigs.getCurrentRefreshRate().getFps(), // Below defines the threshold when an offset is considered to be negative, // i.e. targeting for the N+2 vsync instead of N+1. This means that: For offset // < threshold, SF wake up (vsync_duration - offset) before HW vsync. For @@ -275,7 +275,7 @@ std::unordered_map PhaseDurations::initializeOff PhaseDurations::PhaseDurations(const scheduler::RefreshRateConfigs& refreshRateConfigs) : PhaseDurations(getRefreshRatesFromConfigs(refreshRateConfigs), - refreshRateConfigs.getCurrentRefreshRate().fps, + refreshRateConfigs.getCurrentRefreshRate().getFps(), getProperty("debug.sf.late.sf.duration").value_or(-1), getProperty("debug.sf.late.app.duration").value_or(-1), getProperty("debug.sf.early.sf.duration").value_or(mSfDuration), diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index 14ef73335e..5634adb9fd 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -53,7 +53,7 @@ const RefreshRate& RefreshRateConfigs::getRefreshRateForContent( if (explicitContentFramerate != 0) { contentFramerate = explicitContentFramerate; } else if (contentFramerate == 0) { - contentFramerate = round(mMaxSupportedRefreshRate->fps); + contentFramerate = round(mMaxSupportedRefreshRate->getFps()); } ATRACE_INT("ContentFPS", contentFramerate); @@ -177,7 +177,7 @@ const RefreshRate& RefreshRateConfigs::getRefreshRateForContentV2( continue; } - const auto displayPeriod = scores[i].first->vsyncPeriod; + const auto displayPeriod = scores[i].first->hwcConfig->getVsyncPeriod(); const auto layerPeriod = round(1e9f / layer.desiredRefreshRate); if (layer.vote == LayerVoteType::ExplicitDefault) { const auto layerScore = [&]() { @@ -309,21 +309,30 @@ void RefreshRateConfigs::setCurrentConfigId(HwcConfigIndexType configId) { mCurrentRefreshRate = mRefreshRates.at(configId).get(); } -RefreshRateConfigs::RefreshRateConfigs(const std::vector& configs, - HwcConfigIndexType currentHwcConfig) { - init(configs, currentHwcConfig); -} - RefreshRateConfigs::RefreshRateConfigs( const std::vector>& configs, HwcConfigIndexType currentConfigId) { - std::vector inputConfigs; - for (size_t configId = 0; configId < configs.size(); ++configId) { - auto configGroup = HwcConfigGroupType(configs[configId]->getConfigGroup()); - inputConfigs.push_back({HwcConfigIndexType(static_cast(configId)), configGroup, - configs[configId]->getVsyncPeriod()}); + LOG_ALWAYS_FATAL_IF(configs.empty()); + LOG_ALWAYS_FATAL_IF(currentConfigId.value() >= configs.size()); + + for (auto configId = HwcConfigIndexType(0); configId.value() < configs.size(); configId++) { + const auto& config = configs.at(static_cast(configId.value())); + const float fps = 1e9f / config->getVsyncPeriod(); + mRefreshRates.emplace(configId, + std::make_unique(configId, config, + base::StringPrintf("%2.ffps", fps), fps, + RefreshRate::ConstructorTag(0))); + if (configId == currentConfigId) { + mCurrentRefreshRate = mRefreshRates.at(configId).get(); + } } - init(inputConfigs, currentConfigId); + + std::vector sortedConfigs; + getSortedRefreshRateList([](const RefreshRate&) { return true; }, &sortedConfigs); + mDisplayManagerPolicy.defaultConfig = currentConfigId; + mMinSupportedRefreshRate = sortedConfigs.front(); + mMaxSupportedRefreshRate = sortedConfigs.back(); + constructAvailableRefreshRates(); } bool RefreshRateConfigs::isPolicyValid(const Policy& policy) { @@ -406,10 +415,13 @@ void RefreshRateConfigs::getSortedRefreshRateList( std::sort(outRefreshRates->begin(), outRefreshRates->end(), [](const auto refreshRate1, const auto refreshRate2) { - if (refreshRate1->vsyncPeriod != refreshRate2->vsyncPeriod) { - return refreshRate1->vsyncPeriod > refreshRate2->vsyncPeriod; + if (refreshRate1->hwcConfig->getVsyncPeriod() != + refreshRate2->hwcConfig->getVsyncPeriod()) { + return refreshRate1->hwcConfig->getVsyncPeriod() > + refreshRate2->hwcConfig->getVsyncPeriod(); } else { - return refreshRate1->configGroup > refreshRate2->configGroup; + return refreshRate1->hwcConfig->getConfigGroup() > + refreshRate2->hwcConfig->getConfigGroup(); } }); } @@ -417,13 +429,20 @@ void RefreshRateConfigs::getSortedRefreshRateList( void RefreshRateConfigs::constructAvailableRefreshRates() { // Filter configs based on current policy and sort based on vsync period const Policy* policy = getCurrentPolicyLocked(); - HwcConfigGroupType group = mRefreshRates.at(policy->defaultConfig)->configGroup; + const auto& defaultConfig = mRefreshRates.at(policy->defaultConfig)->hwcConfig; ALOGV("constructAvailableRefreshRates: default %d group %d min %.2f max %.2f", - policy->defaultConfig.value(), group.value(), policy->minRefreshRate, + policy->defaultConfig.value(), defaultConfig->getConfigGroup(), policy->minRefreshRate, policy->maxRefreshRate); getSortedRefreshRateList( [&](const RefreshRate& refreshRate) REQUIRES(mLock) { - return (policy->allowGroupSwitching || refreshRate.configGroup == group) && + const auto& hwcConfig = refreshRate.hwcConfig; + + return hwcConfig->getHeight() == defaultConfig->getHeight() && + hwcConfig->getWidth() == defaultConfig->getWidth() && + hwcConfig->getDpiX() == defaultConfig->getDpiX() && + hwcConfig->getDpiY() == defaultConfig->getDpiY() && + (policy->allowGroupSwitching || + hwcConfig->getConfigGroup() == defaultConfig->getConfigGroup()) && refreshRate.inPolicy(policy->minRefreshRate, policy->maxRefreshRate); }, &mAvailableRefreshRates); @@ -440,30 +459,4 @@ void RefreshRateConfigs::constructAvailableRefreshRates() { policy->maxRefreshRate); } -// NO_THREAD_SAFETY_ANALYSIS since this is called from the constructor -void RefreshRateConfigs::init(const std::vector& configs, - HwcConfigIndexType currentHwcConfig) NO_THREAD_SAFETY_ANALYSIS { - LOG_ALWAYS_FATAL_IF(configs.empty()); - LOG_ALWAYS_FATAL_IF(currentHwcConfig.value() >= configs.size()); - - for (const auto& config : configs) { - const float fps = 1e9f / config.vsyncPeriod; - mRefreshRates.emplace(config.configId, - std::make_unique(config.configId, config.vsyncPeriod, - config.configGroup, - base::StringPrintf("%2.ffps", fps), - fps)); - if (config.configId == currentHwcConfig) { - mCurrentRefreshRate = mRefreshRates.at(config.configId).get(); - } - } - - std::vector sortedConfigs; - getSortedRefreshRateList([](const RefreshRate&) { return true; }, &sortedConfigs); - mDisplayManagerPolicy.defaultConfig = currentHwcConfig; - mMinSupportedRefreshRate = sortedConfigs.front(); - mMaxSupportedRefreshRate = sortedConfigs.back(); - constructAvailableRefreshRates(); -} - } // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index e749f8fb93..dea7e90896 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -29,6 +29,8 @@ #include "Scheduler/StrongTyping.h" namespace android::scheduler { +class RefreshRateConfigsTest; + using namespace std::chrono_literals; enum class RefreshRateConfigEvent : unsigned { None = 0b0, Changed = 0b1 }; @@ -49,30 +51,27 @@ public: static constexpr nsecs_t MARGIN_FOR_PERIOD_CALCULATION = std::chrono::nanoseconds(800us).count(); - struct RefreshRate { - // The tolerance within which we consider FPS approximately equals. - static constexpr float FPS_EPSILON = 0.001f; + class RefreshRate { + private: + // Effectively making the constructor private while allowing + // std::make_unique to create the object + struct ConstructorTag { + explicit ConstructorTag(int) {} + }; - RefreshRate(HwcConfigIndexType configId, nsecs_t vsyncPeriod, - HwcConfigGroupType configGroup, std::string name, float fps) - : configId(configId), - vsyncPeriod(vsyncPeriod), - configGroup(configGroup), - name(std::move(name)), - fps(fps) {} + public: + RefreshRate(HwcConfigIndexType configId, + std::shared_ptr config, std::string name, + float fps, ConstructorTag) + : configId(configId), hwcConfig(config), name(std::move(name)), fps(fps) {} RefreshRate(const RefreshRate&) = delete; - // This config ID corresponds to the position of the config in the vector that is stored - // on the device. - const HwcConfigIndexType configId; - // Vsync period in nanoseconds. - const nsecs_t vsyncPeriod; - // This configGroup for the config. - const HwcConfigGroupType configGroup; - // Human readable name of the refresh rate. - const std::string name; - // Refresh rate in frames per second - const float fps = 0; + + HwcConfigIndexType getConfigId() const { return configId; } + nsecs_t getVsyncPeriod() const { return hwcConfig->getVsyncPeriod(); } + int32_t getConfigGroup() const { return hwcConfig->getConfigGroup(); } + const std::string& getName() const { return name; } + float getFps() const { return fps; } // Checks whether the fps of this RefreshRate struct is within a given min and max refresh // rate passed in. FPS_EPSILON is applied to the boundaries for approximation. @@ -81,11 +80,27 @@ public: } bool operator!=(const RefreshRate& other) const { - return configId != other.configId || vsyncPeriod != other.vsyncPeriod || - configGroup != other.configGroup; + return configId != other.configId || hwcConfig != other.hwcConfig; } bool operator==(const RefreshRate& other) const { return !(*this != other); } + + private: + friend RefreshRateConfigs; + friend RefreshRateConfigsTest; + + // The tolerance within which we consider FPS approximately equals. + static constexpr float FPS_EPSILON = 0.001f; + + // This config ID corresponds to the position of the config in the vector that is stored + // on the device. + const HwcConfigIndexType configId; + // The config itself + std::shared_ptr hwcConfig; + // Human readable name of the refresh rate. + const std::string name; + // Refresh rate in frames per second + const float fps = 0; }; using AllRefreshRatesMapType = @@ -208,20 +223,10 @@ public: // Stores the current configId the device operates at void setCurrentConfigId(HwcConfigIndexType configId) EXCLUDES(mLock); - struct InputConfig { - HwcConfigIndexType configId = HwcConfigIndexType(0); - HwcConfigGroupType configGroup = HwcConfigGroupType(0); - nsecs_t vsyncPeriod = 0; - }; - - RefreshRateConfigs(const std::vector& configs, - HwcConfigIndexType currentHwcConfig); RefreshRateConfigs(const std::vector>& configs, HwcConfigIndexType currentConfigId); private: - void init(const std::vector& configs, HwcConfigIndexType currentHwcConfig); - void constructAvailableRefreshRates() REQUIRES(mLock); void getSortedRefreshRateList( diff --git a/services/surfaceflinger/Scheduler/RefreshRateStats.h b/services/surfaceflinger/Scheduler/RefreshRateStats.h index e44cd528b5..66d4a0305f 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateStats.h +++ b/services/surfaceflinger/Scheduler/RefreshRateStats.h @@ -78,10 +78,10 @@ public: // Multiple configs may map to the same name, e.g. "60fps". Add the // times for such configs together. for (const auto& [configId, time] : mConfigModesTotalTime) { - totalTime[mRefreshRateConfigs.getRefreshRateFromConfigId(configId).name] = 0; + totalTime[mRefreshRateConfigs.getRefreshRateFromConfigId(configId).getName()] = 0; } for (const auto& [configId, time] : mConfigModesTotalTime) { - totalTime[mRefreshRateConfigs.getRefreshRateFromConfigId(configId).name] += time; + totalTime[mRefreshRateConfigs.getRefreshRateFromConfigId(configId).getName()] += time; } totalTime["ScreenOff"] = mScreenOffTime; return totalTime; @@ -115,7 +115,7 @@ private: } mConfigModesTotalTime[mCurrentConfigMode] += timeElapsedMs; fps = static_cast(std::round( - mRefreshRateConfigs.getRefreshRateFromConfigId(mCurrentConfigMode).fps)); + mRefreshRateConfigs.getRefreshRateFromConfigId(mCurrentConfigMode).getFps())); } else { mScreenOffTime += timeElapsedMs; } diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index cd6075f5b4..9a9523f27e 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -332,7 +332,7 @@ void Scheduler::resync() { const nsecs_t last = mLastResyncTime.exchange(now); if (now - last > kIgnoreDelay) { - resyncToHardwareVsync(false, mRefreshRateConfigs.getCurrentRefreshRate().vsyncPeriod); + resyncToHardwareVsync(false, mRefreshRateConfigs.getCurrentRefreshRate().getVsyncPeriod()); } } @@ -389,34 +389,34 @@ void Scheduler::registerLayer(Layer* layer) { // keep the layer history, since we use it for other features (like Frame Rate API), so layers // still need to be registered. if (!mUseContentDetection) { - mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().fps, - mRefreshRateConfigs.getMaxRefreshRate().fps, + mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().getFps(), + mRefreshRateConfigs.getMaxRefreshRate().getFps(), scheduler::LayerHistory::LayerVoteType::NoVote); return; } // In V1 of content detection, all layers are registered as Heuristic (unless it's wallpaper). if (!mUseContentDetectionV2) { - const auto lowFps = mRefreshRateConfigs.getMinRefreshRate().fps; + const auto lowFps = mRefreshRateConfigs.getMinRefreshRate().getFps(); const auto highFps = layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER ? lowFps - : mRefreshRateConfigs.getMaxRefreshRate().fps; + : mRefreshRateConfigs.getMaxRefreshRate().getFps(); mLayerHistory->registerLayer(layer, lowFps, highFps, scheduler::LayerHistory::LayerVoteType::Heuristic); } else { if (layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER) { // Running Wallpaper at Min is considered as part of content detection. - mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().fps, - mRefreshRateConfigs.getMaxRefreshRate().fps, + mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().getFps(), + mRefreshRateConfigs.getMaxRefreshRate().getFps(), scheduler::LayerHistory::LayerVoteType::Min); } else if (layer->getWindowType() == InputWindowInfo::TYPE_STATUS_BAR) { - mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().fps, - mRefreshRateConfigs.getMaxRefreshRate().fps, + mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().getFps(), + mRefreshRateConfigs.getMaxRefreshRate().getFps(), scheduler::LayerHistory::LayerVoteType::NoVote); } else { - mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().fps, - mRefreshRateConfigs.getMaxRefreshRate().fps, + mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().getFps(), + mRefreshRateConfigs.getMaxRefreshRate().getFps(), scheduler::LayerHistory::LayerVoteType::Heuristic); } } @@ -503,12 +503,13 @@ void Scheduler::kernelIdleTimerCallback(TimerState state) { // magic number const auto& refreshRate = mRefreshRateConfigs.getCurrentRefreshRate(); constexpr float FPS_THRESHOLD_FOR_KERNEL_TIMER = 65.0f; - if (state == TimerState::Reset && refreshRate.fps > FPS_THRESHOLD_FOR_KERNEL_TIMER) { + if (state == TimerState::Reset && refreshRate.getFps() > FPS_THRESHOLD_FOR_KERNEL_TIMER) { // If we're not in performance mode then the kernel timer shouldn't do // anything, as the refresh rate during DPU power collapse will be the // same. - resyncToHardwareVsync(true /* makeAvailable */, refreshRate.vsyncPeriod); - } else if (state == TimerState::Expired && refreshRate.fps <= FPS_THRESHOLD_FOR_KERNEL_TIMER) { + resyncToHardwareVsync(true /* makeAvailable */, refreshRate.getVsyncPeriod()); + } else if (state == TimerState::Expired && + refreshRate.getFps() <= FPS_THRESHOLD_FOR_KERNEL_TIMER) { // Disable HW VSYNC if the timer expired, as we don't need it enabled if // we're not pushing frames, and if we're in PERFORMANCE mode then we'll // need to update the DispSync model anyway. @@ -580,30 +581,31 @@ HwcConfigIndexType Scheduler::calculateRefreshRateConfigIndexType() { if (mDisplayPowerTimer && (!mFeatures.isDisplayPowerStateNormal || mFeatures.displayPowerTimer == TimerState::Reset)) { - return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId; + return mRefreshRateConfigs.getMaxRefreshRateByPolicy().getConfigId(); } if (!mUseContentDetectionV2) { // As long as touch is active we want to be in performance mode. if (mTouchTimer && mFeatures.touch == TouchState::Active) { - return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId; + return mRefreshRateConfigs.getMaxRefreshRateByPolicy().getConfigId(); } } // If timer has expired as it means there is no new content on the screen. if (mIdleTimer && mFeatures.idleTimer == TimerState::Expired) { - return mRefreshRateConfigs.getMinRefreshRateByPolicy().configId; + return mRefreshRateConfigs.getMinRefreshRateByPolicy().getConfigId(); } if (!mUseContentDetectionV2) { // If content detection is off we choose performance as we don't know the content fps. if (mFeatures.contentDetectionV1 == ContentDetectionState::Off) { // NOTE: V1 always calls this, but this is not a default behavior for V2. - return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId; + return mRefreshRateConfigs.getMaxRefreshRateByPolicy().getConfigId(); } // Content detection is on, find the appropriate refresh rate with minimal error - return mRefreshRateConfigs.getRefreshRateForContent(mFeatures.contentRequirements).configId; + return mRefreshRateConfigs.getRefreshRateForContent(mFeatures.contentRequirements) + .getConfigId(); } bool touchConsidered; @@ -613,7 +615,7 @@ HwcConfigIndexType Scheduler::calculateRefreshRateConfigIndexType() { mTouchTimer && mFeatures.touch == TouchState::Active, &touchConsidered) - .configId; + .getConfigId(); if (touchConsidered) { // Clear layer history if refresh rate was selected based on touch to allow // the hueristic to pick up with the new rate. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 952edb4a48..8453f45feb 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -927,7 +927,7 @@ int SurfaceFlinger::getActiveConfig(const sp& displayToken) { void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) { ATRACE_CALL(); auto& refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(info.configId); - ALOGV("setDesiredActiveConfig(%s)", refreshRate.name.c_str()); + ALOGV("setDesiredActiveConfig(%s)", refreshRate.getName().c_str()); std::lock_guard lock(mActiveConfigLock); if (mDesiredActiveConfigChanged) { @@ -939,7 +939,7 @@ void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) { } else { // Check is we are already at the desired config const auto display = getDefaultDisplayDeviceLocked(); - if (!display || display->getActiveConfig() == refreshRate.configId) { + if (!display || display->getActiveConfig() == refreshRate.getConfigId()) { return; } @@ -951,12 +951,12 @@ void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) { repaintEverythingForHWC(); // Start receiving vsync samples now, so that we can detect a period // switch. - mScheduler->resyncToHardwareVsync(true, refreshRate.vsyncPeriod); + mScheduler->resyncToHardwareVsync(true, refreshRate.getVsyncPeriod()); // As we called to set period, we will call to onRefreshRateChangeCompleted once // DispSync model is locked. mVSyncModulator->onRefreshRateChangeInitiated(); - mPhaseConfiguration->setRefreshRateFps(refreshRate.fps); + mPhaseConfiguration->setRefreshRateFps(refreshRate.getFps()); mVSyncModulator->setPhaseOffsets(mPhaseConfiguration->getCurrentOffsets()); } @@ -988,8 +988,9 @@ status_t SurfaceFlinger::setActiveConfig(const sp& displayToken, int mo const auto& refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(config); result = setDesiredDisplayConfigSpecsInternal(display, scheduler::RefreshRateConfigs:: - Policy{config, refreshRate.fps, - refreshRate.fps}, + Policy{config, + refreshRate.getFps(), + refreshRate.getFps()}, /*overridePolicy=*/false); } })); @@ -1015,17 +1016,17 @@ void SurfaceFlinger::setActiveConfigInternal() { auto& refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(mUpcomingActiveConfig.configId); - if (refreshRate.vsyncPeriod != oldRefreshRate.vsyncPeriod) { + if (refreshRate.getVsyncPeriod() != oldRefreshRate.getVsyncPeriod()) { mTimeStats->incrementRefreshRateSwitches(); } - mPhaseConfiguration->setRefreshRateFps(refreshRate.fps); + mPhaseConfiguration->setRefreshRateFps(refreshRate.getFps()); mVSyncModulator->setPhaseOffsets(mPhaseConfiguration->getCurrentOffsets()); - ATRACE_INT("ActiveConfigFPS", refreshRate.fps); + ATRACE_INT("ActiveConfigFPS", refreshRate.getFps()); if (mUpcomingActiveConfig.event != Scheduler::ConfigEvent::None) { const nsecs_t vsyncPeriod = mRefreshRateConfigs->getRefreshRateFromConfigId(mUpcomingActiveConfig.configId) - .vsyncPeriod; + .getVsyncPeriod(); mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value, mUpcomingActiveConfig.configId, vsyncPeriod); } @@ -1038,8 +1039,8 @@ void SurfaceFlinger::desiredActiveConfigChangeDone() { const auto& refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(mDesiredActiveConfig.configId); - mScheduler->resyncToHardwareVsync(true, refreshRate.vsyncPeriod); - mPhaseConfiguration->setRefreshRateFps(refreshRate.fps); + mScheduler->resyncToHardwareVsync(true, refreshRate.getVsyncPeriod()); + mPhaseConfiguration->setRefreshRateFps(refreshRate.getFps()); mVSyncModulator->setPhaseOffsets(mPhaseConfiguration->getCurrentOffsets()); } @@ -1071,8 +1072,8 @@ bool SurfaceFlinger::performSetActiveConfig() { auto& refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(desiredActiveConfig.configId); - ALOGV("performSetActiveConfig changing active config to %d(%s)", refreshRate.configId.value(), - refreshRate.name.c_str()); + ALOGV("performSetActiveConfig changing active config to %d(%s)", + refreshRate.getConfigId().value(), refreshRate.getName().c_str()); const auto display = getDefaultDisplayDeviceLocked(); if (!display || display->getActiveConfig() == desiredActiveConfig.configId) { // display is not valid or we are already in the requested mode @@ -1093,7 +1094,7 @@ bool SurfaceFlinger::performSetActiveConfig() { const auto displayId = display->getId(); LOG_ALWAYS_FATAL_IF(!displayId); - ATRACE_INT("ActiveConfigFPS_HWC", refreshRate.fps); + ATRACE_INT("ActiveConfigFPS_HWC", refreshRate.getFps()); // TODO(b/142753666) use constrains HWC2::VsyncPeriodChangeConstraints constraints; @@ -1621,13 +1622,13 @@ void SurfaceFlinger::changeRefreshRateLocked(const RefreshRate& refreshRate, ATRACE_CALL(); // Don't do any updating if the current fps is the same as the new one. - if (!isDisplayConfigAllowed(refreshRate.configId)) { + if (!isDisplayConfigAllowed(refreshRate.getConfigId())) { ALOGV("Skipping config %d as it is not part of allowed configs", - refreshRate.configId.value()); + refreshRate.getConfigId().value()); return; } - setDesiredActiveConfig({refreshRate.configId, event}); + setDesiredActiveConfig({refreshRate.getConfigId(), event}); } void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId, @@ -2977,7 +2978,7 @@ void SurfaceFlinger::initScheduler(DisplayId primaryDisplayId) { // classes from EventThread, and there should be no run-time binder cost // anyway since there are no connected apps at this point. const nsecs_t vsyncPeriod = - mRefreshRateConfigs->getRefreshRateFromConfigId(currentConfig).vsyncPeriod; + mRefreshRateConfigs->getRefreshRateFromConfigId(currentConfig).getVsyncPeriod(); mScheduler->onConfigChanged(mAppConnectionHandle, primaryDisplayId.value, currentConfig, vsyncPeriod); } @@ -5959,7 +5960,8 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecsInternal( // that listeners that care about a change in allowed configs can get the notification. // Giving current ActiveConfig so that most other listeners would just drop the event const nsecs_t vsyncPeriod = - mRefreshRateConfigs->getRefreshRateFromConfigId(display->getActiveConfig()).vsyncPeriod; + mRefreshRateConfigs->getRefreshRateFromConfigId(display->getActiveConfig()) + .getVsyncPeriod(); mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value, display->getActiveConfig(), vsyncPeriod); @@ -5969,13 +5971,16 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecsInternal( // NOTE: Choose the default config ID, if Scheduler doesn't have one in mind. : mRefreshRateConfigs->getRefreshRateFromConfigId(currentPolicy.defaultConfig); ALOGV("trying to switch to Scheduler preferred config %d (%s)", - preferredRefreshRate.configId.value(), preferredRefreshRate.name.c_str()); + preferredRefreshRate.getConfigId().value(), preferredRefreshRate.getName().c_str()); - if (isDisplayConfigAllowed(preferredRefreshRate.configId)) { - ALOGV("switching to Scheduler preferred config %d", preferredRefreshRate.configId.value()); - setDesiredActiveConfig({preferredRefreshRate.configId, Scheduler::ConfigEvent::Changed}); + if (isDisplayConfigAllowed(preferredRefreshRate.getConfigId())) { + ALOGV("switching to Scheduler preferred config %d", + preferredRefreshRate.getConfigId().value()); + setDesiredActiveConfig( + {preferredRefreshRate.getConfigId(), Scheduler::ConfigEvent::Changed}); } else { - LOG_ALWAYS_FATAL("Desired config not allowed: %d", preferredRefreshRate.configId.value()); + LOG_ALWAYS_FATAL("Desired config not allowed: %d", + preferredRefreshRate.getConfigId().value()); } return NO_ERROR; diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index 7557faf8a9..71d17a9f80 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -63,14 +63,15 @@ protected: auto createLayer() { return sp(new mock::MockLayer(mFlinger.flinger())); } - RefreshRateConfigs mConfigs{{ - RefreshRateConfigs::InputConfig{HwcConfigIndexType(0), - HwcConfigGroupType(0), - LO_FPS_PERIOD}, - RefreshRateConfigs::InputConfig{HwcConfigIndexType(1), - HwcConfigGroupType(0), - HI_FPS_PERIOD}, - }, + Hwc2::mock::Display mDisplay; + RefreshRateConfigs mConfigs{{HWC2::Display::Config::Builder(mDisplay, 0) + .setVsyncPeriod(int32_t(LO_FPS_PERIOD)) + .setConfigGroup(0) + .build(), + HWC2::Display::Config::Builder(mDisplay, 1) + .setVsyncPeriod(int32_t(HI_FPS_PERIOD)) + .setConfigGroup(0) + .build()}, HwcConfigIndexType(0)}; TestableScheduler* const mScheduler{new TestableScheduler(mConfigs, false)}; TestableSurfaceFlinger mFlinger; diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp index 8559a5e7d7..71e37a8c98 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp @@ -72,14 +72,15 @@ protected: auto createLayer() { return sp(new mock::MockLayer(mFlinger.flinger())); } - RefreshRateConfigs mConfigs{{ - RefreshRateConfigs::InputConfig{HwcConfigIndexType(0), - HwcConfigGroupType(0), - LO_FPS_PERIOD}, - RefreshRateConfigs::InputConfig{HwcConfigIndexType(1), - HwcConfigGroupType(0), - HI_FPS_PERIOD}, - }, + Hwc2::mock::Display mDisplay; + RefreshRateConfigs mConfigs{{HWC2::Display::Config::Builder(mDisplay, 0) + .setVsyncPeriod(int32_t(LO_FPS_PERIOD)) + .setConfigGroup(0) + .build(), + HWC2::Display::Config::Builder(mDisplay, 1) + .setVsyncPeriod(int32_t(HI_FPS_PERIOD)) + .setConfigGroup(0) + .build()}, HwcConfigIndexType(0)}; TestableScheduler* const mScheduler{new TestableScheduler(mConfigs, true)}; TestableSurfaceFlinger mFlinger; diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp index ce41291813..1b8f11b7db 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -24,6 +24,7 @@ #include "../../Scheduler/RefreshRateConfigs.h" #include "DisplayHardware/HWC2.h" #include "Scheduler/RefreshRateConfigs.h" +#include "mock/DisplayHardware/MockDisplay.h" using namespace std::chrono_literals; using testing::_; @@ -37,24 +38,95 @@ using LayerRequirement = RefreshRateConfigs::LayerRequirement; class RefreshRateConfigsTest : public testing::Test { protected: + RefreshRateConfigsTest(); + ~RefreshRateConfigsTest(); + + // Test config IDs static inline const HwcConfigIndexType HWC_CONFIG_ID_60 = HwcConfigIndexType(0); - static inline const HwcConfigIndexType HWC_CONFIG_ID_72 = HwcConfigIndexType(1); - static inline const HwcConfigIndexType HWC_CONFIG_ID_90 = HwcConfigIndexType(2); + static inline const HwcConfigIndexType HWC_CONFIG_ID_90 = HwcConfigIndexType(1); + static inline const HwcConfigIndexType HWC_CONFIG_ID_72 = HwcConfigIndexType(2); static inline const HwcConfigIndexType HWC_CONFIG_ID_120 = HwcConfigIndexType(3); static inline const HwcConfigIndexType HWC_CONFIG_ID_30 = HwcConfigIndexType(4); - static inline const HwcConfigGroupType HWC_GROUP_ID_0 = HwcConfigGroupType(0); - static inline const HwcConfigGroupType HWC_GROUP_ID_1 = HwcConfigGroupType(1); - static constexpr auto VSYNC_30 = static_cast(1e9f / 30); - static constexpr auto VSYNC_60 = static_cast(1e9f / 60); - static constexpr auto VSYNC_72 = static_cast(1e9f / 72); - static constexpr auto VSYNC_90 = static_cast(1e9f / 90); - static constexpr auto VSYNC_120 = static_cast(1e9f / 120); - static constexpr int64_t VSYNC_60_POINT_4 = 16666665; - RefreshRateConfigsTest(); - ~RefreshRateConfigsTest(); + // Test configs + std::shared_ptr mConfig60 = + createConfig(HWC_CONFIG_ID_60, 0, static_cast(1e9f / 60)); + std::shared_ptr mConfig90 = + createConfig(HWC_CONFIG_ID_90, 0, static_cast(1e9f / 90)); + std::shared_ptr mConfig90DifferentGroup = + createConfig(HWC_CONFIG_ID_90, 1, static_cast(1e9f / 90)); + std::shared_ptr mConfig90DifferentResolution = + createConfig(HWC_CONFIG_ID_90, 0, static_cast(1e9f / 90), 111, 222); + std::shared_ptr mConfig72 = + createConfig(HWC_CONFIG_ID_72, 0, static_cast(1e9f / 72)); + std::shared_ptr mConfig72DifferentGroup = + createConfig(HWC_CONFIG_ID_72, 1, static_cast(1e9f / 72)); + std::shared_ptr mConfig120 = + createConfig(HWC_CONFIG_ID_120, 0, static_cast(1e9f / 120)); + std::shared_ptr mConfig120DifferentGroup = + createConfig(HWC_CONFIG_ID_120, 1, static_cast(1e9f / 120)); + std::shared_ptr mConfig30 = + createConfig(HWC_CONFIG_ID_30, 0, static_cast(1e9f / 30)); + + // Test device configurations + std::vector> m60OnlyConfigDevice = {mConfig60}; + std::vector> m60_90Device = {mConfig60, mConfig90}; + std::vector> m60_90DeviceWithDifferentGroups = + {mConfig60, mConfig90DifferentGroup}; + std::vector> m60_90DeviceWithDifferentResolutions = + {mConfig60, mConfig90DifferentResolution}; + std::vector> m60_72_90Device = {mConfig60, + mConfig90, + mConfig72}; + std::vector> m60_90_72_120Device = {mConfig60, + mConfig90, + mConfig72, + mConfig120}; + std::vector> m30_60_72_90_120Device = {mConfig60, + mConfig90, + mConfig72, + mConfig120, + mConfig30}; + std::vector> m30_60Device = + {mConfig60, mConfig90DifferentGroup, mConfig72DifferentGroup, mConfig120DifferentGroup, + mConfig30}; + std::vector> m30_60_72_90Device = + {mConfig60, mConfig90, mConfig72, mConfig120DifferentGroup, mConfig30}; + std::vector> m30_60_90Device = + {mConfig60, mConfig90, mConfig72DifferentGroup, mConfig120DifferentGroup, mConfig30}; + + // Expected RefreshRate objects + RefreshRate mExpected60Config = {HWC_CONFIG_ID_60, mConfig60, "60fps", 60, + RefreshRate::ConstructorTag(0)}; + RefreshRate mExpectedAlmost60Config = {HWC_CONFIG_ID_60, + createConfig(HWC_CONFIG_ID_60, 0, 16666665), "60fps", 60, + RefreshRate::ConstructorTag(0)}; + RefreshRate mExpected90Config = {HWC_CONFIG_ID_90, mConfig90, "90fps", 90, + RefreshRate::ConstructorTag(0)}; + RefreshRate mExpected90DifferentGroupConfig = {HWC_CONFIG_ID_90, mConfig90DifferentGroup, + "90fps", 90, RefreshRate::ConstructorTag(0)}; + RefreshRate mExpected90DifferentResolutionConfig = {HWC_CONFIG_ID_90, + mConfig90DifferentResolution, "90fps", 90, + RefreshRate::ConstructorTag(0)}; + RefreshRate mExpected72Config = {HWC_CONFIG_ID_72, mConfig72, "72fps", 72, + RefreshRate::ConstructorTag(0)}; + RefreshRate mExpected30Config = {HWC_CONFIG_ID_30, mConfig30, "30fps", 30, + RefreshRate::ConstructorTag(0)}; + RefreshRate mExpected120Config = {HWC_CONFIG_ID_120, mConfig120, "120fps", 120, + RefreshRate::ConstructorTag(0)}; + + Hwc2::mock::Display mDisplay; + +private: + std::shared_ptr createConfig(HwcConfigIndexType configId, + int32_t configGroup, + int64_t vsyncPeriod, + int32_t hight = -1, + int32_t width = -1); }; +using Builder = HWC2::Display::Config::Builder; + RefreshRateConfigsTest::RefreshRateConfigsTest() { const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); @@ -67,41 +139,45 @@ RefreshRateConfigsTest::~RefreshRateConfigsTest() { ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); } +std::shared_ptr RefreshRateConfigsTest::createConfig( + HwcConfigIndexType configId, int32_t configGroup, int64_t vsyncPeriod, int32_t hight, + int32_t width) { + return HWC2::Display::Config::Builder(mDisplay, hwc2_config_t(configId.value())) + .setVsyncPeriod(int32_t(vsyncPeriod)) + .setConfigGroup(configGroup) + .setHeight(hight) + .setWidth(width) + .build(); +} + namespace { /* ------------------------------------------------------------------------ * Test cases */ TEST_F(RefreshRateConfigsTest, oneDeviceConfig_SwitchingSupported) { - std::vector configs{ - {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}}}; auto refreshRateConfigs = - std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); + std::make_unique(m60OnlyConfigDevice, + /*currentConfigId=*/HWC_CONFIG_ID_60); } TEST_F(RefreshRateConfigsTest, invalidPolicy) { - std::vector configs{ - {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}}}; auto refreshRateConfigs = - std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); + std::make_unique(m60OnlyConfigDevice, + /*currentConfigId=*/HWC_CONFIG_ID_60); ASSERT_LT(refreshRateConfigs->setDisplayManagerPolicy({HwcConfigIndexType(10), 60, 60}), 0); ASSERT_LT(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, 20, 40}), 0); } TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap) { - std::vector configs{ - {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, - {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; auto refreshRateConfigs = - std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); + std::make_unique(m60_90Device, + /*currentConfigId=*/HWC_CONFIG_ID_60); const auto& minRate = refreshRateConfigs->getMinRefreshRate(); const auto& performanceRate = refreshRateConfigs->getMaxRefreshRate(); - RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; - ASSERT_EQ(expectedDefaultConfig, minRate); - RefreshRate expectedPerformanceConfig = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", - 90}; - ASSERT_EQ(expectedPerformanceConfig, performanceRate); + ASSERT_EQ(mExpected60Config, minRate); + ASSERT_EQ(mExpected90Config, performanceRate); const auto& minRateByPolicy = refreshRateConfigs->getMinRefreshRateByPolicy(); const auto& performanceRateByPolicy = refreshRateConfigs->getMaxRefreshRateByPolicy(); @@ -110,21 +186,43 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap) { } TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap_differentGroups) { - std::vector configs{ - {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, - {HWC_CONFIG_ID_90, HWC_GROUP_ID_1, VSYNC_90}}}; auto refreshRateConfigs = - std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); + std::make_unique(m60_90DeviceWithDifferentGroups, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + const auto& minRate = refreshRateConfigs->getMinRefreshRateByPolicy(); + const auto& performanceRate = refreshRateConfigs->getMaxRefreshRate(); + const auto& minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy(); + const auto& performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy(); + + ASSERT_EQ(mExpected60Config, minRate); + ASSERT_EQ(mExpected60Config, minRate60); + ASSERT_EQ(mExpected60Config, performanceRate60); + + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, 60, 90}), 0); + refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); + + const auto& minRate90 = refreshRateConfigs->getMinRefreshRateByPolicy(); + const auto& performanceRate90 = refreshRateConfigs->getMaxRefreshRateByPolicy(); + + ASSERT_EQ(mExpected90DifferentGroupConfig, performanceRate); + ASSERT_EQ(mExpected90DifferentGroupConfig, minRate90); + ASSERT_EQ(mExpected90DifferentGroupConfig, performanceRate90); +} + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap_differentResolutions) { + auto refreshRateConfigs = + std::make_unique(m60_90DeviceWithDifferentResolutions, + /*currentConfigId=*/HWC_CONFIG_ID_60); const auto& minRate = refreshRateConfigs->getMinRefreshRateByPolicy(); const auto& performanceRate = refreshRateConfigs->getMaxRefreshRate(); const auto& minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy(); const auto& performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy(); - RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; - ASSERT_EQ(expectedDefaultConfig, minRate); - ASSERT_EQ(expectedDefaultConfig, minRate60); - ASSERT_EQ(expectedDefaultConfig, performanceRate60); + ASSERT_EQ(mExpected60Config, minRate); + ASSERT_EQ(mExpected60Config, minRate60); + ASSERT_EQ(mExpected60Config, performanceRate60); ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, 60, 90}), 0); refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); @@ -132,202 +230,177 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap_differe const auto& minRate90 = refreshRateConfigs->getMinRefreshRateByPolicy(); const auto& performanceRate90 = refreshRateConfigs->getMaxRefreshRateByPolicy(); - RefreshRate expectedPerformanceConfig = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_1, "90fps", - 90}; - ASSERT_EQ(expectedPerformanceConfig, performanceRate); - ASSERT_EQ(expectedPerformanceConfig, minRate90); - ASSERT_EQ(expectedPerformanceConfig, performanceRate90); + ASSERT_EQ(mExpected90DifferentResolutionConfig, performanceRate); + ASSERT_EQ(mExpected90DifferentResolutionConfig, minRate90); + ASSERT_EQ(mExpected90DifferentResolutionConfig, performanceRate90); } TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_policyChange) { - std::vector configs{ - {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, - {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; auto refreshRateConfigs = - std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); + std::make_unique(m60_90Device, + /*currentConfigId=*/HWC_CONFIG_ID_60); auto& minRate = refreshRateConfigs->getMinRefreshRateByPolicy(); auto& performanceRate = refreshRateConfigs->getMaxRefreshRateByPolicy(); - RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; - ASSERT_EQ(expectedDefaultConfig, minRate); - RefreshRate expectedPerformanceConfig = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", - 90}; - ASSERT_EQ(expectedPerformanceConfig, performanceRate); + ASSERT_EQ(mExpected60Config, minRate); + ASSERT_EQ(mExpected90Config, performanceRate); ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, 60, 60}), 0); auto& minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy(); auto& performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy(); - ASSERT_EQ(expectedDefaultConfig, minRate60); - ASSERT_EQ(expectedDefaultConfig, performanceRate60); + ASSERT_EQ(mExpected60Config, minRate60); + ASSERT_EQ(mExpected60Config, performanceRate60); } TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getCurrentRefreshRate) { - std::vector configs{ - {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, - {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; auto refreshRateConfigs = - std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); + std::make_unique(m60_90Device, + /*currentConfigId=*/HWC_CONFIG_ID_60); { auto& current = refreshRateConfigs->getCurrentRefreshRate(); - EXPECT_EQ(current.configId, HWC_CONFIG_ID_60); + EXPECT_EQ(current.getConfigId(), HWC_CONFIG_ID_60); } refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); { auto& current = refreshRateConfigs->getCurrentRefreshRate(); - EXPECT_EQ(current.configId, HWC_CONFIG_ID_90); + EXPECT_EQ(current.getConfigId(), HWC_CONFIG_ID_90); } ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, 90, 90}), 0); { auto& current = refreshRateConfigs->getCurrentRefreshRate(); - EXPECT_EQ(current.configId, HWC_CONFIG_ID_90); + EXPECT_EQ(current.getConfigId(), HWC_CONFIG_ID_90); } } TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContent) { - std::vector configs{ - {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, - {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; auto refreshRateConfigs = - std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); - - RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; - RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + std::make_unique(m60_90Device, + /*currentConfigId=*/HWC_CONFIG_ID_60); const auto makeLayerRequirements = [](float refreshRate) -> std::vector { return {{"testLayer", LayerVoteType::Heuristic, refreshRate, 1.0f}}; }; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(90.0f))); - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(60.0f))); - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(45.0f))); - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(30.0f))); - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(24.0f))); ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, 60, 60}), 0); - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(90.0f))); - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(60.0f))); - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(45.0f))); - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(30.0f))); - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(24.0f))); ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, 90, 90}), 0); - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(90.0f))); - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(60.0f))); - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(45.0f))); - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(30.0f))); - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(24.0f))); ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, 0, 120}), 0); - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(90.0f))); - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(60.0f))); - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(45.0f))); - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(30.0f))); - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(24.0f))); } TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_noLayers) { bool ignored; - std::vector configs{ - {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, - {HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72}, - {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; - auto refreshRateConfigs = std::make_unique(configs, /*currentConfigId=*/ - HWC_CONFIG_ID_72); - - RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; - RefreshRate expected72Config = {HWC_CONFIG_ID_72, VSYNC_72, HWC_GROUP_ID_0, "72fps", 72}; + auto refreshRateConfigs = + std::make_unique(m60_72_90Device, /*currentConfigId=*/ + HWC_CONFIG_ID_72); // If there are not layers, there is not content detection, so return the current // refresh rate. auto layers = std::vector{}; - EXPECT_EQ(expected72Config, + EXPECT_EQ(mExpected72Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); // Current refresh rate can always be changed. refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_60); - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); } TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_60_90) { bool ignored; - std::vector configs{ - {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, - {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; auto refreshRateConfigs = - std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); - - RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; - RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + std::make_unique(m60_90Device, + /*currentConfigId=*/HWC_CONFIG_ID_60); auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; auto& lr = layers[0]; lr.vote = LayerVoteType::Min; lr.name = "Min"; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.vote = LayerVoteType::Max; lr.name = "Max"; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 90.0f; lr.vote = LayerVoteType::Heuristic; lr.name = "90Hz Heuristic"; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 60.0f; lr.name = "60Hz Heuristic"; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 45.0f; lr.name = "45Hz Heuristic"; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 30.0f; lr.name = "30Hz Heuristic"; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 24.0f; lr.name = "24Hz Heuristic"; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); @@ -335,186 +408,168 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_60_90) { ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, 60, 60}), 0); lr.vote = LayerVoteType::Min; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.vote = LayerVoteType::Max; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 90.0f; lr.vote = LayerVoteType::Heuristic; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 60.0f; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 45.0f; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 30.0f; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 24.0f; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, 90, 90}), 0); lr.vote = LayerVoteType::Min; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.vote = LayerVoteType::Max; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 90.0f; lr.vote = LayerVoteType::Heuristic; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 60.0f; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 45.0f; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 30.0f; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 24.0f; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, 0, 120}), 0); lr.vote = LayerVoteType::Min; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.vote = LayerVoteType::Max; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 90.0f; lr.vote = LayerVoteType::Heuristic; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 60.0f; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 45.0f; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 30.0f; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 24.0f; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); } TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_60_72_90) { bool ignored; - std::vector configs{ - {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, - {HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72}, - {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; auto refreshRateConfigs = - std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); - - RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; - RefreshRate expected72Config = {HWC_CONFIG_ID_72, VSYNC_72, HWC_GROUP_ID_0, "72fps", 70}; - RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + std::make_unique(m60_72_90Device, + /*currentConfigId=*/HWC_CONFIG_ID_60); auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; auto& lr = layers[0]; lr.vote = LayerVoteType::Min; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.vote = LayerVoteType::Max; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 90.0f; lr.vote = LayerVoteType::Heuristic; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 60.0f; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 45.0f; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 30.0f; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 24.0f; - EXPECT_EQ(expected72Config, + EXPECT_EQ(mExpected72Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); } TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_72_90_120) { bool ignored; - std::vector configs{ - {{HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30}, - {HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, - {HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72}, - {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}, - {HWC_CONFIG_ID_120, HWC_GROUP_ID_0, VSYNC_120}}}; auto refreshRateConfigs = - std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); - - RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30}; - RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; - RefreshRate expected72Config = {HWC_CONFIG_ID_72, VSYNC_72, HWC_GROUP_ID_0, "72fps", 70}; - RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; - RefreshRate expected120Config = {HWC_CONFIG_ID_120, VSYNC_120, HWC_GROUP_ID_0, "120fps", 120}; + std::make_unique(m30_60_72_90_120Device, + /*currentConfigId=*/HWC_CONFIG_ID_60); auto layers = std::vector{LayerRequirement{.weight = 1.0f}, LayerRequirement{.weight = 1.0f}}; @@ -525,7 +580,7 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_72_90_120) { lr1.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 60.0f; lr2.vote = LayerVoteType::Heuristic; - EXPECT_EQ(expected120Config, + EXPECT_EQ(mExpected120Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); @@ -533,7 +588,7 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_72_90_120) { lr1.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 48.0f; lr2.vote = LayerVoteType::Heuristic; - EXPECT_EQ(expected72Config, + EXPECT_EQ(mExpected72Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); @@ -541,27 +596,16 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_72_90_120) { lr1.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 48.0f; lr2.vote = LayerVoteType::Heuristic; - EXPECT_EQ(expected72Config, + EXPECT_EQ(mExpected72Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); } TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_90_120_DifferentTypes) { bool ignored; - std::vector configs{ - {{HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30}, - {HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, - {HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72}, - {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}, - {HWC_CONFIG_ID_120, HWC_GROUP_ID_0, VSYNC_120}}}; auto refreshRateConfigs = - std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); - - RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30}; - RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; - RefreshRate expected72Config = {HWC_CONFIG_ID_72, VSYNC_72, HWC_GROUP_ID_0, "72fps", 72}; - RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; - RefreshRate expected120Config = {HWC_CONFIG_ID_120, VSYNC_120, HWC_GROUP_ID_0, "120fps", 120}; + std::make_unique(m30_60_72_90_120Device, + /*currentConfigId=*/HWC_CONFIG_ID_60); auto layers = std::vector{LayerRequirement{.weight = 1.0f}, LayerRequirement{.weight = 1.0f}}; @@ -574,7 +618,7 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_90_120_Different lr2.desiredRefreshRate = 60.0f; lr2.vote = LayerVoteType::Heuristic; lr2.name = "60Hz Heuristic"; - EXPECT_EQ(expected120Config, + EXPECT_EQ(mExpected120Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); @@ -584,7 +628,7 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_90_120_Different lr2.desiredRefreshRate = 60.0f; lr2.vote = LayerVoteType::Heuristic; lr2.name = "60Hz Heuristic"; - EXPECT_EQ(expected120Config, + EXPECT_EQ(mExpected120Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); @@ -594,7 +638,7 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_90_120_Different lr2.desiredRefreshRate = 60.0f; lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "60Hz ExplicitDefault"; - EXPECT_EQ(expected120Config, + EXPECT_EQ(mExpected120Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); @@ -604,7 +648,7 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_90_120_Different lr2.desiredRefreshRate = 90.0f; lr2.vote = LayerVoteType::Heuristic; lr2.name = "90Hz Heuristic"; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); @@ -614,7 +658,7 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_90_120_Different lr2.desiredRefreshRate = 90.0f; lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "90Hz Heuristic"; - EXPECT_EQ(expected72Config, + EXPECT_EQ(mExpected72Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); @@ -624,7 +668,7 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_90_120_Different lr2.desiredRefreshRate = 90.0f; lr2.vote = LayerVoteType::Heuristic; lr2.name = "90Hz Heuristic"; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); @@ -634,7 +678,7 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_90_120_Different lr2.desiredRefreshRate = 90.0f; lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "90Hz ExplicitDefault"; - EXPECT_EQ(expected72Config, + EXPECT_EQ(mExpected72Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); @@ -644,7 +688,7 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_90_120_Different lr2.desiredRefreshRate = 90.0f; lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "90Hz ExplicitDefault"; - EXPECT_EQ(expected72Config, + EXPECT_EQ(mExpected72Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); @@ -654,158 +698,137 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_90_120_Different lr2.desiredRefreshRate = 90.0f; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.name = "90Hz ExplicitExactOrMultiple"; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); } TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60) { bool ignored; - std::vector configs{ - {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, - {HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30}}}; auto refreshRateConfigs = - std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); - - RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; - RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30}; + std::make_unique(m30_60Device, + /*currentConfigId=*/HWC_CONFIG_ID_60); auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; auto& lr = layers[0]; lr.vote = LayerVoteType::Min; - EXPECT_EQ(expected30Config, + EXPECT_EQ(mExpected30Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.vote = LayerVoteType::Max; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 90.0f; lr.vote = LayerVoteType::Heuristic; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 60.0f; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 45.0f; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 30.0f; - EXPECT_EQ(expected30Config, + EXPECT_EQ(mExpected30Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 24.0f; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); } TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_72_90) { bool ignored; - std::vector configs{ - {{HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30}, - {HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, - {HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72}, - {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; auto refreshRateConfigs = - std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); - - RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30}; - RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; - RefreshRate expected72Config = {HWC_CONFIG_ID_72, VSYNC_72, HWC_GROUP_ID_0, "72fps", 70}; - RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + std::make_unique(m30_60_72_90Device, + /*currentConfigId=*/HWC_CONFIG_ID_60); auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; auto& lr = layers[0]; lr.vote = LayerVoteType::Min; lr.name = "Min"; - EXPECT_EQ(expected30Config, + EXPECT_EQ(mExpected30Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.vote = LayerVoteType::Max; lr.name = "Max"; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 90.0f; lr.vote = LayerVoteType::Heuristic; lr.name = "90Hz Heuristic"; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr.desiredRefreshRate = 60.0f; lr.name = "60Hz Heuristic"; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true, &ignored)); lr.desiredRefreshRate = 45.0f; lr.name = "45Hz Heuristic"; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true, &ignored)); lr.desiredRefreshRate = 30.0f; lr.name = "30Hz Heuristic"; - EXPECT_EQ(expected30Config, + EXPECT_EQ(mExpected30Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true, &ignored)); lr.desiredRefreshRate = 24.0f; lr.name = "24Hz Heuristic"; - EXPECT_EQ(expected72Config, + EXPECT_EQ(mExpected72Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true, &ignored)); lr.desiredRefreshRate = 24.0f; lr.vote = LayerVoteType::ExplicitExactOrMultiple; lr.name = "24Hz ExplicitExactOrMultiple"; - EXPECT_EQ(expected72Config, + EXPECT_EQ(mExpected72Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true, &ignored)); } TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_PriorityTest) { bool ignored; - std::vector configs{ - {{HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30}, - {HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, - {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; auto refreshRateConfigs = - std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); - - RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30}; - RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; - RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + std::make_unique(m30_60_90Device, + /*currentConfigId=*/HWC_CONFIG_ID_60); auto layers = std::vector{LayerRequirement{.weight = 1.0f}, LayerRequirement{.weight = 1.0f}}; @@ -814,35 +837,35 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_PriorityTest) { lr1.vote = LayerVoteType::Min; lr2.vote = LayerVoteType::Max; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr1.vote = LayerVoteType::Min; lr2.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 24.0f; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr1.vote = LayerVoteType::Min; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 24.0f; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr1.vote = LayerVoteType::Max; lr2.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 60.0f; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); lr1.vote = LayerVoteType::Max; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 60.0f; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); @@ -850,7 +873,7 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_PriorityTest) { lr1.desiredRefreshRate = 15.0f; lr2.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 45.0f; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); @@ -858,22 +881,16 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_PriorityTest) { lr1.desiredRefreshRate = 30.0f; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 45.0f; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); } TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_24FpsVideo) { bool ignored; - std::vector configs{ - {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, - {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; auto refreshRateConfigs = - std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); - - RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30}; - RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; - RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + std::make_unique(m60_90Device, + /*currentConfigId=*/HWC_CONFIG_ID_60); auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; auto& lr = layers[0]; @@ -884,20 +901,15 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_24FpsVideo) { const auto& refreshRate = refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored); - printf("%.2fHz chooses %s\n", fps, refreshRate.name.c_str()); - EXPECT_EQ(expected60Config, refreshRate); + printf("%.2fHz chooses %s\n", fps, refreshRate.getName().c_str()); + EXPECT_EQ(mExpected60Config, refreshRate); } } TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContent_Explicit) { - std::vector configs{ - {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, - {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; auto refreshRateConfigs = - std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); - - RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; - RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + std::make_unique(m60_90Device, + /*currentConfigId=*/HWC_CONFIG_ID_60); auto layers = std::vector{LayerRequirement{.weight = 1.0f}, LayerRequirement{.weight = 1.0f}}; @@ -908,25 +920,20 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContent_Explici lr1.desiredRefreshRate = 60.0f; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 90.0f; - EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(layers)); + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContent(layers)); lr1.vote = LayerVoteType::Heuristic; lr1.desiredRefreshRate = 90.0f; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 60.0f; - EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(layers)); + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContent(layers)); } TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_Explicit) { bool ignored; - std::vector configs{ - {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, - {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; auto refreshRateConfigs = - std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); - - RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; - RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + std::make_unique(m60_90Device, + /*currentConfigId=*/HWC_CONFIG_ID_60); auto layers = std::vector{LayerRequirement{.weight = 1.0f}, LayerRequirement{.weight = 1.0f}}; @@ -937,7 +944,7 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_Expli lr1.desiredRefreshRate = 60.0f; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 90.0f; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); @@ -945,7 +952,7 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_Expli lr1.desiredRefreshRate = 90.0f; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 60.0f; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); @@ -953,32 +960,24 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_Expli lr1.desiredRefreshRate = 90.0f; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 60.0f; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); } TEST_F(RefreshRateConfigsTest, testInPolicy) { - RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60_POINT_4, HWC_GROUP_ID_0, - "60fps", 60}; - ASSERT_TRUE(expectedDefaultConfig.inPolicy(60.000004f, 60.000004f)); - ASSERT_TRUE(expectedDefaultConfig.inPolicy(59.0f, 60.1f)); - ASSERT_FALSE(expectedDefaultConfig.inPolicy(75.0f, 90.0f)); - ASSERT_FALSE(expectedDefaultConfig.inPolicy(60.0011f, 90.0f)); - ASSERT_FALSE(expectedDefaultConfig.inPolicy(50.0f, 59.998f)); + ASSERT_TRUE(mExpectedAlmost60Config.inPolicy(60.000004f, 60.000004f)); + ASSERT_TRUE(mExpectedAlmost60Config.inPolicy(59.0f, 60.1f)); + ASSERT_FALSE(mExpectedAlmost60Config.inPolicy(75.0f, 90.0f)); + ASSERT_FALSE(mExpectedAlmost60Config.inPolicy(60.0011f, 90.0f)); + ASSERT_FALSE(mExpectedAlmost60Config.inPolicy(50.0f, 59.998f)); } TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_75HzContent) { bool ignored; - std::vector configs{ - {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, - {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; auto refreshRateConfigs = - std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); - - RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30}; - RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; - RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + std::make_unique(m60_90Device, + /*currentConfigId=*/HWC_CONFIG_ID_60); auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; auto& lr = layers[0]; @@ -989,21 +988,16 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_75HzContent) { const auto& refreshRate = refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored); - printf("%.2fHz chooses %s\n", fps, refreshRate.name.c_str()); - EXPECT_EQ(expected90Config, refreshRate); + printf("%.2fHz chooses %s\n", fps, refreshRate.getName().c_str()); + EXPECT_EQ(mExpected90Config, refreshRate); } } TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_Multiples) { bool ignored; - std::vector configs{ - {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, - {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; auto refreshRateConfigs = - std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); - - RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; - RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + std::make_unique(m60_90Device, + /*currentConfigId=*/HWC_CONFIG_ID_60); auto layers = std::vector{LayerRequirement{.weight = 1.0f}, LayerRequirement{.weight = 1.0f}}; @@ -1016,7 +1010,7 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_Multiples) { lr2.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 90.0f; lr2.name = "90Hz Heuristic"; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); @@ -1026,7 +1020,7 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_Multiples) { lr2.vote = LayerVoteType::ExplicitDefault; lr2.desiredRefreshRate = 90.0f; lr2.name = "90Hz ExplicitDefault"; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); @@ -1035,7 +1029,7 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_Multiples) { lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Max; lr2.name = "Max"; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); @@ -1045,7 +1039,7 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_Multiples) { lr2.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 90.0f; lr2.name = "90Hz Heuristic"; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); @@ -1054,21 +1048,16 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_Multiples) { lr1.name = "30Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Max; lr2.name = "Max"; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, &ignored)); } TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) { bool ignored; - std::vector configs{ - {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, - {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; auto refreshRateConfigs = - std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); - - RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; - RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + std::make_unique(m60_90Device, + /*currentConfigId=*/HWC_CONFIG_ID_60); auto layers = std::vector{LayerRequirement{.weight = 1.0f}, LayerRequirement{.weight = 1.0f}}; @@ -1080,7 +1069,7 @@ TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) { lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::NoVote; lr2.name = "NoVote"; - EXPECT_EQ(expected60Config, + EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, false, &ignored)); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -1088,7 +1077,7 @@ TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) { lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::NoVote; lr2.name = "NoVote"; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, true, &ignored)); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -1096,7 +1085,7 @@ TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) { lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Max; lr2.name = "Max"; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, true, &ignored)); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -1104,7 +1093,7 @@ TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) { lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Max; lr2.name = "Max"; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, false, &ignored)); // The other layer starts to provide buffers @@ -1114,17 +1103,15 @@ TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) { lr2.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 90.0f; lr2.name = "90Hz Heuristic"; - EXPECT_EQ(expected90Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, false, &ignored)); } TEST_F(RefreshRateConfigsTest, touchConsidered) { bool touchConsidered; - std::vector configs{ - {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, - {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; auto refreshRateConfigs = - std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); + std::make_unique(m60_90Device, + /*currentConfigId=*/HWC_CONFIG_ID_60); refreshRateConfigs->getRefreshRateForContentV2({}, false, &touchConsidered); EXPECT_EQ(false, touchConsidered); @@ -1172,14 +1159,9 @@ TEST_F(RefreshRateConfigsTest, touchConsidered) { TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_ExplicitDefault) { bool ignored; - std::vector configs{ - {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, - {HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72}, - {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}, - {HWC_CONFIG_ID_120, HWC_GROUP_ID_0, VSYNC_120}}}; - - auto refreshRateConfigs = std::make_unique(configs, /*currentConfigId=*/ - HWC_CONFIG_ID_60); + auto refreshRateConfigs = + std::make_unique(m60_90_72_120Device, /*currentConfigId=*/ + HWC_CONFIG_ID_60); auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; auto& lr = layers[0]; @@ -1213,17 +1195,15 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_ExplicitDefault) { const auto& refreshRate = refreshRateConfigs->getRefreshRateForContentV2(layers, false, &ignored); - EXPECT_FLOAT_EQ(refreshRate.fps, test.second) + EXPECT_FLOAT_EQ(refreshRate.getFps(), test.second) << "Expecting " << test.first << "fps => " << test.second << "Hz"; } } TEST_F(RefreshRateConfigsTest, groupSwitching) { - std::vector configs{ - {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, - {HWC_CONFIG_ID_90, HWC_GROUP_ID_1, VSYNC_90}}}; auto refreshRateConfigs = - std::make_unique(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); + std::make_unique(m60_90DeviceWithDifferentGroups, + /*currentConfigId=*/HWC_CONFIG_ID_60); auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; auto& layer = layers[0]; @@ -1234,7 +1214,7 @@ TEST_F(RefreshRateConfigsTest, groupSwitching) { bool touchConsidered; ASSERT_EQ(HWC_CONFIG_ID_60, refreshRateConfigs->getRefreshRateForContentV2(layers, false, &touchConsidered) - .configId); + .getConfigId()); RefreshRateConfigs::Policy policy; policy.defaultConfig = refreshRateConfigs->getCurrentPolicy().defaultConfig; @@ -1242,7 +1222,7 @@ TEST_F(RefreshRateConfigsTest, groupSwitching) { ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy(policy), 0); ASSERT_EQ(HWC_CONFIG_ID_90, refreshRateConfigs->getRefreshRateForContentV2(layers, false, &touchConsidered) - .configId); + .getConfigId()); } } // namespace diff --git a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp index 18d6bd21e6..038e6e6b92 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp @@ -26,6 +26,7 @@ #include #include "Scheduler/RefreshRateStats.h" +#include "mock/DisplayHardware/MockDisplay.h" #include "mock/MockTimeStats.h" using namespace std::chrono_literals; @@ -39,14 +40,14 @@ class RefreshRateStatsTest : public testing::Test { protected: static inline const auto CONFIG_ID_0 = HwcConfigIndexType(0); static inline const auto CONFIG_ID_1 = HwcConfigIndexType(1); - static inline const auto CONFIG_GROUP_0 = HwcConfigGroupType(0); + static inline const auto CONFIG_GROUP_0 = 0; static constexpr int64_t VSYNC_90 = 11111111; static constexpr int64_t VSYNC_60 = 16666667; RefreshRateStatsTest(); ~RefreshRateStatsTest(); - void init(const std::vector& configs) { + void init(const std::vector>& configs) { mRefreshRateConfigs = std::make_unique(configs, /*currentConfig=*/CONFIG_ID_0); mRefreshRateStats = @@ -55,9 +56,14 @@ protected: /*currentPowerMode=*/HWC_POWER_MODE_OFF); } + Hwc2::mock::Display mDisplay; mock::TimeStats mTimeStats; std::unique_ptr mRefreshRateConfigs; std::unique_ptr mRefreshRateStats; + + std::shared_ptr createConfig(HwcConfigIndexType configId, + int32_t configGroup, + int64_t vsyncPeriod); }; RefreshRateStatsTest::RefreshRateStatsTest() { @@ -72,12 +78,20 @@ RefreshRateStatsTest::~RefreshRateStatsTest() { ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); } +std::shared_ptr RefreshRateStatsTest::createConfig( + HwcConfigIndexType configId, int32_t configGroup, int64_t vsyncPeriod) { + return HWC2::Display::Config::Builder(mDisplay, hwc2_config_t(configId.value())) + .setVsyncPeriod(int32_t(vsyncPeriod)) + .setConfigGroup(configGroup) + .build(); +} + namespace { /* ------------------------------------------------------------------------ * Test cases */ TEST_F(RefreshRateStatsTest, oneConfigTest) { - init({{{CONFIG_ID_0, CONFIG_GROUP_0, VSYNC_90}}}); + init({createConfig(CONFIG_ID_0, CONFIG_GROUP_0, VSYNC_90)}); EXPECT_CALL(mTimeStats, recordRefreshRate(0, _)).Times(AtLeast(1)); EXPECT_CALL(mTimeStats, recordRefreshRate(90, _)).Times(AtLeast(1)); @@ -123,7 +137,8 @@ TEST_F(RefreshRateStatsTest, oneConfigTest) { } TEST_F(RefreshRateStatsTest, twoConfigsTest) { - init({{{CONFIG_ID_0, CONFIG_GROUP_0, VSYNC_90}, {CONFIG_ID_1, CONFIG_GROUP_0, VSYNC_60}}}); + init({createConfig(CONFIG_ID_0, CONFIG_GROUP_0, VSYNC_90), + createConfig(CONFIG_ID_1, CONFIG_GROUP_0, VSYNC_60)}); EXPECT_CALL(mTimeStats, recordRefreshRate(0, _)).Times(AtLeast(1)); EXPECT_CALL(mTimeStats, recordRefreshRate(60, _)).Times(AtLeast(1)); diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp index 5db11ec5c1..1aa7320a8a 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp @@ -31,6 +31,7 @@ #include "Scheduler/EventThread.h" #include "Scheduler/RefreshRateConfigs.h" #include "TestableScheduler.h" +#include "mock/DisplayHardware/MockDisplay.h" #include "mock/MockEventThread.h" using testing::_; @@ -63,6 +64,7 @@ protected: Scheduler::ConnectionHandle mConnectionHandle; mock::EventThread* mEventThread; sp mEventThreadConnection; + Hwc2::mock::Display mDisplay; }; SchedulerTest::SchedulerTest() { @@ -70,8 +72,11 @@ SchedulerTest::SchedulerTest() { ::testing::UnitTest::GetInstance()->current_test_info(); ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); - std::vector configs{ - {{HwcConfigIndexType(0), HwcConfigGroupType(0), 16666667}}}; + std::vector> configs{ + HWC2::Display::Config::Builder(mDisplay, 0) + .setVsyncPeriod(int32_t(16666667)) + .setConfigGroup(0) + .build()}; mRefreshRateConfigs = std::make_unique< scheduler::RefreshRateConfigs>(configs, /*currentConfig=*/HwcConfigIndexType(0)); diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 058c5ccf9d..6995ee0097 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -39,6 +39,7 @@ #include "SurfaceFlingerDefaultFactory.h" #include "SurfaceInterceptor.h" #include "TestableScheduler.h" +#include "mock/DisplayHardware/MockDisplay.h" namespace android { @@ -198,8 +199,12 @@ public: std::unique_ptr appEventThread, std::unique_ptr sfEventThread, bool useContentDetectionV2 = false) { - std::vector configs{ - {{HwcConfigIndexType(0), HwcConfigGroupType(0), 16666667}}}; + std::vector> configs{ + HWC2::Display::Config::Builder(mDisplay, 0) + .setVsyncPeriod(int32_t(16666667)) + .setConfigGroup(0) + .build()}; + mFlinger->mRefreshRateConfigs = std::make_unique< scheduler::RefreshRateConfigs>(configs, /*currentConfig=*/HwcConfigIndexType(0)); mFlinger->mRefreshRateStats = std::make_unique< @@ -648,6 +653,7 @@ public: surfaceflinger::test::Factory mFactory; sp mFlinger = new SurfaceFlinger(mFactory, SurfaceFlinger::SkipInitialization); TestableScheduler* mScheduler = nullptr; + Hwc2::mock::Display mDisplay; }; } // namespace android diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h index 5cbba81020..2a310786fa 100644 --- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h +++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h @@ -45,6 +45,7 @@ using android::hardware::graphics::composer::V2_4::IComposerClient; class Composer : public Hwc2::Composer { public: + using Display = android::hardware::graphics::composer::V2_1::Display; Composer(); ~Composer() override; diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.h index 6dc28bcb73..3968035893 100644 --- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.h +++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.h @@ -29,6 +29,9 @@ namespace mock { class Display : public HWC2::Display { public: + using Error = ::Error; + using Layer = ::Layer; + Display(); ~Display(); @@ -80,6 +83,16 @@ public: MOCK_METHOD4(presentOrValidate, Error(uint32_t*, uint32_t*, android::sp*, uint32_t*)); MOCK_CONST_METHOD1(setDisplayBrightness, Error(float)); + MOCK_CONST_METHOD1(getDisplayVsyncPeriod, Error(nsecs_t*)); + MOCK_METHOD3(setActiveConfigWithConstraints, + Error(const std::shared_ptr&, + const HWC2::VsyncPeriodChangeConstraints&, + HWC2::VsyncPeriodChangeTimeline*)); + MOCK_CONST_METHOD1(setAutoLowLatencyMode, Error(bool on)); + MOCK_CONST_METHOD1(getSupportedContentTypes, Error(std::vector*)); + MOCK_CONST_METHOD1(setContentType, Error(HWC2::ContentType)); + MOCK_CONST_METHOD1(getConnectionType, Error(android::DisplayConnectionType*)); + MOCK_CONST_METHOD0(isVsyncPeriodSwitchSupported, bool()); }; } // namespace mock -- cgit v1.2.3-59-g8ed1b From ddb9cc9cffceea1e99a27b1300734ea8ef1f97e7 Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Wed, 22 Apr 2020 19:47:07 -0700 Subject: SurfaceFlinger: fix buffer usage bits of RefreshRateOverlay Set the correct gralloc bits on the buffer, and clear it before drawing the numbers. Bug: 154773593 Test: Enable refresh rate overlay on emulation Change-Id: I977507a80955fadeae7ad7504d5a4dfef5d0a693 --- services/surfaceflinger/RefreshRateOverlay.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 0a0f2f132e..2e7fbc1a78 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -116,9 +116,13 @@ sp RefreshRateOverlay::SevenSegmentDrawer::drawNumber(int number, sp buffer = new GraphicBuffer(BUFFER_WIDTH, BUFFER_HEIGHT, HAL_PIXEL_FORMAT_RGBA_8888, 1, - GRALLOC_USAGE_SW_WRITE_RARELY, "RefreshRateOverlayBuffer"); + GRALLOC_USAGE_SW_WRITE_RARELY | GRALLOC_USAGE_HW_COMPOSER | + GRALLOC_USAGE_HW_TEXTURE, + "RefreshRateOverlayBuffer"); uint8_t* pixels; buffer->lock(GRALLOC_USAGE_SW_WRITE_RARELY, reinterpret_cast(&pixels)); + // Clear buffer content + drawRect(Rect(BUFFER_WIDTH, BUFFER_HEIGHT), half4(0), buffer, pixels); int left = 0; if (hundreds != 0) { drawDigit(hundreds, left, color, buffer, pixels); -- cgit v1.2.3-59-g8ed1b From a7e92558ee6b21be51ec2b47854639c990ec1cc2 Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Thu, 7 May 2020 15:03:45 -0700 Subject: SurfaceFlinger: move refresh rate overlay slightly down Test: Enable overlay from developer option Bug: 156026107 Change-Id: I771b7c0383cc4d5b54ba3bd4b03931f911c6e79c --- services/surfaceflinger/RefreshRateOverlay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 2e7fbc1a78..436a83b3a2 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -207,7 +207,7 @@ void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { } const int32_t left = display->getWidth() / 32; - const int32_t top = display->getHeight() / 32; + const int32_t top = display->getHeight() / 16; const int32_t right = left + display->getWidth() / 8; const int32_t buttom = top + display->getHeight() / 32; -- cgit v1.2.3-59-g8ed1b From 20134646cb4f0795c89baa64048994f148bb00ba Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Mon, 20 Apr 2020 22:36:44 -0700 Subject: SF: Fix thread safety for RefreshRateOverlay Lock mStateLock when reading/writing the pointer, and writing layer state. Destroy the layer on the main thread. Notify overlay when viewport changes to avoid display lookup on refresh rate change. Bug: 123715322 Test: Toggle overlay on flame. Change-Id: I019c5cd49c94182f2c4364b0299fa3aa7783bd15 --- services/surfaceflinger/RefreshRateOverlay.cpp | 20 +++--- services/surfaceflinger/RefreshRateOverlay.h | 26 +++++-- services/surfaceflinger/SurfaceFlinger.cpp | 94 +++++++++++++++----------- services/surfaceflinger/SurfaceFlinger.h | 15 ++-- 4 files changed, 95 insertions(+), 60 deletions(-) (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 436a83b3a2..f602412930 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -200,26 +200,22 @@ void RefreshRateOverlay::primeCache() { } } -void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { - const auto display = mFlinger.getDefaultDisplayDeviceLocked(); - if (!display) { - return; - } +void RefreshRateOverlay::setViewport(ui::Size viewport) { + Rect frame(viewport.width >> 3, viewport.height >> 5); + frame.offsetBy(viewport.width >> 5, viewport.height >> 4); + mLayer->setFrame(frame); - const int32_t left = display->getWidth() / 32; - const int32_t top = display->getHeight() / 16; - const int32_t right = left + display->getWidth() / 8; - const int32_t buttom = top + display->getHeight() / 32; + mFlinger.mTransactionFlags.fetch_or(eTransactionMask); +} +void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { auto buffer = mBufferCache[refreshRate.getFps()]; mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}); - mLayer->setFrame(Rect(left, top, right, buttom)); - mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } -}; // namespace android +} // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/RefreshRateOverlay.h b/services/surfaceflinger/RefreshRateOverlay.h index 6d34df220c..35c80201d7 100644 --- a/services/surfaceflinger/RefreshRateOverlay.h +++ b/services/surfaceflinger/RefreshRateOverlay.h @@ -13,19 +13,35 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #pragma once -#include "SurfaceFlinger.h" +#include + +#include +#include +#include +#include + +#include "Scheduler/RefreshRateConfigs.h" namespace android { +class Client; +class GraphicBuffer; +class IBinder; +class IGraphicBufferProducer; +class Layer; +class SurfaceFlinger; + using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate; class RefreshRateOverlay { public: - RefreshRateOverlay(SurfaceFlinger& flinger); + explicit RefreshRateOverlay(SurfaceFlinger&); - void changeRefreshRate(const RefreshRate& refreshRate); + void setViewport(ui::Size); + void changeRefreshRate(const RefreshRate&); private: class SevenSegmentDrawer { @@ -56,7 +72,7 @@ private: void primeCache(); SurfaceFlinger& mFlinger; - sp mClient; + const sp mClient; sp mLayer; sp mIBinder; sp mGbp; @@ -68,4 +84,4 @@ private: const half3 HIGH_FPS_COLOR = half3(0.0f, 1.0f, 0.0f); }; -}; // namespace android +} // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 87e73a0e7a..bc878871a0 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -582,14 +582,13 @@ void SurfaceFlinger::bootFinished() LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC))); - static_cast(schedule([this]() NO_THREAD_SAFETY_ANALYSIS { + static_cast(schedule([this] { readPersistentProperties(); mPowerAdvisor.onBootFinished(); mBootStage = BootStage::FINISHED; if (property_get_bool("sf.debug.show_refresh_rate_overlay", false)) { - mRefreshRateOverlay = std::make_unique(*this); - mRefreshRateOverlay->changeRefreshRate(mRefreshRateConfigs->getCurrentRefreshRate()); + enableRefreshRateOverlay(true); } })); } @@ -934,9 +933,8 @@ int SurfaceFlinger::getActiveConfig(const sp& displayToken) { } if (isPrimary) { - std::lock_guard lock(mActiveConfigLock); - if (mDesiredActiveConfigChanged) { - return mDesiredActiveConfig.configId.value(); + if (const auto config = getDesiredActiveConfig()) { + return config->configId.value(); } } @@ -1063,14 +1061,7 @@ void SurfaceFlinger::performSetActiveConfig() { ATRACE_CALL(); ALOGV("performSetActiveConfig"); // Store the local variable to release the lock. - const auto desiredActiveConfig = [&]() -> std::optional { - std::lock_guard lock(mActiveConfigLock); - if (mDesiredActiveConfigChanged) { - return mDesiredActiveConfig; - } - return std::nullopt; - }(); - + const auto desiredActiveConfig = getDesiredActiveConfig(); if (!desiredActiveConfig) { // No desired active config pending to be applied return; @@ -1605,7 +1596,7 @@ void SurfaceFlinger::changeRefreshRateLocked(const RefreshRate& refreshRate, } void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hal::HWDisplayId hwcDisplayId, - hal::Connection connection) { + hal::Connection connection) NO_THREAD_SAFETY_ANALYSIS { ALOGV("%s(%d, %" PRIu64 ", %s)", __FUNCTION__, sequenceId, hwcDisplayId, connection == hal::Connection::CONNECTED ? "connected" : "disconnected"); @@ -2679,9 +2670,14 @@ void SurfaceFlinger::processDisplayChanged(const wp& displayToken, if (currentState.width != drawingState.width || currentState.height != drawingState.height) { display->setDisplaySize(currentState.width, currentState.height); + if (display->isPrimary()) { mScheduler->onPrimaryDisplayAreaChanged(currentState.width * currentState.height); } + + if (mRefreshRateOverlay) { + mRefreshRateOverlay->setViewport(display->getSize()); + } } } } @@ -5229,15 +5225,15 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r return NO_ERROR; } case 1034: { - n = data.readInt32(); - if (n == 1 && !mRefreshRateOverlay) { - mRefreshRateOverlay = std::make_unique(*this); - auto& current = mRefreshRateConfigs->getCurrentRefreshRate(); - mRefreshRateOverlay->changeRefreshRate(current); - } else if (n == 0) { - mRefreshRateOverlay.reset(); - } else { - reply->writeBool(mRefreshRateOverlay != nullptr); + switch (n = data.readInt32()) { + case 0: + case 1: + enableRefreshRateOverlay(static_cast(n)); + break; + default: { + Mutex::Autolock lock(mStateLock); + reply->writeBool(mRefreshRateOverlay != nullptr); + } } return NO_ERROR; } @@ -5285,29 +5281,26 @@ void SurfaceFlinger::repaintEverythingForHWC() { void SurfaceFlinger::kernelTimerChanged(bool expired) { static bool updateOverlay = property_get_bool("debug.sf.kernel_idle_timer_update_overlay", true); - if (!updateOverlay || !mRefreshRateOverlay) return; + if (!updateOverlay) return; + if (Mutex::Autolock lock(mStateLock); !mRefreshRateOverlay) return; // Update the overlay on the main thread to avoid race conditions with // mRefreshRateConfigs->getCurrentRefreshRate() - static_cast(schedule([=]() NO_THREAD_SAFETY_ANALYSIS { - if (mRefreshRateOverlay) { + static_cast(schedule([=] { + const auto desiredActiveConfig = getDesiredActiveConfig(); + const auto& current = desiredActiveConfig + ? mRefreshRateConfigs->getRefreshRateFromConfigId(desiredActiveConfig->configId) + : mRefreshRateConfigs->getCurrentRefreshRate(); + const auto& min = mRefreshRateConfigs->getMinRefreshRate(); + + if (current != min) { const auto kernelTimerEnabled = property_get_bool(KERNEL_IDLE_TIMER_PROP, false); const bool timerExpired = kernelTimerEnabled && expired; - const auto& current = [this]() -> const RefreshRate& { - std::lock_guard lock(mActiveConfigLock); - if (mDesiredActiveConfigChanged) { - return mRefreshRateConfigs->getRefreshRateFromConfigId( - mDesiredActiveConfig.configId); - } - - return mRefreshRateConfigs->getCurrentRefreshRate(); - }(); - const auto& min = mRefreshRateConfigs->getMinRefreshRate(); - if (current != min) { + if (Mutex::Autolock lock(mStateLock); mRefreshRateOverlay) { mRefreshRateOverlay->changeRefreshRate(timerExpired ? min : current); - mEventQueue->invalidate(); } + mEventQueue->invalidate(); } })); } @@ -6224,6 +6217,29 @@ void SurfaceFlinger::onFrameRateFlexibilityTokenReleased() { })); } +void SurfaceFlinger::enableRefreshRateOverlay(bool enable) { + static_cast(schedule([=] { + std::unique_ptr overlay; + if (enable) { + overlay = std::make_unique(*this); + } + + { + Mutex::Autolock lock(mStateLock); + + // Destroy the layer of the current overlay, if any, outside the lock. + mRefreshRateOverlay.swap(overlay); + if (!mRefreshRateOverlay) return; + + if (const auto display = getDefaultDisplayDeviceLocked()) { + mRefreshRateOverlay->setViewport(display->getSize()); + } + + mRefreshRateOverlay->changeRefreshRate(mRefreshRateConfigs->getCurrentRefreshRate()); + } + })); +} + } // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index f3984ed8d4..715d5f78ea 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -829,13 +829,13 @@ private: const DisplayDeviceState& state, const sp& displaySurface, const sp& producer); - void processDisplayChangesLocked(); + void processDisplayChangesLocked() REQUIRES(mStateLock); void processDisplayAdded(const wp& displayToken, const DisplayDeviceState& state); void processDisplayRemoved(const wp& displayToken); void processDisplayChanged(const wp& displayToken, const DisplayDeviceState& currentState, - const DisplayDeviceState& drawingState); - void processDisplayHotplugEventsLocked(); + const DisplayDeviceState& drawingState) REQUIRES(mStateLock); + void processDisplayHotplugEventsLocked() REQUIRES(mStateLock); void dispatchDisplayHotplugEvent(PhysicalDisplayId displayId, bool connected); @@ -1216,6 +1216,12 @@ private: * Misc */ + std::optional getDesiredActiveConfig() EXCLUDES(mActiveConfigLock) { + std::lock_guard lock(mActiveConfigLock); + if (mDesiredActiveConfigChanged) return mDesiredActiveConfig; + return std::nullopt; + } + std::mutex mActiveConfigLock; // This bit is set once we start setting the config. We read from this bit during the // process. If at the end, this bit is different than mDesiredActiveConfig, we restart @@ -1258,7 +1264,8 @@ private: // This should only be accessed on the main thread. nsecs_t mFrameStartTime = 0; - std::unique_ptr mRefreshRateOverlay; + void enableRefreshRateOverlay(bool enable); + std::unique_ptr mRefreshRateOverlay GUARDED_BY(mStateLock); // Flag used to set override allowed display configs from backdoor bool mDebugDisplayConfigSetByBackdoor = false; -- cgit v1.2.3-59-g8ed1b